---
title: "Create agent scenario"
method: POST
path: "/api/agent-scenarios"
tags: ["agent_scenarios"]
---

# Create agent scenario

`POST /api/agent-scenarios`

## Request

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

Add a scenario of the team's own: when the trigger text matches an incoming reply the agent follows this scenario (its own steps when it has them, else the classified scenario's playbook with the context over it). Takes effect from the next classify run; at most 20 of the team's own that are not Off. Born autopilot unless level says otherwise. A platform scenario is never created: edit it by key with update_agent_scenario.

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

## Request body

- CreateAgentScenarioRequest: Request body of `create_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, required: The scenario's name, 1..255 chars, the natural key inside the team.
  - `trigger` string, required: When the scenario applies, in plain language, written for an LLM to match against one inbound reply.
  - `context` string, nullable: The instructions over the playbook, any length; the compaction writes the copy the model reads after the save.
  - `steps` object[], nullable: The scenario's own steps; omit them and the classified scenario's playbook applies with the context over it.
    - `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': Default autopilot. off drafts no reply (the other steps still run; a task step hands the thread over). The 21st own scenario is a 429 limit_exceeded.
  - `conditions` object[]: With level conditional: the conditions in order (at most 6), the first that holds deciding; a lead condition needs its words.
    - `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`

`create` success envelope.

- CreateAgentScenarioResponse
  - `success` true, required
  - `operation` 'create', 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.
  - `already_exists` boolean, required
  - `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)
