# Agents Commands

> See [Agents module docs](../../modules/agents) for permissions and data model.

# Agents Commands

See [Agents module docs](../../modules/agents) for permissions and data model.

### `soat create-agent`

Create an agent

- Method: `POST`
- Path: `/api/v1/agents`

#### Usage

```bash
soat create-agent
```

#### Options

##### `--project-id`

Public ID of the project

- Source: `body`
- Required: no
- Type: `string`

##### `--ai-provider-id`

Public ID of the AI provider to pin. Mutually exclusive with `model_route_id`.

- Source: `body`
- Required: no
- Type: `string`

##### `--model-route-id`

Public ID of a model route in the same project. The agent's completion model is then resolved through the route's ordered targets with failover. Mutually exclusive with `ai_provider_id` and `model`.

- Source: `body`
- Required: no
- Type: `string`

##### `--name`

—

- Source: `body`
- Required: no
- Type: `string`

##### `--instructions`

—

- Source: `body`
- Required: no
- Type: `string`

##### `--model`

—

- Source: `body`
- Required: no
- Type: `string`

##### `--tool-bindings`

Tools to attach, one binding object per tool — the only attachment field. An entry is either a reference (`\{ "tool_id": … \}`) or an inline definition (`\{ "tool": … \}`). See [Tool Bindings](/docs/modules/agents#tool-bindings).

- Source: `body`
- Required: no
- Type: `array<object>`

##### `--max-steps`

—

- Source: `body`
- Required: no
- Type: `integer`

##### `--tool-choice`

Tool choice strategy. Accepts a string (`"auto"`, `"required"`) or an object (`\{ "type": "tool", "tool_name": "my_tool" \}`). A forcing value (`"required"` or the object form) forbids a final assistant message on every step of every turn, including a resumed or continued one, so it requires a `has_tool_call` entry in `stop_conditions` — otherwise the write is refused with `FORCED_TOOL_CHOICE_CANNOT_STOP`.

- Source: `body`
- Required: no
- Type: `unknown`

##### `--stop-conditions`

Conditions that end the agent's work early, on top of `max_steps`. Two scopes:  `\{"type": "has_tool_call", "tool_name": "<resolved tool name>"\}` ends the **turn** after the step that calls the named tool. It narrows when the loop ends — it never lets it run past `max_steps`.  `\{"type": "max_chain_generations", "max_generations": <n>\}` bounds the **continuation chain** instead: once the chain has spawned that many generations, further resumptions stop with `chain_limit` rather than extending it. It never shortens a turn. The effective ceiling is the smaller of this and the deployment's `MAX_CONTINUATION_CHAIN_GENERATIONS`, so an agent can be stricter than the platform but never looser.  An unknown `type`, a `has_tool_call` without a `tool_name`, a `max_chain_generations` whose `max_generations` is not a positive integer, or a non-object entry is rejected with 400.

- Source: `body`
- Required: no
- Type: `array<object>`

##### `--active-tool-ids`

—

- Source: `body`
- Required: no
- Type: `array<string>`

##### `--guardrail-ids`

Guardrails attached at the agent scope.

- Source: `body`
- Required: no
- Type: `array<string>`

##### `--step-rules`

—

- Source: `body`
- Required: no
- Type: `array<object>`

##### `--boundary-policy`

—

- Source: `body`
- Required: no
- Type: `object`

##### `--temperature`

—

- Source: `body`
- Required: no
- Type: `number`

##### `--knowledge-config`

—

- Source: `body`
- Required: no
- Type: `object`

##### `--output-schema`

JSON Schema describing the structured object the model must return. When set, non-streaming generations constrain output to this schema and the parsed value is returned as `output.object`. The schema is enforced on the way back, not just sent to the model: an object that violates it fails the generation with 502 `OUTPUT_SCHEMA_VALIDATION_FAILED`, naming the violated field. Constraints beyond `required`/`type` (`minLength`, `enum`, `pattern`, `minItems`) are honored and are what reject a structurally valid but degenerate answer. See the Structured Output section in the Agents module docs.

- Source: `body`
- Required: no
- Type: `object`

##### `--max-context-messages`

Maximum number of recent messages included in the context window. Null means no limit.

- Source: `body`
- Required: no
- Type: `integer`

##### `--single-session-per-actor`

When true, only one open session per actor_id is allowed for this agent.

- Source: `body`
- Required: no
- Type: `boolean`

##### `--trace-content-mode`

Zero-retention opt-in for this agent. `null` inherits the project's setting; `none` means trace and generation content is never written. Setting `full` under a project whose own mode is `none` is refused with 400 — the project is a floor an agent may only tighten.

- Source: `body`
- Required: no
- Type: `enum("full", "none", null)`

##### `--on-approval-expiry`

What happens when one of this agent's held tool calls expires un-approved. `null` (the default) and `terminate` end the chain there — the expired approval, its `approvals.expired` event and the auto-filed `approval_expired` exception are the whole record. `react` spawns a continuation that reports the staleness to the agent, for an agent that acts on it.

- Source: `body`
- Required: no
- Type: `enum("terminate", "react", null)`

##### `--version-label`

Optional tag for the config version this write archives (e.g. `initial`). Annotates the version only — it is not stored on the agent and is not part of the config, so labelling a change is never itself a change.

- Source: `body`
- Required: no
- Type: `string \| null`
- Example: `initial`

### `soat list-agents`

List agents

- Method: `GET`
- Path: `/api/v1/agents`

#### Usage

```bash
soat list-agents
```

#### Options

##### `--project-id`

Project public ID to filter by

- Source: `query`
- Required: no
- Type: `string`

##### `--limit`

Maximum number of results to return

- Source: `query`
- Required: no
- Type: `integer`
- Default: `50`

##### `--offset`

Number of results to skip

- Source: `query`
- Required: no
- Type: `integer`
- Default: `0`

### `soat get-agent`

Get an agent

- Method: `GET`
- Path: `/api/v1/agents/{agent_id}`

#### Usage

```bash
soat get-agent --agent-id <string>
```

#### Options

##### `--agent-id`

—

- Source: `path`
- Required: yes
- Type: `string`

### `soat update-agent`

Update an agent

- Method: `PUT`
- Path: `/api/v1/agents/{agent_id}`

#### Usage

```bash
soat update-agent --agent-id <string>
```

#### Options

##### `--agent-id`

—

- Source: `path`
- Required: yes
- Type: `string`

##### `--ai-provider-id`

—

- Source: `body`
- Required: no
- Type: `string \| null`

##### `--model-route-id`

Model route in the same project. Mutually exclusive with `ai_provider_id` and `model`; set to null to clear.

- Source: `body`
- Required: no
- Type: `string \| null`

##### `--name`

—

- Source: `body`
- Required: no
- Type: `string \| null`

##### `--instructions`

—

- Source: `body`
- Required: no
- Type: `string \| null`

##### `--model`

—

- Source: `body`
- Required: no
- Type: `string \| null`

##### `--tool-bindings`

Tools attached to the agent — the only attachment field. Replaces the whole binding list; set to `null` to clear. See [Tool Bindings](/docs/modules/agents#tool-bindings).

- Source: `body`
- Required: no
- Type: `array<object>`

##### `--max-steps`

—

- Source: `body`
- Required: no
- Type: `integer \| null`

##### `--tool-choice`

Tool choice strategy. Accepts a string (`"auto"`, `"required"`) or an object (`\{ "type": "tool", "tool_name": "my_tool" \}`). A forcing value (`"required"` or the object form) forbids a final assistant message on every step of every turn, including a resumed or continued one, so it requires a `has_tool_call` entry in `stop_conditions` — otherwise the write is refused with `FORCED_TOOL_CHOICE_CANNOT_STOP`.

- Source: `body`
- Required: no
- Type: `unknown \| null`

##### `--stop-conditions`

Conditions that end the agent's work early, on top of `max_steps`. Two scopes:  `\{"type": "has_tool_call", "tool_name": "<resolved tool name>"\}` ends the **turn** after the step that calls the named tool. It narrows when the loop ends — it never lets it run past `max_steps`.  `\{"type": "max_chain_generations", "max_generations": <n>\}` bounds the **continuation chain** instead: once the chain has spawned that many generations, further resumptions stop with `chain_limit` rather than extending it. It never shortens a turn. The effective ceiling is the smaller of this and the deployment's `MAX_CONTINUATION_CHAIN_GENERATIONS`, so an agent can be stricter than the platform but never looser.  An unknown `type`, a `has_tool_call` without a `tool_name`, a `max_chain_generations` whose `max_generations` is not a positive integer, or a non-object entry is rejected with 400.

- Source: `body`
- Required: no
- Type: `array<object>`

##### `--active-tool-ids`

—

- Source: `body`
- Required: no
- Type: `array<string>`

##### `--guardrail-ids`

Guardrails attached at the agent scope.

- Source: `body`
- Required: no
- Type: `array<string>`

##### `--step-rules`

—

- Source: `body`
- Required: no
- Type: `array<object>`

##### `--boundary-policy`

—

- Source: `body`
- Required: no
- Type: `object`

##### `--temperature`

—

- Source: `body`
- Required: no
- Type: `number \| null`

##### `--knowledge-config`

—

- Source: `body`
- Required: no
- Type: `object`

##### `--output-schema`

JSON Schema describing the structured object the model must return. When set, non-streaming generations constrain output to this schema and the parsed value is returned as `output.object`. The schema is enforced on the way back, not just sent to the model: an object that violates it fails the generation with 502 `OUTPUT_SCHEMA_VALIDATION_FAILED`, naming the violated field. Constraints beyond `required`/`type` (`minLength`, `enum`, `pattern`, `minItems`) are honored and are what reject a structurally valid but degenerate answer. See the Structured Output section in the Agents module docs.

- Source: `body`
- Required: no
- Type: `object`

##### `--max-context-messages`

Maximum number of recent messages included in the context window. Null means no limit.

- Source: `body`
- Required: no
- Type: `integer \| null`

##### `--single-session-per-actor`

When true, only one open session per actor_id is allowed for this agent.

- Source: `body`
- Required: no
- Type: `boolean \| null`

##### `--trace-content-mode`

Zero-retention opt-in for this agent. `null` inherits the project's setting; `none` means trace and generation content is never written. Setting `full` under a project whose own mode is `none` is refused with 400.

- Source: `body`
- Required: no
- Type: `enum("full", "none", null)`

##### `--on-approval-expiry`

What happens when one of this agent's held tool calls expires un-approved. `null` (the default) and `terminate` end the chain there — the expired approval, its `approvals.expired` event and the auto-filed `approval_expired` exception are the whole record. `react` spawns a continuation that reports the staleness to the agent, for an agent that acts on it.

- Source: `body`
- Required: no
- Type: `enum("terminate", "react", null)`

##### `--version-label`

Optional tag for the config version this write archives (e.g. `pre-tone-change`). Annotates the version only — it is not stored on the agent and is not part of the config, so labelling a change is never itself a change. Ignored when the write changes nothing, since no version is created.

- Source: `body`
- Required: no
- Type: `string \| null`
- Example: `pre-tone-change`

### `soat patch-agent`

Partially update an agent

- Method: `PATCH`
- Path: `/api/v1/agents/{agent_id}`

#### Usage

```bash
soat patch-agent --agent-id <string>
```

#### Options

##### `--agent-id`

—

- Source: `path`
- Required: yes
- Type: `string`

##### `--ai-provider-id`

—

- Source: `body`
- Required: no
- Type: `string \| null`

##### `--model-route-id`

Model route in the same project. Mutually exclusive with `ai_provider_id` and `model`; set to null to clear.

- Source: `body`
- Required: no
- Type: `string \| null`

##### `--name`

—

- Source: `body`
- Required: no
- Type: `string \| null`

##### `--instructions`

—

- Source: `body`
- Required: no
- Type: `string \| null`

##### `--model`

—

- Source: `body`
- Required: no
- Type: `string \| null`

##### `--tool-bindings`

Tools attached to the agent — the only attachment field. Replaces the whole binding list; set to `null` to clear. See [Tool Bindings](/docs/modules/agents#tool-bindings).

- Source: `body`
- Required: no
- Type: `array<object>`

##### `--max-steps`

—

- Source: `body`
- Required: no
- Type: `integer \| null`

##### `--tool-choice`

Tool choice strategy. Accepts a string (`"auto"`, `"required"`) or an object (`\{ "type": "tool", "tool_name": "my_tool" \}`). A forcing value (`"required"` or the object form) forbids a final assistant message on every step of every turn, including a resumed or continued one, so it requires a `has_tool_call` entry in `stop_conditions` — otherwise the write is refused with `FORCED_TOOL_CHOICE_CANNOT_STOP`.

- Source: `body`
- Required: no
- Type: `unknown \| null`

##### `--stop-conditions`

Conditions that end the agent's work early, on top of `max_steps`. Two scopes:  `\{"type": "has_tool_call", "tool_name": "<resolved tool name>"\}` ends the **turn** after the step that calls the named tool. It narrows when the loop ends — it never lets it run past `max_steps`.  `\{"type": "max_chain_generations", "max_generations": <n>\}` bounds the **continuation chain** instead: once the chain has spawned that many generations, further resumptions stop with `chain_limit` rather than extending it. It never shortens a turn. The effective ceiling is the smaller of this and the deployment's `MAX_CONTINUATION_CHAIN_GENERATIONS`, so an agent can be stricter than the platform but never looser.  An unknown `type`, a `has_tool_call` without a `tool_name`, a `max_chain_generations` whose `max_generations` is not a positive integer, or a non-object entry is rejected with 400.

- Source: `body`
- Required: no
- Type: `array<object>`

##### `--active-tool-ids`

—

- Source: `body`
- Required: no
- Type: `array<string>`

##### `--guardrail-ids`

Guardrails attached at the agent scope.

- Source: `body`
- Required: no
- Type: `array<string>`

##### `--step-rules`

—

- Source: `body`
- Required: no
- Type: `array<object>`

##### `--boundary-policy`

—

- Source: `body`
- Required: no
- Type: `object`

##### `--temperature`

—

- Source: `body`
- Required: no
- Type: `number \| null`

##### `--knowledge-config`

—

- Source: `body`
- Required: no
- Type: `object`

##### `--output-schema`

JSON Schema describing the structured object the model must return. When set, non-streaming generations constrain output to this schema and the parsed value is returned as `output.object`. The schema is enforced on the way back, not just sent to the model: an object that violates it fails the generation with 502 `OUTPUT_SCHEMA_VALIDATION_FAILED`, naming the violated field. Constraints beyond `required`/`type` (`minLength`, `enum`, `pattern`, `minItems`) are honored and are what reject a structurally valid but degenerate answer. See the Structured Output section in the Agents module docs.

- Source: `body`
- Required: no
- Type: `object`

##### `--max-context-messages`

Maximum number of recent messages included in the context window. Null means no limit.

- Source: `body`
- Required: no
- Type: `integer \| null`

##### `--single-session-per-actor`

When true, only one open session per actor_id is allowed for this agent.

- Source: `body`
- Required: no
- Type: `boolean \| null`

##### `--trace-content-mode`

Zero-retention opt-in for this agent. `null` inherits the project's setting; `none` means trace and generation content is never written. Setting `full` under a project whose own mode is `none` is refused with 400.

- Source: `body`
- Required: no
- Type: `enum("full", "none", null)`

##### `--on-approval-expiry`

What happens when one of this agent's held tool calls expires un-approved. `null` (the default) and `terminate` end the chain there — the expired approval, its `approvals.expired` event and the auto-filed `approval_expired` exception are the whole record. `react` spawns a continuation that reports the staleness to the agent, for an agent that acts on it.

- Source: `body`
- Required: no
- Type: `enum("terminate", "react", null)`

##### `--version-label`

Optional tag for the config version this write archives (e.g. `pre-tone-change`). Annotates the version only — it is not stored on the agent and is not part of the config, so labelling a change is never itself a change. Ignored when the write changes nothing, since no version is created.

- Source: `body`
- Required: no
- Type: `string \| null`
- Example: `pre-tone-change`

### `soat delete-agent`

Delete an agent

- Method: `DELETE`
- Path: `/api/v1/agents/{agent_id}`

#### Usage

```bash
soat delete-agent --agent-id <string>
```

#### Options

##### `--agent-id`

—

- Source: `path`
- Required: yes
- Type: `string`

##### `--force`

When `true`, deletes the agent's dependent generations and traces instead of returning `409 AGENT_HAS_DEPENDENTS`. 

- Source: `query`
- Required: no
- Type: `boolean`
- Default: `false`

### `soat create-agent-generation`

Run an agent generation

- Method: `POST`
- Path: `/api/v1/agents/{agent_id}/generate`

#### Usage

```bash
soat create-agent-generation --agent-id <string> --messages <array<object>>
```

#### Options

##### `--agent-id`

—

- Source: `path`
- Required: yes
- Type: `string`

##### `--wait`

When omitted or `false` (default), the generation runs in the background and `202 Accepted` is returned immediately with a `generation_id` to poll. Pass `true` to block until the generation settles and receive the result. Mutually exclusive with `stream: true`. A `builtin` tool call always waits.

- Source: `query`
- Required: no
- Type: `boolean`
- Default: `false`

##### `--messages`

—

- Source: `body`
- Required: yes
- Type: `array<object>`

##### `--stream`

When true the response is an SSE stream

- Source: `body`
- Required: no
- Type: `boolean`
- Default: `false`

##### `--trace-id`

Optional trace ID to group generations. Each generation appends its own steps to the trace's steps object, and `step_count` covers them all.

- Source: `body`
- Required: no
- Type: `string`

##### `--parent-trace-id`

The trace ID of the parent agent generation that triggered this one (for agent-to-agent calls)

- Source: `body`
- Required: no
- Type: `string \| null`

##### `--root-trace-id`

The trace ID of the root generation in the call chain; if omitted, this generation is the root

- Source: `body`
- Required: no
- Type: `string \| null`

##### `--max-call-depth`

Maximum nested agent-call depth; 0 short-circuits with a depth-guard response

- Source: `body`
- Required: no
- Type: `integer`
- Default: `10`

##### `--tool-context`

Key-value pairs forwarded as `X-Soat-Context-<key>` headers on every `http`, `mcp` and `builtin` tool call in this generation. The header name is the deployment's configured context prefix (`X-Soat-Context-` by default) plus the key verbatim — no character is re-cased. Keys are never case-converted — they round-trip exactly as sent. An invalid or colliding key is rejected with `400 INVALID_TOOL_CONTEXT_KEY`.

- Source: `body`
- Required: no
- Type: `object<string, string>`

##### `--action-id`

Logical action label recorded on the generation's usage meter, so spend can be rolled up per action (e.g. an A/B/C/D operating action).

- Source: `body`
- Required: no
- Type: `string`

##### `--guardrail-context`

Caller-supplied guardrail context (the `context.*` namespace guard and class expressions read at tool-dispatch time). Free-form and never interpreted by the platform; a guardrail may combine it with a `context_tool` per its `context_mode`. See the guardrails module.

- Source: `body`
- Required: no
- Type: `object<string, unknown>`

##### `--metadata`

Caller-supplied key/value metadata attached to the generation record for per-run audit attribution (e.g. the knowledge-corpus version that produced this action). Round-trips verbatim when the generation is fetched via the generations API. The bag is caller-owned and no key is reserved: server-owned state (usage attribution, the served agent version, the model route's record, the extraction summary) lives in its own top-level generation fields and cannot be written from here. Use the request's own `action_id` field to set the usage-attribution label.

- Source: `body`
- Required: no
- Type: `object<string, unknown>`

##### `--extract`

Per-turn override of the agent's `knowledge_config.extraction` default. Omit to follow the agent's stored config. Set `false` to suppress automatic memory extraction for this turn (e.g. an operational or tool-listing turn that would only add noise to a curated memory). Set `true` to force extraction on for this turn even when the agent does not enable it by default, provided the agent has a `write_memory_id`. Has no effect on streaming or `requires_action` turns, which never extract.

- Source: `body`
- Required: no
- Type: `boolean`

##### `--knowledge-config`

Per-generation knowledge retrieval override. Array filters (memory_ids, memory_tags, document_ids, document_paths) are unioned with the agent's stored knowledge_config; scalar fields (min_score, limit) use the per-generation value when present.

- Source: `body`
- Required: no
- Type: `object`

### `soat submit-agent-tool-outputs`

Submit tool outputs for a paused generation

- Method: `POST`
- Path: `/api/v1/agents/{agent_id}/generate/{generation_id}/tool-outputs`

#### Usage

```bash
soat submit-agent-tool-outputs --agent-id <string> --generation-id <string> --tool-outputs <array<object>>
```

#### Options

##### `--agent-id`

—

- Source: `path`
- Required: yes
- Type: `string`

##### `--generation-id`

—

- Source: `path`
- Required: yes
- Type: `string`

##### `--tool-outputs`

—

- Source: `body`
- Required: yes
- Type: `array<object>`

### `soat list-agent-versions`

List an agent's config versions

- Method: `GET`
- Path: `/api/v1/agents/{agent_id}/versions`

#### Usage

```bash
soat list-agent-versions --agent-id <string>
```

#### Options

##### `--agent-id`

—

- Source: `path`
- Required: yes
- Type: `string`

##### `--limit`

Maximum number of results to return

- Source: `query`
- Required: no
- Type: `integer`
- Default: `50`

##### `--offset`

Number of results to skip

- Source: `query`
- Required: no
- Type: `integer`
- Default: `0`

### `soat get-agent-version`

Get an archived agent config version

- Method: `GET`
- Path: `/api/v1/agents/{agent_id}/versions/{version}`

#### Usage

```bash
soat get-agent-version --agent-id <string> --version <integer>
```

#### Options

##### `--agent-id`

—

- Source: `path`
- Required: yes
- Type: `string`

##### `--version`

—

- Source: `path`
- Required: yes
- Type: `integer`

### `soat restore-agent-version`

Restore an archived config as a new version

- Method: `POST`
- Path: `/api/v1/agents/{agent_id}/versions/{version}/restore`

#### Usage

```bash
soat restore-agent-version --agent-id <string> --version <integer>
```

#### Options

##### `--agent-id`

—

- Source: `path`
- Required: yes
- Type: `string`

##### `--version`

—

- Source: `path`
- Required: yes
- Type: `integer`

##### `--label`

Tag for the version this restore creates. Defaults to `restored from v\{version\}`.

- Source: `body`
- Required: no
- Type: `string`
- Example: `rollback-incident-42`

### `soat set-agent-release`

Set or replace a staged rollout

- Method: `PUT`
- Path: `/api/v1/agents/{agent_id}/release`

#### Usage

```bash
soat set-agent-release --agent-id <string> --stable-version <integer> --canary-version <integer> --canary-percent <integer>
```

#### Options

##### `--agent-id`

—

- Source: `path`
- Required: yes
- Type: `string`

##### `--stable-version`

An existing version to serve as the baseline

- Source: `body`
- Required: yes
- Type: `integer`
- Example: `3`

##### `--canary-version`

An existing version to trial. Must differ from `stable_version`.

- Source: `body`
- Required: yes
- Type: `integer`
- Example: `4`

##### `--canary-percent`

Percentage of traffic to assign to `canary_version`

- Source: `body`
- Required: yes
- Type: `integer`
- Example: `20`

##### `--promotion-gate`

Eval to gate promotion on. It must belong to this project and evaluate this agent; anything else is a `400`. Omit it, or send null, for a rollout that can be promoted at will.

- Source: `body`
- Required: no
- Type: `string \| null`
- Example: `eval_V1StGXR8Z5jdHi6B`

### `soat promote-agent-release`

Promote the canary and end the rollout

- Method: `POST`
- Path: `/api/v1/agents/{agent_id}/release/promote`

#### Usage

```bash
soat promote-agent-release --agent-id <string>
```

#### Options

##### `--agent-id`

—

- Source: `path`
- Required: yes
- Type: `string`

### `soat abort-agent-release`

Abort the rollout and roll back to stable

- Method: `POST`
- Path: `/api/v1/agents/{agent_id}/release/abort`

#### Usage

```bash
soat abort-agent-release --agent-id <string>
```

#### Options

##### `--agent-id`

—

- Source: `path`
- Required: yes
- Type: `string`
