---
title: "Partially update project automation"
method: PATCH
path: "/v1/project_automation/{project_automation_id}"
tags: ["ProjectAutomations"]
---

# Partially update project automation

`PATCH /v1/project_automation/{project_automation_id}`

## Request

- Base URL: `https://api.braintrust.dev`
- URL: `https://api.braintrust.dev/v1/project_automation/{project_automation_id}`
- Auth: one of:
  - HTTP bearer
  - none

Partially update a project automation object. Specify the fields to update in the payload. Any object-type fields will be deep-merged with existing content. Currently we do not support removing fields or setting them to null.

## Path parameters

- `project_automation_id` string, uuid, required: ProjectAutomation id

## Request body

- PatchProjectAutomation
  - `name` string, nullable: Name of the project automation
  - `description` string, nullable: Textual description of the project automation
  - `config` union: The configuration for the automation rule
    - object
      - `event_type` 'logs', required: The type of automation.
      - `status` 'active' | 'paused': Whether the automation is active or paused.
      - `btql_filter` string, required: BTQL filter to identify rows for the automation rule
      - `interval_seconds` number, required: Perform the triggered action at most once in this interval of seconds
      - `action` union, required: The action to take when the automation rule is triggered
        - object
          - `type` 'webhook', required: The type of action to take
          - `url` string, required: The webhook URL to send the request to
          - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
        - object
          - `type` 'slack', required: The type of action to take
          - `workspace_id` string, required: The Slack workspace ID to post to
          - `channel` string, required: The Slack channel ID to post to
          - `message_template` string: Custom message template for the alert
          - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
        - object
          - `type` 'pagerduty', required: The type of action to take
          - `routing_key_secret_name` string, uuid, required: The data-plane secret containing the PagerDuty routing key
          - `severity` 'critical' | 'error' | 'warning' | 'info', required
          - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
    - object
      - `event_type` 'btql_export', required: The type of automation.
      - `status` 'active' | 'paused': Whether the automation is active or paused.
      - `export_definition` union, required: The definition of what to export
        - object
          - `type` 'log_traces', required
        - object
          - `type` 'log_spans', required
        - object
          - `type` 'btql_query', required
          - `btql_query` string, required: The BTQL query to export
      - `scope` union: Execution scope for export automation. Defaults to span-level execution.
        - SpanScope: Process individual spans
          - `type` 'span', required
        - TraceScope: Process entire traces (all spans sharing the same root_span_id)
          - `type` 'trace', required
          - `idle_seconds` number: Consider trace complete after this many seconds of inactivity (default: 30)
        - GroupScope: Process spans/traces grouped by a field (e.g., session_id)
          - `type` 'group', required
          - `group_by` string, required: Field path to group by, e.g. metadata.session_id
          - `interval_seconds` number: Maximum time range to include when constructing a group
          - `max_traces` integer: Maximum number of traces to include when constructing a group (default/max: 64)
          - `placement` 'first' | 'each', required: Which trace or traces to write grouped scorer results to
          - `idle_seconds` number: Optional: trigger after this many seconds of inactivity
      - `export_path` string, required: The path to export the results to. It should include the storage protocol and prefix, e.g. s3://bucket-name/path/to/export
      - `format` 'jsonl' | 'parquet', required: The format to export the results in
      - `interval_seconds` number, required: Perform the triggered action at most once in this interval of seconds
      - `credentials` union, required
        - object
          - `type` 'aws_iam', required
          - `role_arn` string, required: The ARN of the IAM role to use
          - `external_id` string, required: The automation-specific external id component (auto-generated by default)
        - object
          - `type` 'gcp_service_account', required
          - `service_account_email` string, required: The GCP service account email to impersonate
          - `credential_name` string: The name of a Google workload identity federation credential configured in this organization's AI providers. Supported data planes can use it regardless of hosting environment. If omitted, the data plane's GCP identity is used.
      - `batch_size` number, nullable: The number of rows to export in each batch
    - object
      - `event_type` 'async_query', required: The type of automation.
      - `status` 'active' | 'paused': Whether the automation is active or paused.
      - `created_by_user_id` string, uuid, required: The user who submitted the async query
      - `object_type` 'project_logs' | 'experiment' | 'dataset' | 'playground_logs', required: The source object type for the async query
      - `object_id` string, required: The source object ID for the async query
      - `query` string, required: The SQL query to execute asynchronously
      - `format` 'jsonl', required: The materialized result format
      - `batch_size` integer, nullable: The maximum number of result rows to write per async query batch
    - object
      - `event_type` 'retention', required: The type of automation.
      - `object_type` 'project_logs' | 'experiment' | 'dataset', required: The object type that the retention policy applies to
      - `retention_days` integer, required: The number of days to retain the object
    - object
      - `event_type` 'environment_update', required: The type of automation.
      - `status` 'active' | 'paused': Whether the automation is active or paused.
      - `environment_filter` string[]: Optional list of environment slugs to filter by
      - `action` union, required: The action to take when the automation rule is triggered
        - object
          - `type` 'webhook', required: The type of action to take
          - `url` string, required: The webhook URL to send the request to
          - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
        - object
          - `type` 'slack', required: The type of action to take
          - `workspace_id` string, required: The Slack workspace ID to post to
          - `channel` string, required: The Slack channel ID to post to
          - `message_template` string: Custom message template for the alert
          - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
        - object
          - `type` 'pagerduty', required: The type of action to take
          - `routing_key_secret_name` string, uuid, required: The data-plane secret containing the PagerDuty routing key
          - `severity` 'critical' | 'error' | 'warning' | 'info', required
          - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
    - WindowedAutomationConfig
      - `event_type` 'windowed', required: The type of automation.
      - `product_origin` 'patterns' | 'dashboard' | 'null', nullable: The product surface that created and manages the automation
      - `status` 'active' | 'paused': Whether the automation is active or paused.
      - `continuous` boolean: Between scheduled runs, check for accumulated new work. The executor decides how to process it.
      - `threshold` object: Optional calculation and lifecycle policy that gate scheduled delivery
        - `calculation` object, required: The calculation evaluated for each window
          - `type` 'btql', required
          - `btql_query` string, required: A project-scoped BTQL or SQL query without runtime-owned evaluation time bounds
          - `output` object, required
            - `type` 'scalar', required
            - `value_column` string, required: The numeric result column produced by the query
        - `policy` object, required: The lifecycle policy applied to each calculation result
          - `condition` object, required
            - `type` 'threshold', required
            - `operator` 'lt' | 'lte' | 'gt' | 'gte' | 'eq' | 'neq', required
            - `threshold` number, required
          - `pending_seconds` integer, required: How long the condition must remain breached before firing
          - `no_data_behavior` 'keep_last' | 'resolve' | 'alert', required: How the lifecycle changes when the calculation returns no data
          - `renotify_interval_seconds` integer, nullable: Optional reminder interval while the automation is firing
          - `notify_on_recovery` boolean: Whether to deliver actions when a firing automation recovers
      - `window` object, required
        - `window_seconds` integer, required: How much recent data each scheduled run covers
        - `schedule` union, required: How often the windowed automation runs: at a fixed interval or on a cron schedule
          - object
            - `type` 'interval', required
            - `evaluation_interval_seconds` integer, required: How often the automation runs
          - object
            - `type` 'cron', required
            - `cron_expression` string, required: A standard five-field cron expression (minute hour day-of-month month day-of-week) controlling when the automation runs
            - `timezone` string, nullable: IANA timezone used to interpret the cron expression (defaults to UTC)
        - `evaluation_delay_seconds` integer, required: How far behind the present each evaluation window ends
      - `loop` object: Optional Loop agent to run for each triggered window
        - `prompt` string, required: Instructions for the Loop agent
        - `include_trigger_input` boolean: Whether to include the automation trigger payload as input
        - `agent_slug` string, required: The Loop agent to run
        - `auto_approve_tools` string[]: Write tools that may run without interactive approval
        - `harness` 'native' | 'codex' | 'claude-code' | 'pi': Required for an explicit model selection. Currently only Codex is supported.
        - `model` string: Omit harness, model, and endpoint_name to inherit the organization default provider and its recommended execution settings.
        - `endpoint_name` string
        - `reasoning_effort` 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max'
        - `target` object: The object this automation writes to or maintains
          - `type` 'dashboard', required
          - `id` union, required
            - string, uuid
            - 'overview'
      - `actions` union[]: Delivery actions exposed to Loop as tools, or run directly when Loop is not configured
        - union: A delivery action available to an automation
          - object
            - `type` 'webhook', required: The type of action to take
            - `url` string, required: The webhook URL to send the request to
            - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
          - object
            - `type` 'slack', required: The type of action to take
            - `workspace_id` string, required: The Slack workspace ID to post to
            - `channel` string, required: The Slack channel ID to post to
            - `message_template` string: Custom message template for the alert
            - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
          - object
            - `type` 'pagerduty', required: The type of action to take
            - `routing_key_secret_name` string, uuid, required: The data-plane secret containing the PagerDuty routing key
            - `severity` 'critical' | 'error' | 'warning' | 'info', required
            - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
    - TopicAutomationConfig
      - `event_type` 'topic', required: The type of automation.
      - `status` 'active' | 'paused': Whether the automation is active or paused.
      - `sampling_rate` number, required: The sampling rate for topic automation
      - `facet_model` 'brain-facet-latest' | 'brain-facet-1' | 'brain-facet-2' | 'null', nullable: Optional facet model override for topic automation
      - `facet_functions` union[], required: Facet functions used by the topic automation
        - union
          - object
            - `type` 'function', required
            - `id` string, required
            - `version` string: The version of the function
          - object
            - `type` 'global', required
            - `name` string, required
            - `function_type` 'llm' | 'scorer' | 'task' | 'tool' | 'custom_view' | 'preprocessor' | 'facet' | 'classifier' | 'tag' | 'parameters' | 'sandbox': The type of global function. Defaults to 'scorer'.
      - `topic_map_functions` TopicMapFunctionAutomation[], required: Topic map functions with optional per-topic-map filters
        - `function` union, required
          - object
            - `type` 'function', required
            - `id` string, required
            - `version` string: The version of the function
          - object
            - `type` 'global', required
            - `name` string, required
            - `function_type` 'llm' | 'scorer' | 'task' | 'tool' | 'custom_view' | 'preprocessor' | 'facet' | 'classifier' | 'tag' | 'parameters' | 'sandbox': The type of global function. Defaults to 'scorer'.
        - `btql_filter` string, nullable: Per-topic-map BTQL filter. For trace scope, a topic map runs when max(filter) over the trace is truthy. For span scope, it runs when the current span matches.
      - `scope` union: Execution scope for topic automation.
        - SpanScope: Process individual spans
          - `type` 'span', required
        - TraceScope: Process entire traces (all spans sharing the same root_span_id)
          - `type` 'trace', required
          - `idle_seconds` number: Consider trace complete after this many seconds of inactivity (default: 30)
        - GroupScope: Process spans/traces grouped by a field (e.g., session_id)
          - `type` 'group', required
          - `group_by` string, required: Field path to group by, e.g. metadata.session_id
          - `interval_seconds` number: Maximum time range to include when constructing a group
          - `max_traces` integer: Maximum number of traces to include when constructing a group (default/max: 64)
          - `placement` 'first' | 'each', required: Which trace or traces to write grouped scorer results to
          - `idle_seconds` number: Optional: trigger after this many seconds of inactivity
      - `data_scope` union: Optional data scope for topic automation.
        - object
          - `type` 'project_logs', required
        - object
          - `type` 'project_experiments', required
        - object
          - `type` 'experiment', required
          - `experiment_id` string, required
      - `btql_filter` string, nullable: Optional BTQL filter applied before topic automation.
      - `rerun_seconds` number, nullable: How often to recompute topic maps
      - `relabel_overlap_seconds` number, nullable: Deprecated. How much recent history to relabel after a new topic map version becomes active. Data planes v2.15.0 and later ignore this and apply a topic map version after the first only to traces classified once it is active.
      - `backfill_time_range` union: Topic window used for classification coverage and initial backfill.
        - string
        - object
          - `from` string, required
          - `to` string, required
    - TopicDigestAutomationConfig
      - `event_type` 'topic_digest', required: The type of automation.
      - `status` 'active' | 'paused': Whether the automation is active or paused.
      - `window_seconds` integer: How much recent history to include in each digest
      - `scheduled_time_minutes_utc` integer, required: Minutes after midnight UTC when the digest should be sent
      - `action` object, required: The Slack action to take when the digest is sent
        - `type` 'slack', required: The type of action to take
        - `workspace_id` string, required: The Slack workspace ID to post to
        - `channel` string, required: The Slack channel ID to post to
        - `message_template` string: Custom message template for the alert
        - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
      - `topic_map_function_ids` string[]: Optional topic map function IDs to include in the digest

## Response `200`

Returns the project automation object

- ProjectAutomation
  - `id` string, uuid, required: Unique identifier for the project automation
  - `project_id` string, uuid, required: Unique identifier for the project that the project automation belongs under
  - `user_id` string, uuid, nullable: Identifies the user who created the project automation
  - `created` string, date-time, nullable: Date of project automation creation
  - `name` string, required: Name of the project automation
  - `description` string, nullable: Textual description of the project automation
  - `config` union, required: The configuration for the automation rule
    - object
      - `event_type` 'logs', required: The type of automation.
      - `status` 'active' | 'paused': Whether the automation is active or paused.
      - `btql_filter` string, required: BTQL filter to identify rows for the automation rule
      - `interval_seconds` number, required: Perform the triggered action at most once in this interval of seconds
      - `action` union, required: The action to take when the automation rule is triggered
        - object
          - `type` 'webhook', required: The type of action to take
          - `url` string, required: The webhook URL to send the request to
          - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
        - object
          - `type` 'slack', required: The type of action to take
          - `workspace_id` string, required: The Slack workspace ID to post to
          - `channel` string, required: The Slack channel ID to post to
          - `message_template` string: Custom message template for the alert
          - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
        - object
          - `type` 'pagerduty', required: The type of action to take
          - `routing_key_secret_name` string, uuid, required: The data-plane secret containing the PagerDuty routing key
          - `severity` 'critical' | 'error' | 'warning' | 'info', required
          - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
    - object
      - `event_type` 'btql_export', required: The type of automation.
      - `status` 'active' | 'paused': Whether the automation is active or paused.
      - `export_definition` union, required: The definition of what to export
        - object
          - `type` 'log_traces', required
        - object
          - `type` 'log_spans', required
        - object
          - `type` 'btql_query', required
          - `btql_query` string, required: The BTQL query to export
      - `scope` union: Execution scope for export automation. Defaults to span-level execution.
        - SpanScope: Process individual spans
          - `type` 'span', required
        - TraceScope: Process entire traces (all spans sharing the same root_span_id)
          - `type` 'trace', required
          - `idle_seconds` number: Consider trace complete after this many seconds of inactivity (default: 30)
        - GroupScope: Process spans/traces grouped by a field (e.g., session_id)
          - `type` 'group', required
          - `group_by` string, required: Field path to group by, e.g. metadata.session_id
          - `interval_seconds` number: Maximum time range to include when constructing a group
          - `max_traces` integer: Maximum number of traces to include when constructing a group (default/max: 64)
          - `placement` 'first' | 'each', required: Which trace or traces to write grouped scorer results to
          - `idle_seconds` number: Optional: trigger after this many seconds of inactivity
      - `export_path` string, required: The path to export the results to. It should include the storage protocol and prefix, e.g. s3://bucket-name/path/to/export
      - `format` 'jsonl' | 'parquet', required: The format to export the results in
      - `interval_seconds` number, required: Perform the triggered action at most once in this interval of seconds
      - `credentials` union, required
        - object
          - `type` 'aws_iam', required
          - `role_arn` string, required: The ARN of the IAM role to use
          - `external_id` string, required: The automation-specific external id component (auto-generated by default)
        - object
          - `type` 'gcp_service_account', required
          - `service_account_email` string, required: The GCP service account email to impersonate
          - `credential_name` string: The name of a Google workload identity federation credential configured in this organization's AI providers. Supported data planes can use it regardless of hosting environment. If omitted, the data plane's GCP identity is used.
      - `batch_size` number, nullable: The number of rows to export in each batch
    - object
      - `event_type` 'async_query', required: The type of automation.
      - `status` 'active' | 'paused': Whether the automation is active or paused.
      - `created_by_user_id` string, uuid, required: The user who submitted the async query
      - `object_type` 'project_logs' | 'experiment' | 'dataset' | 'playground_logs', required: The source object type for the async query
      - `object_id` string, required: The source object ID for the async query
      - `query` string, required: The SQL query to execute asynchronously
      - `format` 'jsonl', required: The materialized result format
      - `batch_size` integer, nullable: The maximum number of result rows to write per async query batch
    - object
      - `event_type` 'retention', required: The type of automation.
      - `object_type` 'project_logs' | 'experiment' | 'dataset', required: The object type that the retention policy applies to
      - `retention_days` integer, required: The number of days to retain the object
    - object
      - `event_type` 'environment_update', required: The type of automation.
      - `status` 'active' | 'paused': Whether the automation is active or paused.
      - `environment_filter` string[]: Optional list of environment slugs to filter by
      - `action` union, required: The action to take when the automation rule is triggered
        - object
          - `type` 'webhook', required: The type of action to take
          - `url` string, required: The webhook URL to send the request to
          - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
        - object
          - `type` 'slack', required: The type of action to take
          - `workspace_id` string, required: The Slack workspace ID to post to
          - `channel` string, required: The Slack channel ID to post to
          - `message_template` string: Custom message template for the alert
          - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
        - object
          - `type` 'pagerduty', required: The type of action to take
          - `routing_key_secret_name` string, uuid, required: The data-plane secret containing the PagerDuty routing key
          - `severity` 'critical' | 'error' | 'warning' | 'info', required
          - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
    - WindowedAutomationConfig
      - `event_type` 'windowed', required: The type of automation.
      - `product_origin` 'patterns' | 'dashboard' | 'null', nullable: The product surface that created and manages the automation
      - `status` 'active' | 'paused': Whether the automation is active or paused.
      - `continuous` boolean: Between scheduled runs, check for accumulated new work. The executor decides how to process it.
      - `threshold` object: Optional calculation and lifecycle policy that gate scheduled delivery
        - `calculation` object, required: The calculation evaluated for each window
          - `type` 'btql', required
          - `btql_query` string, required: A project-scoped BTQL or SQL query without runtime-owned evaluation time bounds
          - `output` object, required
            - `type` 'scalar', required
            - `value_column` string, required: The numeric result column produced by the query
        - `policy` object, required: The lifecycle policy applied to each calculation result
          - `condition` object, required
            - `type` 'threshold', required
            - `operator` 'lt' | 'lte' | 'gt' | 'gte' | 'eq' | 'neq', required
            - `threshold` number, required
          - `pending_seconds` integer, required: How long the condition must remain breached before firing
          - `no_data_behavior` 'keep_last' | 'resolve' | 'alert', required: How the lifecycle changes when the calculation returns no data
          - `renotify_interval_seconds` integer, nullable: Optional reminder interval while the automation is firing
          - `notify_on_recovery` boolean: Whether to deliver actions when a firing automation recovers
      - `window` object, required
        - `window_seconds` integer, required: How much recent data each scheduled run covers
        - `schedule` union, required: How often the windowed automation runs: at a fixed interval or on a cron schedule
          - object
            - `type` 'interval', required
            - `evaluation_interval_seconds` integer, required: How often the automation runs
          - object
            - `type` 'cron', required
            - `cron_expression` string, required: A standard five-field cron expression (minute hour day-of-month month day-of-week) controlling when the automation runs
            - `timezone` string, nullable: IANA timezone used to interpret the cron expression (defaults to UTC)
        - `evaluation_delay_seconds` integer, required: How far behind the present each evaluation window ends
      - `loop` object: Optional Loop agent to run for each triggered window
        - `prompt` string, required: Instructions for the Loop agent
        - `include_trigger_input` boolean: Whether to include the automation trigger payload as input
        - `agent_slug` string, required: The Loop agent to run
        - `auto_approve_tools` string[]: Write tools that may run without interactive approval
        - `harness` 'native' | 'codex' | 'claude-code' | 'pi': Required for an explicit model selection. Currently only Codex is supported.
        - `model` string: Omit harness, model, and endpoint_name to inherit the organization default provider and its recommended execution settings.
        - `endpoint_name` string
        - `reasoning_effort` 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max'
        - `target` object: The object this automation writes to or maintains
          - `type` 'dashboard', required
          - `id` union, required
            - string, uuid
            - 'overview'
      - `actions` union[]: Delivery actions exposed to Loop as tools, or run directly when Loop is not configured
        - union: A delivery action available to an automation
          - object
            - `type` 'webhook', required: The type of action to take
            - `url` string, required: The webhook URL to send the request to
            - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
          - object
            - `type` 'slack', required: The type of action to take
            - `workspace_id` string, required: The Slack workspace ID to post to
            - `channel` string, required: The Slack channel ID to post to
            - `message_template` string: Custom message template for the alert
            - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
          - object
            - `type` 'pagerduty', required: The type of action to take
            - `routing_key_secret_name` string, uuid, required: The data-plane secret containing the PagerDuty routing key
            - `severity` 'critical' | 'error' | 'warning' | 'info', required
            - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
    - TopicAutomationConfig
      - `event_type` 'topic', required: The type of automation.
      - `status` 'active' | 'paused': Whether the automation is active or paused.
      - `sampling_rate` number, required: The sampling rate for topic automation
      - `facet_model` 'brain-facet-latest' | 'brain-facet-1' | 'brain-facet-2' | 'null', nullable: Optional facet model override for topic automation
      - `facet_functions` union[], required: Facet functions used by the topic automation
        - union
          - object
            - `type` 'function', required
            - `id` string, required
            - `version` string: The version of the function
          - object
            - `type` 'global', required
            - `name` string, required
            - `function_type` 'llm' | 'scorer' | 'task' | 'tool' | 'custom_view' | 'preprocessor' | 'facet' | 'classifier' | 'tag' | 'parameters' | 'sandbox': The type of global function. Defaults to 'scorer'.
      - `topic_map_functions` TopicMapFunctionAutomation[], required: Topic map functions with optional per-topic-map filters
        - `function` union, required
          - object
            - `type` 'function', required
            - `id` string, required
            - `version` string: The version of the function
          - object
            - `type` 'global', required
            - `name` string, required
            - `function_type` 'llm' | 'scorer' | 'task' | 'tool' | 'custom_view' | 'preprocessor' | 'facet' | 'classifier' | 'tag' | 'parameters' | 'sandbox': The type of global function. Defaults to 'scorer'.
        - `btql_filter` string, nullable: Per-topic-map BTQL filter. For trace scope, a topic map runs when max(filter) over the trace is truthy. For span scope, it runs when the current span matches.
      - `scope` union: Execution scope for topic automation.
        - SpanScope: Process individual spans
          - `type` 'span', required
        - TraceScope: Process entire traces (all spans sharing the same root_span_id)
          - `type` 'trace', required
          - `idle_seconds` number: Consider trace complete after this many seconds of inactivity (default: 30)
        - GroupScope: Process spans/traces grouped by a field (e.g., session_id)
          - `type` 'group', required
          - `group_by` string, required: Field path to group by, e.g. metadata.session_id
          - `interval_seconds` number: Maximum time range to include when constructing a group
          - `max_traces` integer: Maximum number of traces to include when constructing a group (default/max: 64)
          - `placement` 'first' | 'each', required: Which trace or traces to write grouped scorer results to
          - `idle_seconds` number: Optional: trigger after this many seconds of inactivity
      - `data_scope` union: Optional data scope for topic automation.
        - object
          - `type` 'project_logs', required
        - object
          - `type` 'project_experiments', required
        - object
          - `type` 'experiment', required
          - `experiment_id` string, required
      - `btql_filter` string, nullable: Optional BTQL filter applied before topic automation.
      - `rerun_seconds` number, nullable: How often to recompute topic maps
      - `relabel_overlap_seconds` number, nullable: Deprecated. How much recent history to relabel after a new topic map version becomes active. Data planes v2.15.0 and later ignore this and apply a topic map version after the first only to traces classified once it is active.
      - `backfill_time_range` union: Topic window used for classification coverage and initial backfill.
        - string
        - object
          - `from` string, required
          - `to` string, required
    - TopicDigestAutomationConfig
      - `event_type` 'topic_digest', required: The type of automation.
      - `status` 'active' | 'paused': Whether the automation is active or paused.
      - `window_seconds` integer: How much recent history to include in each digest
      - `scheduled_time_minutes_utc` integer, required: Minutes after midnight UTC when the digest should be sent
      - `action` object, required: The Slack action to take when the digest is sent
        - `type` 'slack', required: The type of action to take
        - `workspace_id` string, required: The Slack workspace ID to post to
        - `channel` string, required: The Slack channel ID to post to
        - `message_template` string: Custom message template for the alert
        - `formatting_prompt` string: Instructions for Loop to format content sent to this destination
      - `topic_map_function_ids` string[]: Optional topic map function IDs to include in the digest
  - `runtime_block` object
    - `reason` string, required
    - `model` string, required

## Other responses

- `400`: The request was unacceptable, often due to missing a required parameter
- `401`: No valid API key provided
- `403`: The API key doesn’t have permissions to perform the request
- `429`: Too many requests hit the API too quickly. We recommend an exponential backoff of your requests
- `500`: Something went wrong on Braintrust's end. (These are rare.)

## Changes

- **2026-10-30** `8f5039399f77`: 16 breaking, 6 info
  - the request property `config/oneOf[#/components/schemas/TopicAutomationConfig]/btql_filter` became not nullable
  - the request property `config/oneOf[#/components/schemas/TopicAutomationConfig]/facet_model` became not nullable
  - the request property `config/oneOf[#/components/schemas/TopicAutomationConfig]/relabel_overlap_seconds` became not nullable
  - the request property `config/oneOf[#/components/schemas/TopicAutomationConfig]/rerun_seconds` became not nullable
  - …18 more
- **2026-10-29** `6409b3f2bde5`: 2 breaking, 2 info
  - removed `subschema #1, subschema #5` from the `config` request property `oneOf` list
  - added `subschema #1, subschema #5` to the `config` response property `oneOf` list for the response status `200`
  - added `subschema #1, subschema #5` to the `config` request property `oneOf` list
  - removed `subschema #1, subschema #5` from the `config` response property `oneOf` list for the response status `200`
- **2026-10-22** `0426dee78e5b`: 2 info
  - added the new optional request property `config/oneOf[#/components/schemas/WindowedAutomationConfig]/continuous`
  - added the optional property `config/oneOf[#/components/schemas/WindowedAutomationConfig]/continuous` to the response with the `200` status
- …earlier changes not shown

[Operation history](https://skmtc.dev/braintrustdata/apis/braintrust-api/changes/v1/project_automation/:project_automation_id/patch.md)

---

[API](https://skmtc.dev/braintrustdata/apis/braintrust-api.md) - [All operations](https://skmtc.dev/braintrustdata/apis/braintrust-api/llms.txt) - [OpenAPI document](https://skmtc.dev/braintrustdata/apis/braintrust-api/revisions/19184ec94018?raw)
