BrowserStack AI Evals
Evaluation

Automation Rules

Create, list, update, pause, resume, and delete automation rules from the SDK across TypeScript, Python, Java, and Go.

Automation Rules

Automation rules watch your traces (or sessions) and, when one matches, run one or more actions on it — score it with an evaluator list (ONLINE_EVAL), add it to a dataset (DATASET), or both.

The CLASSIFIER action type shown in the dashboard is not available on the public API yet. Sending a rule with type: "CLASSIFIER" returns 400. Support is planned for a future version.

Setup

Put your public and secret keys in your environment, then create one client and reuse it for every call on this page.

import { AISDK } from '@browserstack/ai-sdk';const publicKey = process.env.AISDK_PUBLIC_KEY!;const secretKey = process.env.AISDK_SECRET_KEY!;const client = new AISDK({  publicKey,  secretKey,});

The AutomationRule shape

Every method below (except delete) returns an AutomationRule. Here's what's in it:

FieldTypeDefaultDescription
idstringserverServer-generated rule id.
projectIdstringserverFilled in from your API-key scope.
namestringrequiredMust be unique within the project (409 if a rule with the same name already exists).
descriptionstring | nullnullOptional free-form description.
sourceType"TRACE" | "SESSION""TRACE"You can't change this after creating the rule.
samplingRate1..100100Percent of matched objects the rule actually fires on.
status"ACTIVE" | "PAUSED""ACTIVE"Whether the rule is running.
targetingFiltersTargetingFilter[][]Conditions a trace or session must meet to match.
actionsAutomationRuleAction[]required1 or 2 actions. At most one ONLINE_EVAL and one DATASET.
createdBystring | nullserverThe user or API key that created the rule.
createdAt / updatedAtDateserverISO 8601 timestamps.

Create a rule

const rule = await client.automationRules.create({  name,  description: 'SDK CRUD test rule',  sourceType: 'TRACE',  samplingRate: 50,  status: 'ACTIVE',  targetingFilters: [    {      fieldName: 'name',      operator: 'EQUALS',      value: 'sdk-test-trace',      logicalOperator: 'AND',    },  ],  actions: [    {      type: 'ONLINE_EVAL',      config: { concurrency: 2, delaySeconds: 30, eventName: null },      metrics: [{ evaluatorListId: evaluatorListId!, routeToHumanReview: false }],    },    {      type: 'DATASET',      config: {        datasetId,        mappingType: 'EXPECTED_OUTPUT',        extractionMode: 'SINGLE_IO',        datasetTag: null,        outputObservationName: null,      },    },  ],});

Creates the rule, its actions, and its targeting filters in a single call. You need at least one action, and each action type can appear at most once.

ParamTypeRequiredDescription
namestringtrueA name for the rule, 1–255 characters. Must be unique within the project.
descriptionstring | nullfalseOptional free-form description.
sourceTypeEventSchedulerTypefalseWhether the rule watches traces or sessions. Defaults to `TRACE`.
samplingRatenumberfalsePercent of matching traces the rule fires on (1–100). Useful for sampling high-volume traffic.
Default: 100
statusAutomationRuleStatusfalseThe starting status. Set to `PAUSED` if you want the rule created but not running yet.
Default: "ACTIVE"
targetingFiltersTargetingFilter[]falseThe conditions a trace must meet to match. Leave empty to fire on every trace.
Default: []
targetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
actionsAutomationRuleActionInput[]trueOne or two actions to run when the rule fires — for example, score the trace or add it to a dataset.
ParamTypeRequiredDescription
namestrtrueA name for the rule, 1–255 characters. Must be unique within the project.
descriptionOptional[str]falseOptional free-form description.
source_typeOptional[EventSchedulerType]falseWhether the rule watches traces or sessions. Defaults to `TRACE`.
sampling_rateOptional[int]falsePercent of matching traces the rule fires on (1–100). Useful for sampling high-volume traffic.
Default: 100
statusOptional[object]falseThe starting status. Set to `PAUSED` if you want the rule created but not running yet.
Default: "ACTIVE"
targeting_filtersOptional[list[TargetingFilterInput]]falseThe conditions a trace must meet to match. Leave empty to fire on every trace.
Default: []
targeting_filters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targeting_filters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targeting_filters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targeting_filters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
actionslist[AutomationRuleActionInput]trueOne or two actions to run when the rule fires — for example, score the trace or add it to a dataset.
ParamTypeRequiredDescription
nameStringtrueA name for the rule, 1–255 characters. Must be unique within the project.
descriptionStringfalseOptional free-form description.
sourceTypeEventSchedulerTypefalseWhether the rule watches traces or sessions. Defaults to `TRACE`.
samplingRateIntegerfalsePercent of matching traces the rule fires on (1–100). Useful for sampling high-volume traffic.
Default: 100
statusObjectfalseThe starting status. Set to `PAUSED` if you want the rule created but not running yet.
Default: "ACTIVE"
targetingFiltersList<TargetingFilter>falseThe conditions a trace must meet to match. Leave empty to fire on every trace.
Default: []
targetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
actionsList<AutomationRuleActionInput>trueOne or two actions to run when the rule fires — for example, score the trace or add it to a dataset.
ParamTypeRequiredDescription
NamestringtrueA name for the rule, 1–255 characters. Must be unique within the project.
Description*stringfalseOptional free-form description.
SourceType*EventSchedulerTypefalseWhether the rule watches traces or sessions. Defaults to `TRACE`.
SamplingRate*intfalsePercent of matching traces the rule fires on (1–100). Useful for sampling high-volume traffic.
Default: 100
Status*AutomationRuleStatusfalseThe starting status. Set to `PAUSED` if you want the rule created but not running yet.
Default: "ACTIVE"
TargetingFilters*[]TargetingFilterfalseThe conditions a trace must meet to match. Leave empty to fire on every trace.
Default: []
TargetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
TargetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
TargetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
TargetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
Actions[]AutomationRuleActionInputtrueOne or two actions to run when the rule fires — for example, score the trace or add it to a dataset.

List rules

const { data, meta } = await client.automationRules.list({  page: 1,  limit: 50,});

meta contains the pagination fields (page, limit, totalItems, totalPages). Asking for a page past the last one returns data: [] — it's not an error.

Lists the rules in your project, paginated. You can page through results, search by name, and optionally filter to rules with a specific action type.

ParamTypeRequiredDescription
pagenumberfalse1-indexed page number (default 1)
Default: 1
limitnumberfalsePage size, max 100 (default 50)
Default: 50
searchstringfalseSubstring match on name + description (case-insensitive)
actionTypeAutomationRuleActionType
"ONLINE_EVAL" | "DATASET"
falseIf set, only returns rules that have at least one action of this type.
ParamTypeRequiredDescription
pageOptional[int]false1-indexed page number (default 1)
Default: 1
limitOptional[int]falsePage size, max 100 (default 50)
Default: 50
searchOptional[str]falseSubstring match on name + description (case-insensitive)
action_typeOptional[str]
"ONLINE_EVAL", "DATASET"
falseIf set, only returns rules that have at least one action of this type.
ParamTypeRequiredDescription
pageIntegerfalse1-indexed page number (default 1)
Default: 1
limitIntegerfalsePage size, max 100 (default 50)
Default: 50
searchStringfalseSubstring match on name + description (case-insensitive)
actionTypeString
"ONLINE_EVAL", "DATASET"
falseIf set, only returns rules that have at least one action of this type.
ParamTypeRequiredDescription
Page*intfalse1-indexed page number (default 1)
Default: 1
Limit*intfalsePage size, max 100 (default 50)
Default: 50
Search*stringfalseSubstring match on name + description (case-insensitive)
ActionType*string
"ONLINE_EVAL", "DATASET"
falseIf set, only returns rules that have at least one action of this type.

Get a rule by id

const fetched = await client.automationRules.get(ruleId);

Get an automation rule by id

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.

Update a rule

Use this to update rule-level fields like name, description, samplingRate, or targetingFilters. You can't change sourceType. To add or remove actions, use the action-level methods further down; to toggle per-metric routing, use updateAction() since metrics belong to the action, not the rule.

const updated = await client.automationRules.update(ruleId, {  samplingRate: 75,  description: 'updated description',});

Updates the rule. Only the fields you send are changed — anything you leave out stays the same. A few things to know: - You can't change `sourceType`. - To add or remove actions, use the `/actions` endpoints below. To toggle per-metric human-review routing, use `PATCH /actions/{actionId}` (metrics belong to an action, not to the rule). - Pass `description: null` to clear the description. - `targetingFilters`, if you send it, replaces the whole filter list — send the full set you want, not a delta.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
namestringfalseNew rule name.
descriptionstring | nullfalseNew description. Pass `null` to clear it.
samplingRatenumberfalseNew sampling rate (1–100).
statusAutomationRuleStatusfalseNew status — `ACTIVE` or `PAUSED`.
targetingFiltersTargetingFilter[]falseNew targeting filters. Pass an empty array to clear.
targetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
nameOptional[str]falseNew rule name.
descriptionOptional[str]falseNew description. Pass `null` to clear it.
sampling_rateOptional[int]falseNew sampling rate (1–100).
statusOptional[AutomationRuleStatus]falseNew status — `ACTIVE` or `PAUSED`.
targeting_filtersOptional[list[TargetingFilterInput]]falseNew targeting filters. Pass an empty array to clear.
targeting_filters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targeting_filters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targeting_filters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targeting_filters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
nameStringfalseNew rule name.
descriptionStringfalseNew description. Pass `null` to clear it.
samplingRateIntegerfalseNew sampling rate (1–100).
statusAutomationRuleStatusfalseNew status — `ACTIVE` or `PAUSED`.
targetingFiltersList<TargetingFilter>falseNew targeting filters. Pass an empty array to clear.
targetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
Name*stringfalseNew rule name.
Description*stringfalseNew description. Pass `null` to clear it.
SamplingRate*intfalseNew sampling rate (1–100).
Status*AutomationRuleStatusfalseNew status — `ACTIVE` or `PAUSED`.
TargetingFilters*[]TargetingFilterfalseNew targeting filters. Pass an empty array to clear.
TargetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
TargetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
TargetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
TargetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"

Pause and resume

updateStatus() pauses or resumes a rule. It's a convenience shortcut over update() — the effect is the same as calling update(ruleId, { status: 'PAUSED' }) or { status: 'ACTIVE' }, but it reads more clearly at the call site.

const paused = await client.automationRules.updateStatus(  ruleId,  { status: 'PAUSED' },);const resumed = await client.automationRules.updateStatus(  ruleId,  { status: 'ACTIVE' },);

A convenience shortcut for pausing or resuming a rule. Same as `PATCH /automation-rules/{ruleId}` with just `{ status }`, but reads more clearly at the call site.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
statusAutomationRuleStatustrueThe new status — `ACTIVE` or `PAUSED`.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
statusAutomationRuleStatustrueThe new status — `ACTIVE` or `PAUSED`.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
statusAutomationRuleStatustrueThe new status — `ACTIVE` or `PAUSED`.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
StatusAutomationRuleStatustrueThe new status — `ACTIVE` or `PAUSED`.

Delete a rule

Deletes the rule and everything attached to it — actions, metrics, and targeting filters.

const result = await client.automationRules.delete(ruleId);

Deletes the rule and everything attached to it — actions, metrics, and targeting filters. Any evaluation results the rule already produced are kept.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.

Add an action

Add a second action to an existing rule — for example, attach a DATASET action to a rule that already runs ONLINE_EVAL. A rule can hold at most one action of each type, so adding a second ONLINE_EVAL (or DATASET) to a rule that already has one is rejected.

const addedAction = await client.automationRules.addAction(ruleId, {  action: {    type: 'DATASET',    config: {      datasetId,      mappingType: 'LLM_OUTPUT',      extractionMode: 'SINGLE_IO',    },  },});

Returns the full updated rule, so you don't need a follow-up get().

Adds one action to an existing rule. Pass the action as a nested `action` object — the same shape as an entry in `actions[]` when you create a rule. A rule can hold at most one action of each type, so adding a second action of the same type returns `409`.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionAutomationRuleActionInputtrueThe action to add. A rule can hold up to two actions.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
actionAutomationRuleActionInputtrueThe action to add. A rule can hold up to two actions.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
actionAutomationRuleActionInputtrueThe action to add. A rule can hold up to two actions.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
ActionAutomationRuleActionInputtrueThe action to add. A rule can hold up to two actions.

Update an action

Update an action's config in place. For ONLINE_EVAL actions, you can optionally pass a metrics array to flip routeToHumanReview on individual evaluators (up to 50 per call).

const updatedAction = await client.automationRules.updateAction(  ruleId,  actionId,  {    action: {      type: 'ONLINE_EVAL',      config: {        concurrency: 8,        delaySeconds: 120,        eventName: null,      },    },  },);

Updates the action's `config` in place. For `ONLINE_EVAL` actions you can also pass a `metrics` list to flip `routeToHumanReview` per metric — this endpoint is the only way to change those toggles.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionIdstringtrueThe action's id (returned in `actions[].id` on the rule).
actionAutomationRuleActionUpdateInputtrueThe fields to update on the action. Anything you leave out stays the same.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
action_idstrtrueThe action's id (returned in `actions[].id` on the rule).
actionAutomationRuleActionUpdateInputtrueThe fields to update on the action. Anything you leave out stays the same.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
actionIdStringtrueThe action's id (returned in `actions[].id` on the rule).
actionAutomationRuleActionUpdateInputtrueThe fields to update on the action. Anything you leave out stays the same.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionIdstringtrueThe action's id (returned in `actions[].id` on the rule).
ActionAutomationRuleActionUpdateInputtrueThe fields to update on the action. Anything you leave out stays the same.

Delete an action

A rule always needs at least one action, so deleting the last remaining action returns 400. Delete the whole rule instead if that's what you want.

const deletedActionResult = await client.automationRules.deleteAction(  ruleId,  actionId,);

A rule always needs at least one action. Deleting the last remaining action returns `409` — delete the whole rule instead.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionIdstringtrueThe action's id (returned in `actions[].id` on the rule).
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
action_idstrtrueThe action's id (returned in `actions[].id` on the rule).
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
actionIdStringtrueThe action's id (returned in `actions[].id` on the rule).
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionIdstringtrueThe action's id (returned in `actions[].id` on the rule).

Complete example

Every step above, stitched together into one block you can copy and adapt. Fill in ruleId / actionId where a later step needs the id.

// 1. Set up the clientimport { AISDK } from '@browserstack/ai-sdk';const publicKey = process.env.AISDK_PUBLIC_KEY!;const secretKey = process.env.AISDK_SECRET_KEY!;const client = new AISDK({  publicKey,  secretKey,});// 2. Per-run variablesconst name = 'Score production traces on latency evaluator';// 3. Create a ruleconst rule = await client.automationRules.create({  name,  description: 'SDK CRUD test rule',  sourceType: 'TRACE',  samplingRate: 50,  status: 'ACTIVE',  targetingFilters: [    {      fieldName: 'name',      operator: 'EQUALS',      value: 'sdk-test-trace',      logicalOperator: 'AND',    },  ],  actions: [    {      type: 'ONLINE_EVAL',      config: { concurrency: 2, delaySeconds: 30, eventName: null },      metrics: [{ evaluatorListId: evaluatorListId!, routeToHumanReview: false }],    },    {      type: 'DATASET',      config: {        datasetId,        mappingType: 'EXPECTED_OUTPUT',        extractionMode: 'SINGLE_IO',        datasetTag: null,        outputObservationName: null,      },    },  ],});// 4. Grab the rule id for later stepsconst ruleId = rule.id;// 5. List rulesconst { data, meta } = await client.automationRules.list({  page: 1,  limit: 50,});// 6. Fetch a rule by idconst fetched = await client.automationRules.get(ruleId);// 7. Update the ruleconst updated = await client.automationRules.update(ruleId, {  samplingRate: 75,  description: 'updated description',});// 8. Pause and resumeconst paused = await client.automationRules.updateStatus(  ruleId,  { status: 'PAUSED' },);const resumed = await client.automationRules.updateStatus(  ruleId,  { status: 'ACTIVE' },);// 9. Add an actionconst addedAction = await client.automationRules.addAction(ruleId, {  action: {    type: 'DATASET',    config: {      datasetId,      mappingType: 'LLM_OUTPUT',      extractionMode: 'SINGLE_IO',    },  },});// 10. Grab the action id for later stepsconst actionId = ds!.id;// 11. Update an actionconst updatedAction = await client.automationRules.updateAction(  ruleId,  actionId,  {    action: {      type: 'ONLINE_EVAL',      config: {        concurrency: 8,        delaySeconds: 120,        eventName: null,      },    },  },);// 12. Delete an actionconst deletedActionResult = await client.automationRules.deleteAction(  ruleId,  actionId,);// 13. Delete the ruleconst result = await client.automationRules.delete(ruleId);

Setup

Put your public and secret keys in your environment, then create one client and reuse it for every call on this page.

from browserstack_ai_sdk import AISDKclient = AISDK(    public_key=os.environ["AISDK_PUBLIC_KEY"],    secret_key=os.environ["AISDK_SECRET_KEY"],)

The AutomationRule shape

Every method below (except delete) returns an AutomationRule. Here's what's in it:

FieldTypeDefaultDescription
idstrserverServer-generated rule id.
project_idstrserverFilled in from your API-key scope.
namestrrequiredMust be unique within the project (409 if a rule with the same name already exists).
descriptionstr | NoneNoneOptional free-form description.
source_type"TRACE" | "SESSION""TRACE"You can't change this after creating the rule.
sampling_rate1..100100Percent of matched objects the rule actually fires on.
status"ACTIVE" | "PAUSED""ACTIVE"Whether the rule is running.
targeting_filterslist[TargetingFilter][]Conditions a trace or session must meet to match.
actionslist[AutomationRuleAction]required1 or 2 actions. At most one ONLINE_EVAL and one DATASET.
created_bystr | NoneserverThe user or API key that created the rule.
created_at / updated_atdatetimeserverISO 8601 timestamps.

Create a rule

rule = client.automation_rules.create(    name=name,    description="SDK CRUD test rule",    source_type="TRACE",    sampling_rate=50,    status="ACTIVE",    targeting_filters=[        {            "field_name": "name",            "operator": "EQUALS",            "value": "sdk-test-trace",            "logical_operator": "AND",        },    ],    actions=[        {            "type": "ONLINE_EVAL",            "config": {                "concurrency": 2,                "delay_seconds": 30,                "event_name": None,            },            "metrics": [                {                    "evaluator_list_id": evaluator_list_id,                    "route_to_human_review": False,                },            ],        },        {            "type": "DATASET",            "config": {                "dataset_id": dataset_id,                "mapping_type": "EXPECTED_OUTPUT",                "extraction_mode": "SINGLE_IO",                "dataset_tag": None,                "output_observation_name": None,            },        },    ],)

Creates the rule, its actions, and its targeting filters in a single call. You need at least one action, and each action type can appear at most once.

ParamTypeRequiredDescription
namestringtrueA name for the rule, 1–255 characters. Must be unique within the project.
descriptionstring | nullfalseOptional free-form description.
sourceTypeEventSchedulerTypefalseWhether the rule watches traces or sessions. Defaults to `TRACE`.
samplingRatenumberfalsePercent of matching traces the rule fires on (1–100). Useful for sampling high-volume traffic.
Default: 100
statusAutomationRuleStatusfalseThe starting status. Set to `PAUSED` if you want the rule created but not running yet.
Default: "ACTIVE"
targetingFiltersTargetingFilter[]falseThe conditions a trace must meet to match. Leave empty to fire on every trace.
Default: []
targetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
actionsAutomationRuleActionInput[]trueOne or two actions to run when the rule fires — for example, score the trace or add it to a dataset.
ParamTypeRequiredDescription
namestrtrueA name for the rule, 1–255 characters. Must be unique within the project.
descriptionOptional[str]falseOptional free-form description.
source_typeOptional[EventSchedulerType]falseWhether the rule watches traces or sessions. Defaults to `TRACE`.
sampling_rateOptional[int]falsePercent of matching traces the rule fires on (1–100). Useful for sampling high-volume traffic.
Default: 100
statusOptional[object]falseThe starting status. Set to `PAUSED` if you want the rule created but not running yet.
Default: "ACTIVE"
targeting_filtersOptional[list[TargetingFilterInput]]falseThe conditions a trace must meet to match. Leave empty to fire on every trace.
Default: []
targeting_filters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targeting_filters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targeting_filters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targeting_filters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
actionslist[AutomationRuleActionInput]trueOne or two actions to run when the rule fires — for example, score the trace or add it to a dataset.
ParamTypeRequiredDescription
nameStringtrueA name for the rule, 1–255 characters. Must be unique within the project.
descriptionStringfalseOptional free-form description.
sourceTypeEventSchedulerTypefalseWhether the rule watches traces or sessions. Defaults to `TRACE`.
samplingRateIntegerfalsePercent of matching traces the rule fires on (1–100). Useful for sampling high-volume traffic.
Default: 100
statusObjectfalseThe starting status. Set to `PAUSED` if you want the rule created but not running yet.
Default: "ACTIVE"
targetingFiltersList<TargetingFilter>falseThe conditions a trace must meet to match. Leave empty to fire on every trace.
Default: []
targetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
actionsList<AutomationRuleActionInput>trueOne or two actions to run when the rule fires — for example, score the trace or add it to a dataset.
ParamTypeRequiredDescription
NamestringtrueA name for the rule, 1–255 characters. Must be unique within the project.
Description*stringfalseOptional free-form description.
SourceType*EventSchedulerTypefalseWhether the rule watches traces or sessions. Defaults to `TRACE`.
SamplingRate*intfalsePercent of matching traces the rule fires on (1–100). Useful for sampling high-volume traffic.
Default: 100
Status*AutomationRuleStatusfalseThe starting status. Set to `PAUSED` if you want the rule created but not running yet.
Default: "ACTIVE"
TargetingFilters*[]TargetingFilterfalseThe conditions a trace must meet to match. Leave empty to fire on every trace.
Default: []
TargetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
TargetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
TargetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
TargetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
Actions[]AutomationRuleActionInputtrueOne or two actions to run when the rule fires — for example, score the trace or add it to a dataset.

List rules

res = client.automation_rules.list(page=1, limit=50)data = res.datameta = res.meta

meta contains the pagination fields (page, limit, total_items, total_pages). Asking for a page past the last one returns data: [] — it's not an error.

Lists the rules in your project, paginated. You can page through results, search by name, and optionally filter to rules with a specific action type.

ParamTypeRequiredDescription
pagenumberfalse1-indexed page number (default 1)
Default: 1
limitnumberfalsePage size, max 100 (default 50)
Default: 50
searchstringfalseSubstring match on name + description (case-insensitive)
actionTypeAutomationRuleActionType
"ONLINE_EVAL" | "DATASET"
falseIf set, only returns rules that have at least one action of this type.
ParamTypeRequiredDescription
pageOptional[int]false1-indexed page number (default 1)
Default: 1
limitOptional[int]falsePage size, max 100 (default 50)
Default: 50
searchOptional[str]falseSubstring match on name + description (case-insensitive)
action_typeOptional[str]
"ONLINE_EVAL", "DATASET"
falseIf set, only returns rules that have at least one action of this type.
ParamTypeRequiredDescription
pageIntegerfalse1-indexed page number (default 1)
Default: 1
limitIntegerfalsePage size, max 100 (default 50)
Default: 50
searchStringfalseSubstring match on name + description (case-insensitive)
actionTypeString
"ONLINE_EVAL", "DATASET"
falseIf set, only returns rules that have at least one action of this type.
ParamTypeRequiredDescription
Page*intfalse1-indexed page number (default 1)
Default: 1
Limit*intfalsePage size, max 100 (default 50)
Default: 50
Search*stringfalseSubstring match on name + description (case-insensitive)
ActionType*string
"ONLINE_EVAL", "DATASET"
falseIf set, only returns rules that have at least one action of this type.

Get a rule by id

fetched = client.automation_rules.get(rule_id)

Get an automation rule by id

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.

Update a rule

Use this to update rule-level fields like name, description, sampling_rate, or targeting_filters. You can't change source_type. To add or remove actions, use the action-level methods further down; to toggle per-metric routing, use update_action() since metrics belong to the action, not the rule.

updated = client.automation_rules.update(    rule_id,    sampling_rate=75,    description="updated description",)

Updates the rule. Only the fields you send are changed — anything you leave out stays the same. A few things to know: - You can't change `sourceType`. - To add or remove actions, use the `/actions` endpoints below. To toggle per-metric human-review routing, use `PATCH /actions/{actionId}` (metrics belong to an action, not to the rule). - Pass `description: null` to clear the description. - `targetingFilters`, if you send it, replaces the whole filter list — send the full set you want, not a delta.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
namestringfalseNew rule name.
descriptionstring | nullfalseNew description. Pass `null` to clear it.
samplingRatenumberfalseNew sampling rate (1–100).
statusAutomationRuleStatusfalseNew status — `ACTIVE` or `PAUSED`.
targetingFiltersTargetingFilter[]falseNew targeting filters. Pass an empty array to clear.
targetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
nameOptional[str]falseNew rule name.
descriptionOptional[str]falseNew description. Pass `null` to clear it.
sampling_rateOptional[int]falseNew sampling rate (1–100).
statusOptional[AutomationRuleStatus]falseNew status — `ACTIVE` or `PAUSED`.
targeting_filtersOptional[list[TargetingFilterInput]]falseNew targeting filters. Pass an empty array to clear.
targeting_filters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targeting_filters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targeting_filters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targeting_filters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
nameStringfalseNew rule name.
descriptionStringfalseNew description. Pass `null` to clear it.
samplingRateIntegerfalseNew sampling rate (1–100).
statusAutomationRuleStatusfalseNew status — `ACTIVE` or `PAUSED`.
targetingFiltersList<TargetingFilter>falseNew targeting filters. Pass an empty array to clear.
targetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
Name*stringfalseNew rule name.
Description*stringfalseNew description. Pass `null` to clear it.
SamplingRate*intfalseNew sampling rate (1–100).
Status*AutomationRuleStatusfalseNew status — `ACTIVE` or `PAUSED`.
TargetingFilters*[]TargetingFilterfalseNew targeting filters. Pass an empty array to clear.
TargetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
TargetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
TargetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
TargetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"

Pause and resume

update_status() pauses or resumes a rule. It's a convenience shortcut over update() — the effect is the same as calling update(rule_id, status='PAUSED') or status='ACTIVE', but it reads more clearly at the call site.

paused = client.automation_rules.update_status(rule_id, status="PAUSED")resumed = client.automation_rules.update_status(rule_id, status="ACTIVE")

A convenience shortcut for pausing or resuming a rule. Same as `PATCH /automation-rules/{ruleId}` with just `{ status }`, but reads more clearly at the call site.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
statusAutomationRuleStatustrueThe new status — `ACTIVE` or `PAUSED`.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
statusAutomationRuleStatustrueThe new status — `ACTIVE` or `PAUSED`.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
statusAutomationRuleStatustrueThe new status — `ACTIVE` or `PAUSED`.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
StatusAutomationRuleStatustrueThe new status — `ACTIVE` or `PAUSED`.

Delete a rule

Deletes the rule and everything attached to it — actions, metrics, and targeting filters.

result = client.automation_rules.delete(rule_id)

Deletes the rule and everything attached to it — actions, metrics, and targeting filters. Any evaluation results the rule already produced are kept.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.

Add an action

Add a second action to an existing rule — for example, attach a DATASET action to a rule that already runs ONLINE_EVAL. A rule can hold at most one action of each type, so adding a second ONLINE_EVAL (or DATASET) to a rule that already has one is rejected.

added_action = client.automation_rules.add_action(    rule_id,    action={        "type": "DATASET",        "config": {            "dataset_id": dataset_id,            "mapping_type": "LLM_OUTPUT",            "extraction_mode": "SINGLE_IO",        },    },)

Returns the full updated rule, so you don't need a follow-up get().

Adds one action to an existing rule. Pass the action as a nested `action` object — the same shape as an entry in `actions[]` when you create a rule. A rule can hold at most one action of each type, so adding a second action of the same type returns `409`.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionAutomationRuleActionInputtrueThe action to add. A rule can hold up to two actions.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
actionAutomationRuleActionInputtrueThe action to add. A rule can hold up to two actions.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
actionAutomationRuleActionInputtrueThe action to add. A rule can hold up to two actions.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
ActionAutomationRuleActionInputtrueThe action to add. A rule can hold up to two actions.

Update an action

Update an action's config in place. For ONLINE_EVAL actions, you can optionally pass a metrics array to flip route_to_human_review on individual evaluators (up to 50 per call).

updated_action = client.automation_rules.update_action(    rule_id,    action_id,    action={        "type": "ONLINE_EVAL",        "config": {            "concurrency": 8,            "delay_seconds": 120,            "event_name": None,        },    },)

Updates the action's `config` in place. For `ONLINE_EVAL` actions you can also pass a `metrics` list to flip `routeToHumanReview` per metric — this endpoint is the only way to change those toggles.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionIdstringtrueThe action's id (returned in `actions[].id` on the rule).
actionAutomationRuleActionUpdateInputtrueThe fields to update on the action. Anything you leave out stays the same.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
action_idstrtrueThe action's id (returned in `actions[].id` on the rule).
actionAutomationRuleActionUpdateInputtrueThe fields to update on the action. Anything you leave out stays the same.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
actionIdStringtrueThe action's id (returned in `actions[].id` on the rule).
actionAutomationRuleActionUpdateInputtrueThe fields to update on the action. Anything you leave out stays the same.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionIdstringtrueThe action's id (returned in `actions[].id` on the rule).
ActionAutomationRuleActionUpdateInputtrueThe fields to update on the action. Anything you leave out stays the same.

Delete an action

A rule always needs at least one action, so deleting the last remaining action returns 400. Delete the whole rule instead if that's what you want.

deleted_action_result = client.automation_rules.delete_action(rule_id, action_id)

A rule always needs at least one action. Deleting the last remaining action returns `409` — delete the whole rule instead.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionIdstringtrueThe action's id (returned in `actions[].id` on the rule).
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
action_idstrtrueThe action's id (returned in `actions[].id` on the rule).
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
actionIdStringtrueThe action's id (returned in `actions[].id` on the rule).
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionIdstringtrueThe action's id (returned in `actions[].id` on the rule).

Complete example

Every step above, stitched together into one block you can copy and adapt. Fill in rule_id / action_id where a later step needs the id.

# 1. Set up the clientfrom browserstack_ai_sdk import AISDKclient = AISDK(    public_key=os.environ["AISDK_PUBLIC_KEY"],    secret_key=os.environ["AISDK_SECRET_KEY"],)# 2. Per-run variablesname = "Score production traces on latency evaluator"# 3. Create a rulerule = client.automation_rules.create(    name=name,    description="SDK CRUD test rule",    source_type="TRACE",    sampling_rate=50,    status="ACTIVE",    targeting_filters=[        {            "field_name": "name",            "operator": "EQUALS",            "value": "sdk-test-trace",            "logical_operator": "AND",        },    ],    actions=[        {            "type": "ONLINE_EVAL",            "config": {                "concurrency": 2,                "delay_seconds": 30,                "event_name": None,            },            "metrics": [                {                    "evaluator_list_id": evaluator_list_id,                    "route_to_human_review": False,                },            ],        },        {            "type": "DATASET",            "config": {                "dataset_id": dataset_id,                "mapping_type": "EXPECTED_OUTPUT",                "extraction_mode": "SINGLE_IO",                "dataset_tag": None,                "output_observation_name": None,            },        },    ],)# 4. Grab the rule id for later stepsrule_id = rule.id# 5. List rulesres = client.automation_rules.list(page=1, limit=50)data = res.datameta = res.meta# 6. Fetch a rule by idfetched = client.automation_rules.get(rule_id)# 7. Update the ruleupdated = client.automation_rules.update(    rule_id,    sampling_rate=75,    description="updated description",)# 8. Pause and resumepaused = client.automation_rules.update_status(rule_id, status="PAUSED")resumed = client.automation_rules.update_status(rule_id, status="ACTIVE")# 9. Add an actionadded_action = client.automation_rules.add_action(    rule_id,    action={        "type": "DATASET",        "config": {            "dataset_id": dataset_id,            "mapping_type": "LLM_OUTPUT",            "extraction_mode": "SINGLE_IO",        },    },)# 10. Grab the action id for later stepsaction_id = ds.id# 11. Update an actionupdated_action = client.automation_rules.update_action(    rule_id,    action_id,    action={        "type": "ONLINE_EVAL",        "config": {            "concurrency": 8,            "delay_seconds": 120,            "event_name": None,        },    },)# 12. Delete an actiondeleted_action_result = client.automation_rules.delete_action(rule_id, action_id)# 13. Delete the ruleresult = client.automation_rules.delete(rule_id)

Setup

Put your public and secret keys in your environment, then create one SDK instance and reuse it for every call on this page.

import com.browserstack.aisdk.AISDK;import com.browserstack.aisdk.clients.automation_rule.AddAutomationRuleActionBody;import com.browserstack.aisdk.clients.automation_rule.AutomationRule;import com.browserstack.aisdk.clients.automation_rule.AutomationRuleConfig;import com.browserstack.aisdk.clients.automation_rule.AutomationRuleStatus;import com.browserstack.aisdk.clients.automation_rule.CreateAutomationRuleBody;import com.browserstack.aisdk.clients.automation_rule.DatasetActionConfigInput;import com.browserstack.aisdk.clients.automation_rule.DatasetActionInput;import com.browserstack.aisdk.clients.automation_rule.DatasetActionInputType;import com.browserstack.aisdk.clients.automation_rule.DatasetExtractionMode;import com.browserstack.aisdk.clients.automation_rule.DatasetMappingType;import com.browserstack.aisdk.clients.automation_rule.DeleteAutomationRuleResponse;import com.browserstack.aisdk.clients.automation_rule.EventSchedulerType;import com.browserstack.aisdk.clients.automation_rule.ListAutomationRulesParams;import com.browserstack.aisdk.clients.automation_rule.ListAutomationRulesResponse;import com.browserstack.aisdk.clients.automation_rule.OnlineEvalActionConfigInput;import com.browserstack.aisdk.clients.automation_rule.OnlineEvalActionInput;import com.browserstack.aisdk.clients.automation_rule.OnlineEvalActionInputType;import com.browserstack.aisdk.clients.automation_rule.OnlineEvalActionUpdateInput;import com.browserstack.aisdk.clients.automation_rule.OnlineEvalMetricInput;import com.browserstack.aisdk.clients.automation_rule.SuccessAck;import com.browserstack.aisdk.clients.automation_rule.UpdateAutomationRuleActionBody;import com.browserstack.aisdk.clients.automation_rule.UpdateAutomationRuleBody;import com.browserstack.aisdk.clients.automation_rule.UpdateAutomationRuleStatusBody;import java.util.Arrays;import java.util.Collections;import java.util.List;AISDK sdk = AISDK.builder()    .publicKey(System.getenv("AISDK_PUBLIC_KEY"))    .secretKey(System.getenv("AISDK_SECRET_KEY"))    .build();AutomationRule automationRules = sdk.automationRule();

The AutomationRule shape

Every method below (except delete) returns an AutomationRule. Here's what's in it:

FieldTypeDefaultDescription
idStringserverServer-generated rule id.
projectIdStringserverFilled in from your API-key scope.
nameStringrequiredMust be unique within the project (409 if a rule with the same name already exists).
descriptionString | nullnullOptional free-form description.
sourceType"TRACE" | "SESSION""TRACE"You can't change this after creating the rule.
samplingRate1..100100Percent of matched objects the rule actually fires on.
status"ACTIVE" | "PAUSED""ACTIVE"Whether the rule is running.
targetingFiltersList<TargetingFilter>[]Conditions a trace or session must meet to match.
actionsList<AutomationRuleAction>required1 or 2 actions. At most one ONLINE_EVAL and one DATASET.
createdByString | nullserverThe user or API key that created the rule.
createdAt / updatedAtInstantserverISO 8601 timestamps.

Create a rule

// Build a rule with two actions: an ONLINE_EVAL that runs an// evaluator list on a sampled slice of production traces, and a// DATASET action that captures the trace input/output as// expected-output pairs into a dataset for later experimentation.CreateAutomationRuleBody createBody = new CreateAutomationRuleBody();createBody.name = name;createBody.status = AutomationRuleStatus.ACTIVE;createBody.samplingRate = 50;createBody.sourceType = EventSchedulerType.TRACE;OnlineEvalActionInput evalAction = new OnlineEvalActionInput();evalAction.type = OnlineEvalActionInputType.ONLINE_EVAL;evalAction.config = new OnlineEvalActionConfigInput();evalAction.config.concurrency = 2;evalAction.config.delaySeconds = 30;OnlineEvalMetricInput metric = new OnlineEvalMetricInput();metric.evaluatorListId = "ee_latency_v1";metric.routeToHumanReview = false;evalAction.metrics = Collections.singletonList(metric);DatasetActionInput datasetAction = new DatasetActionInput();datasetAction.type = DatasetActionInputType.DATASET;datasetAction.config = new DatasetActionConfigInput();datasetAction.config.datasetId = "ds_prod_captures";datasetAction.config.mappingType = DatasetMappingType.EXPECTED_OUTPUT;datasetAction.config.extractionMode = DatasetExtractionMode.SINGLE_IO;createBody.actions = Arrays.asList(evalAction, datasetAction);AutomationRuleConfig rule = automationRules.create(createBody);

Creates the rule, its actions, and its targeting filters in a single call. You need at least one action, and each action type can appear at most once.

ParamTypeRequiredDescription
namestringtrueA name for the rule, 1–255 characters. Must be unique within the project.
descriptionstring | nullfalseOptional free-form description.
sourceTypeEventSchedulerTypefalseWhether the rule watches traces or sessions. Defaults to `TRACE`.
samplingRatenumberfalsePercent of matching traces the rule fires on (1–100). Useful for sampling high-volume traffic.
Default: 100
statusAutomationRuleStatusfalseThe starting status. Set to `PAUSED` if you want the rule created but not running yet.
Default: "ACTIVE"
targetingFiltersTargetingFilter[]falseThe conditions a trace must meet to match. Leave empty to fire on every trace.
Default: []
targetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
actionsAutomationRuleActionInput[]trueOne or two actions to run when the rule fires — for example, score the trace or add it to a dataset.
ParamTypeRequiredDescription
namestrtrueA name for the rule, 1–255 characters. Must be unique within the project.
descriptionOptional[str]falseOptional free-form description.
source_typeOptional[EventSchedulerType]falseWhether the rule watches traces or sessions. Defaults to `TRACE`.
sampling_rateOptional[int]falsePercent of matching traces the rule fires on (1–100). Useful for sampling high-volume traffic.
Default: 100
statusOptional[object]falseThe starting status. Set to `PAUSED` if you want the rule created but not running yet.
Default: "ACTIVE"
targeting_filtersOptional[list[TargetingFilterInput]]falseThe conditions a trace must meet to match. Leave empty to fire on every trace.
Default: []
targeting_filters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targeting_filters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targeting_filters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targeting_filters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
actionslist[AutomationRuleActionInput]trueOne or two actions to run when the rule fires — for example, score the trace or add it to a dataset.
ParamTypeRequiredDescription
nameStringtrueA name for the rule, 1–255 characters. Must be unique within the project.
descriptionStringfalseOptional free-form description.
sourceTypeEventSchedulerTypefalseWhether the rule watches traces or sessions. Defaults to `TRACE`.
samplingRateIntegerfalsePercent of matching traces the rule fires on (1–100). Useful for sampling high-volume traffic.
Default: 100
statusObjectfalseThe starting status. Set to `PAUSED` if you want the rule created but not running yet.
Default: "ACTIVE"
targetingFiltersList<TargetingFilter>falseThe conditions a trace must meet to match. Leave empty to fire on every trace.
Default: []
targetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
actionsList<AutomationRuleActionInput>trueOne or two actions to run when the rule fires — for example, score the trace or add it to a dataset.
ParamTypeRequiredDescription
NamestringtrueA name for the rule, 1–255 characters. Must be unique within the project.
Description*stringfalseOptional free-form description.
SourceType*EventSchedulerTypefalseWhether the rule watches traces or sessions. Defaults to `TRACE`.
SamplingRate*intfalsePercent of matching traces the rule fires on (1–100). Useful for sampling high-volume traffic.
Default: 100
Status*AutomationRuleStatusfalseThe starting status. Set to `PAUSED` if you want the rule created but not running yet.
Default: "ACTIVE"
TargetingFilters*[]TargetingFilterfalseThe conditions a trace must meet to match. Leave empty to fire on every trace.
Default: []
TargetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
TargetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
TargetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
TargetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
Actions[]AutomationRuleActionInputtrueOne or two actions to run when the rule fires — for example, score the trace or add it to a dataset.

List rules

ListAutomationRulesParams params = new ListAutomationRulesParams();params.page = 1;params.limit = 50;ListAutomationRulesResponse page = automationRules.list(params);List<AutomationRuleConfig> rules = page.data;

meta contains the pagination fields (page, limit, totalItems, totalPages). Asking for a page past the last one returns data: [] — it's not an error.

Lists the rules in your project, paginated. You can page through results, search by name, and optionally filter to rules with a specific action type.

ParamTypeRequiredDescription
pagenumberfalse1-indexed page number (default 1)
Default: 1
limitnumberfalsePage size, max 100 (default 50)
Default: 50
searchstringfalseSubstring match on name + description (case-insensitive)
actionTypeAutomationRuleActionType
"ONLINE_EVAL" | "DATASET"
falseIf set, only returns rules that have at least one action of this type.
ParamTypeRequiredDescription
pageOptional[int]false1-indexed page number (default 1)
Default: 1
limitOptional[int]falsePage size, max 100 (default 50)
Default: 50
searchOptional[str]falseSubstring match on name + description (case-insensitive)
action_typeOptional[str]
"ONLINE_EVAL", "DATASET"
falseIf set, only returns rules that have at least one action of this type.
ParamTypeRequiredDescription
pageIntegerfalse1-indexed page number (default 1)
Default: 1
limitIntegerfalsePage size, max 100 (default 50)
Default: 50
searchStringfalseSubstring match on name + description (case-insensitive)
actionTypeString
"ONLINE_EVAL", "DATASET"
falseIf set, only returns rules that have at least one action of this type.
ParamTypeRequiredDescription
Page*intfalse1-indexed page number (default 1)
Default: 1
Limit*intfalsePage size, max 100 (default 50)
Default: 50
Search*stringfalseSubstring match on name + description (case-insensitive)
ActionType*string
"ONLINE_EVAL", "DATASET"
falseIf set, only returns rules that have at least one action of this type.

Get a rule by id

AutomationRuleConfig fetched = automationRules.get(ruleId);

Get an automation rule by id

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.

Update a rule

Use this to update rule-level fields like name, description, samplingRate, or targetingFilters. You can't change sourceType. To add or remove actions, use the action-level methods further down; to toggle per-metric routing, use updateAction() since metrics belong to the action, not the rule.

// Partial update — only non-null fields are sent on the wire.UpdateAutomationRuleBody updateBody = new UpdateAutomationRuleBody();updateBody.samplingRate = 75;updateBody.description = "updated description";AutomationRuleConfig updated = automationRules.update(ruleId, updateBody);

Updates the rule. Only the fields you send are changed — anything you leave out stays the same. A few things to know: - You can't change `sourceType`. - To add or remove actions, use the `/actions` endpoints below. To toggle per-metric human-review routing, use `PATCH /actions/{actionId}` (metrics belong to an action, not to the rule). - Pass `description: null` to clear the description. - `targetingFilters`, if you send it, replaces the whole filter list — send the full set you want, not a delta.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
namestringfalseNew rule name.
descriptionstring | nullfalseNew description. Pass `null` to clear it.
samplingRatenumberfalseNew sampling rate (1–100).
statusAutomationRuleStatusfalseNew status — `ACTIVE` or `PAUSED`.
targetingFiltersTargetingFilter[]falseNew targeting filters. Pass an empty array to clear.
targetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
nameOptional[str]falseNew rule name.
descriptionOptional[str]falseNew description. Pass `null` to clear it.
sampling_rateOptional[int]falseNew sampling rate (1–100).
statusOptional[AutomationRuleStatus]falseNew status — `ACTIVE` or `PAUSED`.
targeting_filtersOptional[list[TargetingFilterInput]]falseNew targeting filters. Pass an empty array to clear.
targeting_filters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targeting_filters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targeting_filters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targeting_filters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
nameStringfalseNew rule name.
descriptionStringfalseNew description. Pass `null` to clear it.
samplingRateIntegerfalseNew sampling rate (1–100).
statusAutomationRuleStatusfalseNew status — `ACTIVE` or `PAUSED`.
targetingFiltersList<TargetingFilter>falseNew targeting filters. Pass an empty array to clear.
targetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
Name*stringfalseNew rule name.
Description*stringfalseNew description. Pass `null` to clear it.
SamplingRate*intfalseNew sampling rate (1–100).
Status*AutomationRuleStatusfalseNew status — `ACTIVE` or `PAUSED`.
TargetingFilters*[]TargetingFilterfalseNew targeting filters. Pass an empty array to clear.
TargetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
TargetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
TargetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
TargetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"

Pause and resume

updateStatus() pauses or resumes a rule. It's a convenience shortcut over update() — the effect is the same as calling update(ruleId, UpdateRequest.builder().status("PAUSED").build()), but it reads more clearly at the call site.

// Pause the rule while iterating on evaluator config.UpdateAutomationRuleStatusBody pauseBody = new UpdateAutomationRuleStatusBody();pauseBody.status = AutomationRuleStatus.PAUSED;AutomationRuleConfig paused = automationRules.updateStatus(ruleId, pauseBody);// ...and resume when ready.UpdateAutomationRuleStatusBody resumeBody = new UpdateAutomationRuleStatusBody();resumeBody.status = AutomationRuleStatus.ACTIVE;AutomationRuleConfig resumed = automationRules.updateStatus(ruleId, resumeBody);

A convenience shortcut for pausing or resuming a rule. Same as `PATCH /automation-rules/{ruleId}` with just `{ status }`, but reads more clearly at the call site.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
statusAutomationRuleStatustrueThe new status — `ACTIVE` or `PAUSED`.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
statusAutomationRuleStatustrueThe new status — `ACTIVE` or `PAUSED`.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
statusAutomationRuleStatustrueThe new status — `ACTIVE` or `PAUSED`.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
StatusAutomationRuleStatustrueThe new status — `ACTIVE` or `PAUSED`.

Delete a rule

Deletes the rule and everything attached to it — actions, metrics, and targeting filters.

DeleteAutomationRuleResponse result = automationRules.delete(ruleId);

Deletes the rule and everything attached to it — actions, metrics, and targeting filters. Any evaluation results the rule already produced are kept.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.

Add an action

Add a second action to an existing rule — for example, attach a DATASET action to a rule that already runs ONLINE_EVAL. A rule can hold at most one action of each type, so adding a second ONLINE_EVAL (or DATASET) to a rule that already has one is rejected.

// Attach another DATASET action to an existing rule — captures the// LLM output into a second dataset for regression comparison.DatasetActionInput extraDataset = new DatasetActionInput();extraDataset.type = DatasetActionInputType.DATASET;extraDataset.config = new DatasetActionConfigInput();extraDataset.config.datasetId = "ds_regression_capture";extraDataset.config.mappingType = DatasetMappingType.LLM_OUTPUT;extraDataset.config.extractionMode = DatasetExtractionMode.SINGLE_IO;AddAutomationRuleActionBody addActionBody = new AddAutomationRuleActionBody();addActionBody.action = extraDataset;AutomationRuleConfig addedAction = automationRules.addAction(ruleId, addActionBody);

Returns the full updated rule, so you don't need a follow-up get().

Adds one action to an existing rule. Pass the action as a nested `action` object — the same shape as an entry in `actions[]` when you create a rule. A rule can hold at most one action of each type, so adding a second action of the same type returns `409`.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionAutomationRuleActionInputtrueThe action to add. A rule can hold up to two actions.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
actionAutomationRuleActionInputtrueThe action to add. A rule can hold up to two actions.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
actionAutomationRuleActionInputtrueThe action to add. A rule can hold up to two actions.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
ActionAutomationRuleActionInputtrueThe action to add. A rule can hold up to two actions.

Update an action

Update an action's config in place. For ONLINE_EVAL actions, you can optionally pass a metrics array to flip routeToHumanReview on individual evaluators (up to 50 per call).

// Retune the ONLINE_EVAL action's concurrency + delay in place.OnlineEvalActionUpdateInput retuned = new OnlineEvalActionUpdateInput();retuned.type = OnlineEvalActionInputType.ONLINE_EVAL;retuned.config = new OnlineEvalActionConfigInput();retuned.config.concurrency = 8;retuned.config.delaySeconds = 120;UpdateAutomationRuleActionBody updateActionBody = new UpdateAutomationRuleActionBody();updateActionBody.action = retuned;AutomationRuleConfig updatedAction = automationRules.updateAction(ruleId, actionId, updateActionBody);

Updates the action's `config` in place. For `ONLINE_EVAL` actions you can also pass a `metrics` list to flip `routeToHumanReview` per metric — this endpoint is the only way to change those toggles.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionIdstringtrueThe action's id (returned in `actions[].id` on the rule).
actionAutomationRuleActionUpdateInputtrueThe fields to update on the action. Anything you leave out stays the same.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
action_idstrtrueThe action's id (returned in `actions[].id` on the rule).
actionAutomationRuleActionUpdateInputtrueThe fields to update on the action. Anything you leave out stays the same.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
actionIdStringtrueThe action's id (returned in `actions[].id` on the rule).
actionAutomationRuleActionUpdateInputtrueThe fields to update on the action. Anything you leave out stays the same.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionIdstringtrueThe action's id (returned in `actions[].id` on the rule).
ActionAutomationRuleActionUpdateInputtrueThe fields to update on the action. Anything you leave out stays the same.

Delete an action

A rule always needs at least one action, so deleting the last remaining action returns 400. Delete the whole rule instead if that's what you want.

// Remove an action from a rule (the rule must retain at least one// action — deleting the last remaining action returns 409).SuccessAck deletedActionResult = automationRules.deleteAction(ruleId, actionId);

A rule always needs at least one action. Deleting the last remaining action returns `409` — delete the whole rule instead.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionIdstringtrueThe action's id (returned in `actions[].id` on the rule).
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
action_idstrtrueThe action's id (returned in `actions[].id` on the rule).
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
actionIdStringtrueThe action's id (returned in `actions[].id` on the rule).
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionIdstringtrueThe action's id (returned in `actions[].id` on the rule).

Complete example

Every step above, stitched together into one block you can copy and adapt. Fill in ruleId / actionId where a later step needs the id.

// 1. Set up the SDKimport com.browserstack.aisdk.AISDK;import com.browserstack.aisdk.clients.automation_rule.AddAutomationRuleActionBody;import com.browserstack.aisdk.clients.automation_rule.AutomationRule;import com.browserstack.aisdk.clients.automation_rule.AutomationRuleConfig;import com.browserstack.aisdk.clients.automation_rule.AutomationRuleStatus;import com.browserstack.aisdk.clients.automation_rule.CreateAutomationRuleBody;import com.browserstack.aisdk.clients.automation_rule.DatasetActionConfigInput;import com.browserstack.aisdk.clients.automation_rule.DatasetActionInput;import com.browserstack.aisdk.clients.automation_rule.DatasetActionInputType;import com.browserstack.aisdk.clients.automation_rule.DatasetExtractionMode;import com.browserstack.aisdk.clients.automation_rule.DatasetMappingType;import com.browserstack.aisdk.clients.automation_rule.DeleteAutomationRuleResponse;import com.browserstack.aisdk.clients.automation_rule.EventSchedulerType;import com.browserstack.aisdk.clients.automation_rule.ListAutomationRulesParams;import com.browserstack.aisdk.clients.automation_rule.ListAutomationRulesResponse;import com.browserstack.aisdk.clients.automation_rule.OnlineEvalActionConfigInput;import com.browserstack.aisdk.clients.automation_rule.OnlineEvalActionInput;import com.browserstack.aisdk.clients.automation_rule.OnlineEvalActionInputType;import com.browserstack.aisdk.clients.automation_rule.OnlineEvalActionUpdateInput;import com.browserstack.aisdk.clients.automation_rule.OnlineEvalMetricInput;import com.browserstack.aisdk.clients.automation_rule.SuccessAck;import com.browserstack.aisdk.clients.automation_rule.UpdateAutomationRuleActionBody;import com.browserstack.aisdk.clients.automation_rule.UpdateAutomationRuleBody;import com.browserstack.aisdk.clients.automation_rule.UpdateAutomationRuleStatusBody;import java.util.Arrays;import java.util.Collections;import java.util.List;AISDK sdk = AISDK.builder()    .publicKey(System.getenv("AISDK_PUBLIC_KEY"))    .secretKey(System.getenv("AISDK_SECRET_KEY"))    .build();AutomationRule automationRules = sdk.automationRule();// 2. Per-run variablesString name = "Score production traces on latency evaluator";// 3. Create a rule// Build a rule with two actions: an ONLINE_EVAL that runs an// evaluator list on a sampled slice of production traces, and a// DATASET action that captures the trace input/output as// expected-output pairs into a dataset for later experimentation.CreateAutomationRuleBody createBody = new CreateAutomationRuleBody();createBody.name = name;createBody.status = AutomationRuleStatus.ACTIVE;createBody.samplingRate = 50;createBody.sourceType = EventSchedulerType.TRACE;OnlineEvalActionInput evalAction = new OnlineEvalActionInput();evalAction.type = OnlineEvalActionInputType.ONLINE_EVAL;evalAction.config = new OnlineEvalActionConfigInput();evalAction.config.concurrency = 2;evalAction.config.delaySeconds = 30;OnlineEvalMetricInput metric = new OnlineEvalMetricInput();metric.evaluatorListId = "ee_latency_v1";metric.routeToHumanReview = false;evalAction.metrics = Collections.singletonList(metric);DatasetActionInput datasetAction = new DatasetActionInput();datasetAction.type = DatasetActionInputType.DATASET;datasetAction.config = new DatasetActionConfigInput();datasetAction.config.datasetId = "ds_prod_captures";datasetAction.config.mappingType = DatasetMappingType.EXPECTED_OUTPUT;datasetAction.config.extractionMode = DatasetExtractionMode.SINGLE_IO;createBody.actions = Arrays.asList(evalAction, datasetAction);AutomationRuleConfig rule = automationRules.create(createBody);// 4. Grab the rule id for later stepsString ruleId = rule.id;// 5. List rulesListAutomationRulesParams params = new ListAutomationRulesParams();params.page = 1;params.limit = 50;ListAutomationRulesResponse page = automationRules.list(params);List<AutomationRuleConfig> rules = page.data;// 6. Fetch a rule by idAutomationRuleConfig fetched = automationRules.get(ruleId);// 7. Update the rule// Partial update — only non-null fields are sent on the wire.UpdateAutomationRuleBody updateBody = new UpdateAutomationRuleBody();updateBody.samplingRate = 75;updateBody.description = "updated description";AutomationRuleConfig updated = automationRules.update(ruleId, updateBody);// 8. Pause and resume// Pause the rule while iterating on evaluator config.UpdateAutomationRuleStatusBody pauseBody = new UpdateAutomationRuleStatusBody();pauseBody.status = AutomationRuleStatus.PAUSED;AutomationRuleConfig paused = automationRules.updateStatus(ruleId, pauseBody);// ...and resume when ready.UpdateAutomationRuleStatusBody resumeBody = new UpdateAutomationRuleStatusBody();resumeBody.status = AutomationRuleStatus.ACTIVE;AutomationRuleConfig resumed = automationRules.updateStatus(ruleId, resumeBody);// 9. Add an action// Attach another DATASET action to an existing rule — captures the// LLM output into a second dataset for regression comparison.DatasetActionInput extraDataset = new DatasetActionInput();extraDataset.type = DatasetActionInputType.DATASET;extraDataset.config = new DatasetActionConfigInput();extraDataset.config.datasetId = "ds_regression_capture";extraDataset.config.mappingType = DatasetMappingType.LLM_OUTPUT;extraDataset.config.extractionMode = DatasetExtractionMode.SINGLE_IO;AddAutomationRuleActionBody addActionBody = new AddAutomationRuleActionBody();addActionBody.action = extraDataset;AutomationRuleConfig addedAction = automationRules.addAction(ruleId, addActionBody);// 10. Grab the action id for later stepsString actionId = addedAction.actions.get(0).id;// 11. Update an action// Retune the ONLINE_EVAL action's concurrency + delay in place.OnlineEvalActionUpdateInput retuned = new OnlineEvalActionUpdateInput();retuned.type = OnlineEvalActionInputType.ONLINE_EVAL;retuned.config = new OnlineEvalActionConfigInput();retuned.config.concurrency = 8;retuned.config.delaySeconds = 120;UpdateAutomationRuleActionBody updateActionBody = new UpdateAutomationRuleActionBody();updateActionBody.action = retuned;AutomationRuleConfig updatedAction = automationRules.updateAction(ruleId, actionId, updateActionBody);// 12. Delete an action// Remove an action from a rule (the rule must retain at least one// action — deleting the last remaining action returns 409).SuccessAck deletedActionResult = automationRules.deleteAction(ruleId, actionId);// 13. Delete the ruleDeleteAutomationRuleResponse result = automationRules.delete(ruleId);

Setup

Put your public and secret keys in your environment, then create one SDK instance and reuse it for every call on this page.

import (	"context"	"log"	aisdk "github.com/browserstack/ai-sdk-go")ctx := context.Background()publicKey := os.Getenv("AISDK_PUBLIC_KEY")secretKey := os.Getenv("AISDK_SECRET_KEY")sdk, err := aisdk.New(aisdk.WithCredentials(publicKey, secretKey))if err != nil {	log.Fatalf("aisdk.New: %v", err)}client := sdk.AutomationRule()

The AutomationRule shape

Every method below (except Delete) returns an AutomationRule. Here's what's in it:

FieldTypeDefaultDescription
IDstringserverServer-generated rule id.
ProjectIDstringserverFilled in from your API-key scope.
NamestringrequiredMust be unique within the project (409 if a rule with the same name already exists).
Description*stringnilOptional free-form description.
SourceType"TRACE" | "SESSION""TRACE"You can't change this after creating the rule.
SamplingRate1..100100Percent of matched objects the rule actually fires on.
Status"ACTIVE" | "PAUSED""ACTIVE"Whether the rule is running.
TargetingFilters[]TargetingFilter[]Conditions a trace or session must meet to match.
Actions[]AutomationRuleActionrequired1 or 2 actions. At most one ONLINE_EVAL and one DATASET.
CreatedBy*stringserverThe user or API key that created the rule.
CreatedAt / UpdatedAttime.TimeserverISO 8601 timestamps.

Create a rule

sourceType := EventSchedulerTypeTracestatus := AutomationRuleStatusActivesamplingRate := 50mappingType := DatasetMappingTypeExpectedOutputextractionMode := DatasetExtractionModeSingleIoconcurrency := 2delaySeconds := 30routeToHumanReview := falserule, err := client.Create(ctx, &CreateAutomationRuleBody{	Name:         name,	SourceType:   &sourceType,	SamplingRate: &samplingRate,	Status:       &status,	Actions: []AutomationRuleActionInput{		OnlineEvalActionInput{			Type: OnlineEvalActionInputTypeOnlineEval,			Config: OnlineEvalActionConfigInput{				Concurrency:  &concurrency,				DelaySeconds: &delaySeconds,			},			Metrics: []OnlineEvalMetricInput{				{EvaluatorListId: evaluatorListID, RouteToHumanReview: &routeToHumanReview},			},		},		DatasetActionInput{			Type: DatasetActionInputTypeDataset,			Config: DatasetActionConfigInput{				DatasetId:      datasetID,				MappingType:    &mappingType,				ExtractionMode: &extractionMode,			},		},	},})

Creates the rule, its actions, and its targeting filters in a single call. You need at least one action, and each action type can appear at most once.

ParamTypeRequiredDescription
namestringtrueA name for the rule, 1–255 characters. Must be unique within the project.
descriptionstring | nullfalseOptional free-form description.
sourceTypeEventSchedulerTypefalseWhether the rule watches traces or sessions. Defaults to `TRACE`.
samplingRatenumberfalsePercent of matching traces the rule fires on (1–100). Useful for sampling high-volume traffic.
Default: 100
statusAutomationRuleStatusfalseThe starting status. Set to `PAUSED` if you want the rule created but not running yet.
Default: "ACTIVE"
targetingFiltersTargetingFilter[]falseThe conditions a trace must meet to match. Leave empty to fire on every trace.
Default: []
targetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
actionsAutomationRuleActionInput[]trueOne or two actions to run when the rule fires — for example, score the trace or add it to a dataset.
ParamTypeRequiredDescription
namestrtrueA name for the rule, 1–255 characters. Must be unique within the project.
descriptionOptional[str]falseOptional free-form description.
source_typeOptional[EventSchedulerType]falseWhether the rule watches traces or sessions. Defaults to `TRACE`.
sampling_rateOptional[int]falsePercent of matching traces the rule fires on (1–100). Useful for sampling high-volume traffic.
Default: 100
statusOptional[object]falseThe starting status. Set to `PAUSED` if you want the rule created but not running yet.
Default: "ACTIVE"
targeting_filtersOptional[list[TargetingFilterInput]]falseThe conditions a trace must meet to match. Leave empty to fire on every trace.
Default: []
targeting_filters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targeting_filters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targeting_filters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targeting_filters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
actionslist[AutomationRuleActionInput]trueOne or two actions to run when the rule fires — for example, score the trace or add it to a dataset.
ParamTypeRequiredDescription
nameStringtrueA name for the rule, 1–255 characters. Must be unique within the project.
descriptionStringfalseOptional free-form description.
sourceTypeEventSchedulerTypefalseWhether the rule watches traces or sessions. Defaults to `TRACE`.
samplingRateIntegerfalsePercent of matching traces the rule fires on (1–100). Useful for sampling high-volume traffic.
Default: 100
statusObjectfalseThe starting status. Set to `PAUSED` if you want the rule created but not running yet.
Default: "ACTIVE"
targetingFiltersList<TargetingFilter>falseThe conditions a trace must meet to match. Leave empty to fire on every trace.
Default: []
targetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
actionsList<AutomationRuleActionInput>trueOne or two actions to run when the rule fires — for example, score the trace or add it to a dataset.
ParamTypeRequiredDescription
NamestringtrueA name for the rule, 1–255 characters. Must be unique within the project.
Description*stringfalseOptional free-form description.
SourceType*EventSchedulerTypefalseWhether the rule watches traces or sessions. Defaults to `TRACE`.
SamplingRate*intfalsePercent of matching traces the rule fires on (1–100). Useful for sampling high-volume traffic.
Default: 100
Status*AutomationRuleStatusfalseThe starting status. Set to `PAUSED` if you want the rule created but not running yet.
Default: "ACTIVE"
TargetingFilters*[]TargetingFilterfalseThe conditions a trace must meet to match. Leave empty to fire on every trace.
Default: []
TargetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
TargetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
TargetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
TargetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
Actions[]AutomationRuleActionInputtrueOne or two actions to run when the rule fires — for example, score the trace or add it to a dataset.

List rules

pageNum := 1limit := 50page, err := client.List(ctx, &ListAutomationRulesParams{	Page:  &pageNum,	Limit: &limit,})

Meta contains the pagination fields (Page, Limit, TotalItems, TotalPages). Asking for a page past the last one returns Data: [] — it's not an error.

Lists the rules in your project, paginated. You can page through results, search by name, and optionally filter to rules with a specific action type.

ParamTypeRequiredDescription
pagenumberfalse1-indexed page number (default 1)
Default: 1
limitnumberfalsePage size, max 100 (default 50)
Default: 50
searchstringfalseSubstring match on name + description (case-insensitive)
actionTypeAutomationRuleActionType
"ONLINE_EVAL" | "DATASET"
falseIf set, only returns rules that have at least one action of this type.
ParamTypeRequiredDescription
pageOptional[int]false1-indexed page number (default 1)
Default: 1
limitOptional[int]falsePage size, max 100 (default 50)
Default: 50
searchOptional[str]falseSubstring match on name + description (case-insensitive)
action_typeOptional[str]
"ONLINE_EVAL", "DATASET"
falseIf set, only returns rules that have at least one action of this type.
ParamTypeRequiredDescription
pageIntegerfalse1-indexed page number (default 1)
Default: 1
limitIntegerfalsePage size, max 100 (default 50)
Default: 50
searchStringfalseSubstring match on name + description (case-insensitive)
actionTypeString
"ONLINE_EVAL", "DATASET"
falseIf set, only returns rules that have at least one action of this type.
ParamTypeRequiredDescription
Page*intfalse1-indexed page number (default 1)
Default: 1
Limit*intfalsePage size, max 100 (default 50)
Default: 50
Search*stringfalseSubstring match on name + description (case-insensitive)
ActionType*string
"ONLINE_EVAL", "DATASET"
falseIf set, only returns rules that have at least one action of this type.

Get a rule by id

fetched, err := client.Get(ctx, ruleID)

Get an automation rule by id

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.

Update a rule

Use this to update rule-level fields like Name, Description, SamplingRate, or TargetingFilters. You can't change SourceType. To add or remove actions, use the action-level methods further down; to toggle per-metric routing, use UpdateAction() since metrics belong to the action, not the rule.

updateSamplingRate := 75updateDescription := "updated description"updated, err := client.Update(ctx, ruleID, &UpdateAutomationRuleBody{	SamplingRate: &updateSamplingRate,	Description:  &updateDescription,})

Updates the rule. Only the fields you send are changed — anything you leave out stays the same. A few things to know: - You can't change `sourceType`. - To add or remove actions, use the `/actions` endpoints below. To toggle per-metric human-review routing, use `PATCH /actions/{actionId}` (metrics belong to an action, not to the rule). - Pass `description: null` to clear the description. - `targetingFilters`, if you send it, replaces the whole filter list — send the full set you want, not a delta.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
namestringfalseNew rule name.
descriptionstring | nullfalseNew description. Pass `null` to clear it.
samplingRatenumberfalseNew sampling rate (1–100).
statusAutomationRuleStatusfalseNew status — `ACTIVE` or `PAUSED`.
targetingFiltersTargetingFilter[]falseNew targeting filters. Pass an empty array to clear.
targetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
nameOptional[str]falseNew rule name.
descriptionOptional[str]falseNew description. Pass `null` to clear it.
sampling_rateOptional[int]falseNew sampling rate (1–100).
statusOptional[AutomationRuleStatus]falseNew status — `ACTIVE` or `PAUSED`.
targeting_filtersOptional[list[TargetingFilterInput]]falseNew targeting filters. Pass an empty array to clear.
targeting_filters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targeting_filters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targeting_filters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targeting_filters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
nameStringfalseNew rule name.
descriptionStringfalseNew description. Pass `null` to clear it.
samplingRateIntegerfalseNew sampling rate (1–100).
statusAutomationRuleStatusfalseNew status — `ACTIVE` or `PAUSED`.
targetingFiltersList<TargetingFilter>falseNew targeting filters. Pass an empty array to clear.
targetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
targetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
targetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
targetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
Name*stringfalseNew rule name.
Description*stringfalseNew description. Pass `null` to clear it.
SamplingRate*intfalseNew sampling rate (1–100).
Status*AutomationRuleStatusfalseNew status — `ACTIVE` or `PAUSED`.
TargetingFilters*[]TargetingFilterfalseNew targeting filters. Pass an empty array to clear.
TargetingFilters.fieldNamestringtrueThe trace attribute to compare (for example `name`, `metadata.userId`, `input`, `output`).
TargetingFilters.operator"EQUALS" | "NOT_EQUALS" | "CONTAINS" | "NOT_CONTAINS" | "STARTS_WITH" | "ENDS_WITH" | "REGEX" | "IN" | "NOT_IN" | "GREATER_THAN" | "LESS_THAN" | "GREATER_THAN_OR_EQUAL" | "LESS_THAN_OR_EQUAL"trueThe comparison to run between `fieldName` and `value`.
TargetingFilters.valuestringtrueWhat to compare against. For `IN` / `NOT_IN`, pass a comma-separated list.
TargetingFilters.logicalOperator"AND" | "OR"falseHow this clause combines with the next one in the list.
Default: "AND"

Pause and resume

UpdateStatus() pauses or resumes a rule. It's a convenience shortcut over Update() — the effect is the same as calling Update() with Status: "PAUSED" or Status: "ACTIVE", but it reads more clearly at the call site.

// Pause the rule while iterating on evaluator config.paused, err := client.UpdateStatus(ctx, ruleID, &UpdateAutomationRuleStatusBody{	Status: AutomationRuleStatusPaused,})// ...and resume the rule when evaluator config is finalized.resumed, err := client.UpdateStatus(ctx, ruleID, &UpdateAutomationRuleStatusBody{	Status: AutomationRuleStatusActive,})

A convenience shortcut for pausing or resuming a rule. Same as `PATCH /automation-rules/{ruleId}` with just `{ status }`, but reads more clearly at the call site.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
statusAutomationRuleStatustrueThe new status — `ACTIVE` or `PAUSED`.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
statusAutomationRuleStatustrueThe new status — `ACTIVE` or `PAUSED`.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
statusAutomationRuleStatustrueThe new status — `ACTIVE` or `PAUSED`.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
StatusAutomationRuleStatustrueThe new status — `ACTIVE` or `PAUSED`.

Delete a rule

Deletes the rule and everything attached to it — actions, metrics, and targeting filters.

result, err := client.Delete(ctx, ruleID)

Deletes the rule and everything attached to it — actions, metrics, and targeting filters. Any evaluation results the rule already produced are kept.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.

Add an action

Add a second action to an existing rule — for example, attach a DATASET action to a rule that already runs ONLINE_EVAL. A rule can hold at most one action of each type, so adding a second ONLINE_EVAL (or DATASET) to a rule that already has one is rejected.

addActionMappingType := DatasetMappingTypeLlmOutputaddActionExtractionMode := DatasetExtractionModeSingleIoaddedAction, err := client.AddAction(ctx, ruleID, &AddAutomationRuleActionBody{	Action: DatasetActionInput{		Type: DatasetActionInputTypeDataset,		Config: DatasetActionConfigInput{			DatasetId:      datasetID,			MappingType:    &addActionMappingType,			ExtractionMode: &addActionExtractionMode,		},	},})

Returns the full updated rule, so you don't need a follow-up Get().

Adds one action to an existing rule. Pass the action as a nested `action` object — the same shape as an entry in `actions[]` when you create a rule. A rule can hold at most one action of each type, so adding a second action of the same type returns `409`.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionAutomationRuleActionInputtrueThe action to add. A rule can hold up to two actions.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
actionAutomationRuleActionInputtrueThe action to add. A rule can hold up to two actions.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
actionAutomationRuleActionInputtrueThe action to add. A rule can hold up to two actions.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
ActionAutomationRuleActionInputtrueThe action to add. A rule can hold up to two actions.

Update an action

Update an action's Config in place. For ONLINE_EVAL actions, you can optionally pass a Metrics slice to flip RouteToHumanReview on individual evaluators (up to 50 per call).

updateActionConcurrency := 8updateActionDelaySeconds := 120updatedAction, err := client.UpdateAction(ctx, ruleID, actionID, &UpdateAutomationRuleActionBody{	Action: OnlineEvalActionUpdateInput{		Type: OnlineEvalActionInputTypeOnlineEval,		Config: OnlineEvalActionConfigInput{			Concurrency:  &updateActionConcurrency,			DelaySeconds: &updateActionDelaySeconds,		},	},})

Updates the action's `config` in place. For `ONLINE_EVAL` actions you can also pass a `metrics` list to flip `routeToHumanReview` per metric — this endpoint is the only way to change those toggles.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionIdstringtrueThe action's id (returned in `actions[].id` on the rule).
actionAutomationRuleActionUpdateInputtrueThe fields to update on the action. Anything you leave out stays the same.
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
action_idstrtrueThe action's id (returned in `actions[].id` on the rule).
actionAutomationRuleActionUpdateInputtrueThe fields to update on the action. Anything you leave out stays the same.
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
actionIdStringtrueThe action's id (returned in `actions[].id` on the rule).
actionAutomationRuleActionUpdateInputtrueThe fields to update on the action. Anything you leave out stays the same.
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionIdstringtrueThe action's id (returned in `actions[].id` on the rule).
ActionAutomationRuleActionUpdateInputtrueThe fields to update on the action. Anything you leave out stays the same.

Delete an action

A rule always needs at least one action, so deleting the last remaining action returns 400. Delete the whole rule instead if that's what you want.

deletedActionResult, err := client.DeleteAction(ctx, ruleID, actionID)

A rule always needs at least one action. Deleting the last remaining action returns `409` — delete the whole rule instead.

ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionIdstringtrueThe action's id (returned in `actions[].id` on the rule).
ParamTypeRequiredDescription
rule_idstrtrueThe automation rule's id.
action_idstrtrueThe action's id (returned in `actions[].id` on the rule).
ParamTypeRequiredDescription
ruleIdStringtrueThe automation rule's id.
actionIdStringtrueThe action's id (returned in `actions[].id` on the rule).
ParamTypeRequiredDescription
ruleIdstringtrueThe automation rule's id.
actionIdstringtrueThe action's id (returned in `actions[].id` on the rule).

Complete example

Every step above, stitched together into one block you can copy and adapt. Fill in ruleID / actionID where a later step needs the id.

// 1. Set up the SDKimport (	"context"	"log"	aisdk "github.com/browserstack/ai-sdk-go")ctx := context.Background()publicKey := os.Getenv("AISDK_PUBLIC_KEY")secretKey := os.Getenv("AISDK_SECRET_KEY")sdk, err := aisdk.New(aisdk.WithCredentials(publicKey, secretKey))if err != nil {	log.Fatalf("aisdk.New: %v", err)}client := sdk.AutomationRule()// 2. Per-run variablesname := "Score production traces on latency evaluator"// 3. Create a rulesourceType := EventSchedulerTypeTracestatus := AutomationRuleStatusActivesamplingRate := 50mappingType := DatasetMappingTypeExpectedOutputextractionMode := DatasetExtractionModeSingleIoconcurrency := 2delaySeconds := 30routeToHumanReview := falserule, err := client.Create(ctx, &CreateAutomationRuleBody{	Name:         name,	SourceType:   &sourceType,	SamplingRate: &samplingRate,	Status:       &status,	Actions: []AutomationRuleActionInput{		OnlineEvalActionInput{			Type: OnlineEvalActionInputTypeOnlineEval,			Config: OnlineEvalActionConfigInput{				Concurrency:  &concurrency,				DelaySeconds: &delaySeconds,			},			Metrics: []OnlineEvalMetricInput{				{EvaluatorListId: evaluatorListID, RouteToHumanReview: &routeToHumanReview},			},		},		DatasetActionInput{			Type: DatasetActionInputTypeDataset,			Config: DatasetActionConfigInput{				DatasetId:      datasetID,				MappingType:    &mappingType,				ExtractionMode: &extractionMode,			},		},	},})// 4. Grab the rule id for later stepsruleID := rule.Id// 5. List rulespageNum := 1limit := 50page, err := client.List(ctx, &ListAutomationRulesParams{	Page:  &pageNum,	Limit: &limit,})// 6. Fetch a rule by idfetched, err := client.Get(ctx, ruleID)// 7. Update the ruleupdateSamplingRate := 75updateDescription := "updated description"updated, err := client.Update(ctx, ruleID, &UpdateAutomationRuleBody{	SamplingRate: &updateSamplingRate,	Description:  &updateDescription,})// 8. Pause and resume// Pause the rule while iterating on evaluator config.paused, err := client.UpdateStatus(ctx, ruleID, &UpdateAutomationRuleStatusBody{	Status: AutomationRuleStatusPaused,})// ...and resume the rule when evaluator config is finalized.resumed, err := client.UpdateStatus(ctx, ruleID, &UpdateAutomationRuleStatusBody{	Status: AutomationRuleStatusActive,})// 9. Add an actionaddActionMappingType := DatasetMappingTypeLlmOutputaddActionExtractionMode := DatasetExtractionModeSingleIoaddedAction, err := client.AddAction(ctx, ruleID, &AddAutomationRuleActionBody{	Action: DatasetActionInput{		Type: DatasetActionInputTypeDataset,		Config: DatasetActionConfigInput{			DatasetId:      datasetID,			MappingType:    &addActionMappingType,			ExtractionMode: &addActionExtractionMode,		},	},})// 10. Grab the action id for later stepsactionID := addedAction.Actions[0].Id// 11. Update an actionupdateActionConcurrency := 8updateActionDelaySeconds := 120updatedAction, err := client.UpdateAction(ctx, ruleID, actionID, &UpdateAutomationRuleActionBody{	Action: OnlineEvalActionUpdateInput{		Type: OnlineEvalActionInputTypeOnlineEval,		Config: OnlineEvalActionConfigInput{			Concurrency:  &updateActionConcurrency,			DelaySeconds: &updateActionDelaySeconds,		},	},})// 12. Delete an actiondeletedActionResult, err := client.DeleteAction(ctx, ruleID, actionID)// 13. Delete the ruleresult, err := client.Delete(ctx, ruleID)

Where to view results

Matched traces are processed on the same schedule as the rest of the ingestion pipeline. Here's where each action's output lands:

  • ONLINE_EVAL actions — scores show up on the trace or observation in the dashboard. See the Online Evaluations UI guide.
  • DATASET actions — matched items are added to the target dataset. See the Datasets UI guide.
  • Rule management — every rule you create through the SDK also shows up under Settings → Automation Rules. See the Automation Rules UI guide for filter syntax and the human-review routing flow.