---
title: "Update agent scenario"
method: PATCH
path: "/api/agent-scenarios/{sid}"
tags: ["agent_scenarios"]
---

# Update agent scenario

`PATCH /api/agent-scenarios/{sid}`

## Request

- Base URL: `https://beta.getsales.io/unibox/v1`
- URL: `https://beta.getsales.io/unibox/v1/api/agent-scenarios/{sid}`
- Auth: HTTP bearer and API key in header `Team-SID`

Edit a scenario: by sid (a row of the team's), or by platform key (the first edit bears the team's row). The steps (the list replaced whole: switch one off, reorder, delete, add, reword a step's instructions, its when, its parameters), the instructions over them (context), the level with its conditions (autopilot, copilot, conditional, off); a team's own scenario also its title and trigger. A locked step stays on as it is; a parameter outside its dictionary is a 422.

Contract:
- MCP tool `update_agent_scenario`, registry package `mcp.unibox/agent_scenarios`, mount `unibox.agent`.
- Operation `update`, response envelope `update`.
- Flags: none.

## Path parameters

- `sid` string, required: ub_sc_ sid or key: interested, meeting_request, info_request, referral, not_now, out_of_office, auto_reply, wrong_person, reschedule_request, cancel_request, other_low_signal, not_interested, objection, do_not_contact, followup_no_reply, signal_followup.

## Request body

- UpdateAgentScenarioRequest: Request body of `update_agent_scenario`.
  - `agent_sid` string: The AI SDR whose scenario it is (ub_ag_…); with a platform key, which agent's version. Left out, the team's default agent.
  - `title` string: The team's own scenario only: a platform scenario's name is the platform's (422).
  - `trigger` string: The team's own scenario only (422 on a platform scenario).
  - `context` string, nullable: The instructions over the playbook; null clears them.
  - `steps` object[], nullable: FULL-REPLACE of the step list: on a platform scenario the fork (null drops it, the seed applies again; a locked step stays on, as it is); on the team's own scenario its steps.
    - `id` string, required
    - `kind` 'react' | 'move_stage' | 'like_post' | 'send_message' | 'wait_for_reply' | 'wait_until' | 'create_task' | 'find_people' | 'reach_objective' | 'use_playbook' | 'resume_orchestration' | 'stoplist_person', required
    - `enabled` boolean
    - `locked` boolean
    - `when` string, nullable
    - `instructions` string, nullable
    - `params` object
  - `level` 'autopilot' | 'copilot' | 'conditional' | 'off': The level: autopilot, copilot, conditional (with conditions) or off. On a platform key the first edit bears the team's row; reset_agent_scenario puts the seed's level back.
  - `conditions` object[], nullable: FULL-REPLACE of a Conditional level's conditions, in order (at most 6); null clears them. Read on every reply: the first that holds decides, Autopilot otherwise.
    - `kind` 'lead' | 'no_answer': Default lead.
    - `when` string, nullable: Required on a lead condition; ignored on the built-in one.
    - `then` 'copilot' | 'off': Default copilot.

## Response `200`

`update` success envelope.

- UpdateAgentScenarioResponse
  - `success` true, required
  - `operation` 'update', required
  - `item` object, required
    - `sid` string, nullable, required: Agent scenario sid (ub_sc_…); null on a platform scenario the team never touched (no row yet: address it by scenario_key).
    - `team_sid` string, required: Owning team (ts_tm_…, external - gs.service.id).
    - `agent_sid` string, nullable, required: The AI SDR the row belongs to (ub_ag_…; block 10, 2026-10-30): its versions of the platform scenarios and its own rows. A seed item names the agent it was read for.
    - `scenario_key` string, nullable, required: A platform scenario's key; null = the agent's own scenario.
    - `title` string, nullable, required: The team's own scenario: its name, 1..255 chars, the natural key inside the team. A platform scenario: null (the platform's title is in `seed`).
    - `trigger` string, nullable, required: The team's own scenario: the "when this applies" text, 1..2048 chars, read by the classify verbatim against the incoming reply. A platform scenario: null (the classify key decides it).
    - `context` string, nullable, required: The instructions over the playbook, a person's text of any length (max 32768).
    - `context_compact` string, nullable, required: [ro] The copy the model reads, written by the compaction after a save that moved the context; null until it lands.
    - `steps` object[], nullable, required: A platform row: the team's fork of the seed's step list, null = the seed's list applies. A team's own row: its own steps, null = the classified scenario's playbook applies with the context over it.
      - `id` string, required: Stable inside the playbook (react, stage, reply, wait, followup, last_wait, task on the platform seeds); minted for an added step.
      - `kind` 'react' | 'move_stage' | 'like_post' | 'send_message' | 'wait_for_reply' | 'wait_until' | 'create_task' | 'find_people' | 'reach_objective' | 'use_playbook' | 'resume_orchestration' | 'stoplist_person', required
      - `enabled` boolean, required: Off: never planned under this scenario.
      - `locked` boolean, required: Platform only: the step cannot be switched off, moved or removed (the stoplist step of do_not_contact).
      - `when` string, nullable, required: "Plan it when ...": the condition the planning turn judges; null = always.
      - `instructions` string, nullable, required: What the step must do or say, the text the model reads; the product copy a team reads IS the prompt text.
      - `params` object, required: The kind's product parameters, each a value of its dictionary (see above).
    - `steps_base_version` integer, nullable, required: A platform row with a fork: the seed version the fork was taken from (compare with seed.version: "the default changed").
    - `level` 'autopilot' | 'copilot' | 'conditional' | 'off', nullable, required: The row's level (block AC4): autopilot, copilot, conditional or off; null on a platform row that keeps the seed's (playbook.level says which stands). A team's own row is born autopilot.
    - `conditions` object[], nullable, required: The row's conditions when its level is conditional, in order (at most 6); null otherwise.
      - `kind` 'lead' | 'no_answer', required: lead: the team's words, judged by the classifier; no_answer: the built-in one, a question Knowledge has no answer for, read by unibox from the turn's missing-answer signal.
      - `when` string, nullable, required: A lead condition's words completing "when the lead ..." ("mentions a contract or a security review"), 3..255 chars; null on the built-in one.
      - `then` 'copilot' | 'off', required: What the reply gets when the condition holds: copilot (drafted for a person's OK) or off (nothing drafted).
    - `created_by` object, nullable, required: Actor that wrote the row; null on a platform scenario with no row.
      - `actor_type` 'user' | 'support' | 'api_key' | 'system' | 'agent', required
      - `actor_sid` string, nullable, required
      - `team_sid` string, required
      - `actor_name` string, nullable: The OAuth client that acted ("Claude", "n8n"); null for a user, an API key or a system job.
      - `oauth_client_sid` string, nullable: The acting OAuth client (id_oc_*); null off the OAuth path.
      - `reason` string, nullable: Why a system actor wrote the row (snapshot_capture_job, ...); null otherwise.
      - `permissions` object, required: Internal audit context: the grant set the actor held at write time. Not a contract.
      - `cluster_id` integer, nullable: Internal audit context: the cluster that served the write.
      - `trace_id` string, nullable: Internal audit context: the trace id of the request that wrote the row.
    - `match_count` integer, required: A team's own scenario: lifetime matches, bumped asynchronously after each classify run.
    - `last_matched_at` string, nullable, required: ISO 8601 UTC of the most recent match; null = never matched.
    - `deleted_by` object, nullable, required
      - `actor_type` 'user' | 'support' | 'api_key' | 'system' | 'agent', required
      - `actor_sid` string, nullable, required
      - `team_sid` string, required
      - `actor_name` string, nullable: The OAuth client that acted ("Claude", "n8n"); null for a user, an API key or a system job.
      - `oauth_client_sid` string, nullable: The acting OAuth client (id_oc_*); null off the OAuth path.
      - `reason` string, nullable: Why a system actor wrote the row (snapshot_capture_job, ...); null otherwise.
      - `permissions` object, required: Internal audit context: the grant set the actor held at write time. Not a contract.
      - `cluster_id` integer, nullable: Internal audit context: the cluster that served the write.
      - `trace_id` string, nullable: Internal audit context: the trace id of the request that wrote the row.
    - `created_at` string, nullable, required
    - `updated_at` string, nullable, required
    - `deleted_at` string, nullable, required
    - `source` 'platform' | 'edited' | 'custom', required: platform = the seed as it ships; edited = the team's version of a platform scenario; custom = the team's own.
    - `seed` object, nullable, required: [ro] The platform seed under the key (null on a team's own scenario).
      - `version` integer, required
      - `title` string, required
      - `trigger` string, required: The classify's definition of the scenario, in a reader's words; not editable.
      - `goal` string, required
      - `max_steps` integer, required
      - `steps` object[], required: The seed's whole step list, the ones off by default included.
        - `id` string, required: Stable inside the playbook (react, stage, reply, wait, followup, last_wait, task on the platform seeds); minted for an added step.
        - `kind` 'react' | 'move_stage' | 'like_post' | 'send_message' | 'wait_for_reply' | 'wait_until' | 'create_task' | 'find_people' | 'reach_objective' | 'use_playbook' | 'resume_orchestration' | 'stoplist_person', required
        - `enabled` boolean, required: Off: never planned under this scenario.
        - `locked` boolean, required: Platform only: the step cannot be switched off, moved or removed (the stoplist step of do_not_contact).
        - `when` string, nullable, required: "Plan it when ...": the condition the planning turn judges; null = always.
        - `instructions` string, nullable, required: What the step must do or say, the text the model reads; the product copy a team reads IS the prompt text.
        - `params` object, required: The kind's product parameters, each a value of its dictionary (see above).
    - `playbook` object, nullable, required: [ro] The effective playbook: the seed or the fork, enabled steps in order, the instructions over them. Null on a team's own scenario without steps of its own.
      - `source` 'platform' | 'edited' | 'custom', required
      - `key` string, nullable, required: The scenario key the playbook plays for; null only on a team's own scenario with steps of its own.
      - `version` integer, required: The platform seed version the steps were taken from.
      - `goal` string, required
      - `max_steps` integer, required: The ceiling the plan tool holds: the seed's plus the steps the team added.
      - `steps` object[], required: The enabled steps in order.
        - `id` string, required: Stable inside the playbook (react, stage, reply, wait, followup, last_wait, task on the platform seeds); minted for an added step.
        - `kind` 'react' | 'move_stage' | 'like_post' | 'send_message' | 'wait_for_reply' | 'wait_until' | 'create_task' | 'find_people' | 'reach_objective' | 'use_playbook' | 'resume_orchestration' | 'stoplist_person', required
        - `enabled` boolean, required: Off: never planned under this scenario.
        - `locked` boolean, required: Platform only: the step cannot be switched off, moved or removed (the stoplist step of do_not_contact).
        - `when` string, nullable, required: "Plan it when ...": the condition the planning turn judges; null = always.
        - `instructions` string, nullable, required: What the step must do or say, the text the model reads; the product copy a team reads IS the prompt text.
        - `params` object, required: The kind's product parameters, each a value of its dictionary (see above).
      - `instructions` string, nullable, required: The team's instructions over the steps (the row's compact context).
      - `level` 'autopilot' | 'copilot' | 'conditional' | 'off', required: The scenario's level as it stands: the row's, else the seed's (block AC4).
      - `conditions` object[], required: A Conditional level's conditions in order; empty on any other level.
        - `kind` 'lead' | 'no_answer', required: lead: the team's words, judged by the classifier; no_answer: the built-in one, a question Knowledge has no answer for, read by unibox from the turn's missing-answer signal.
        - `when` string, nullable, required: A lead condition's words completing "when the lead ..." ("mentions a contract or a security review"), 3..255 chars; null on the built-in one.
        - `then` 'copilot' | 'off', required: What the reply gets when the condition holds: copilot (drafted for a person's OK) or off (nothing drafted).
    - `default_changed` boolean, required: [ro] True when the platform seed moved past the version the team's fork was taken from: compare and reset, or keep yours.
  - `updated_fields` string[], required
  - `previous_values` object, required
  - `kept_fields` string[]: The fields this write did not change because the person's own value stands on them (stamped person); read the item for what landed.
  - `meta` object, required
    - `trace_id` string, required: UUID v7; same 128-bit value as the X-Trace-Id header.
    - `span_id` string, required: 16 hex chars, root span of this request.
    - `timestamp` string, required: ISO 8601 UTC (Y-m-dTH:i:sZ), response time.
    - `duration_ms` integer, required: Server-side wall clock.
    - `team_sid` string, nullable: The team this call ran in (the token team, or the team_sid override). Null when unauthenticated; absent from pre-2026-08-20 backends.
    - `actor_type` string, nullable: user | agent | api_key | system. Null when unauthenticated; absent from pre-2026-08-20 backends.

## Other responses

- `4XX`: MCP error envelope. `error.code` is one of validation_failed, nothing_to_update, not_found, relation_not_found, invalid_transition, limit_exceeded, payment_required, duplicate_rejected, conflict, delete_blocked, unauthorized, forbidden, rate_limited, not_implemented.
- `5XX`: MCP error envelope with `error.code` internal_error or service_unavailable.

---

[API](https://skmtc.dev/getsales/apis/getsales-public-contract-gs-service-unibox.md) - [All operations](https://skmtc.dev/getsales/apis/getsales-public-contract-gs-service-unibox/llms.txt) - [OpenAPI document](https://skmtc.dev/getsales/apis/getsales-public-contract-gs-service-unibox/revisions/8f1bc317897f?raw)
