---
title: Agent config
description: Every field of the agent config.
---

An agent version is one JSON document. The console's [version editor](/console/agents#the-version-editor) is a form over it; [`subako agent publish`](/build/cli#agents) reads it from a file; the API takes it at `POST /v1/agents/{agent_id}/versions`, with the provider beside it as `model_provider_id`.

```json agent.json
{
  "system_prompt": "You triage support tickets for Acme.",
  "model": { "format": "openai_responses", "model": "hawk", "max_tokens": 8192, "context_window": 128000 },
  "mcp": [{ "name": "orders", "url": "https://mcp.acme.example/orders", "default_policy": "require_approval" }],
  "skills": [{ "name": "refund-policy", "skill_id": "<skill-id>", "version": { "type": "latest" } }],
  "functions": [{ "name": "files", "source": { "type": "platform", "package": "files" }, "default_policy": "allow" }],
  "volume": { "data": { "type": "enabled" } },
  "builtin": { "session_display_name": { "when": "empty" }, "ask_user": { "widgets": [{ "type": "select" }] } }
}
```

`subako agent config-example --format <format>` prints the smallest document that publishes. A key the server does not know is ignored rather than refused, so check a version's page after publishing.

## Top level

| Field | | |
| --- | --- | --- |
| `system_prompt` | string | What the model is told before every conversation. Omit it to tell it nothing. |
| `model` | object, required | The model and its settings. |
| `mcp` | array | MCP server grants. |
| `skills` | array | Skill grants. |
| `sandboxes` | array | Sandbox grants. |
| `functions` | array | Function package grants. |
| `volume` | object | The Session Volume's areas. |
| `builtin` | object | Tools Subako itself serves. |

The model provider is not in the document: the editor's **Provider**, the CLI's `--model-provider`, or the API's `model_provider_id` names it, so one file publishes against any provider of the same format. CORS origins are set on the agent rather than the version — see [Sessions over the API](/build/sessions-api#calling-from-a-browser).

## `model`

Tagged by `format`, which must be the provider's.

**openai_responses**

| Field | | |
| --- | --- | --- |
| `model` | string, required | The model's ID. A platform provider's must be one it prices — checked at publish. Your own provider's is checked when a session first calls it. |
| `max_tokens` | integer, required | The most the model may write in one step. |
| `context_window` | integer, required | How many tokens the model reads at once. |
| `image_input` | `supported` \| `unsupported` | Whether the model is shown images. `supported` by default. |
| `reasoning_effort` | `none` \| `minimal` \| `low` \| `medium` \| `high` \| `xhigh` | Omitted, the model's default. |

**anthropic**

| Field | | |
| --- | --- | --- |
| `model` | string, required | The model's ID, such as `claude-sonnet-5`. |
| `max_tokens` | integer, required | The most the model may write in one step, thinking included. |
| `context_window` | integer, required | How many tokens the model reads at once. |
| `image_input` | `supported` \| `unsupported` | Whether the model is shown images. `supported` by default. |
| `thinking` | object | `{"type": "adaptive"}`, `{"type": "disabled"}`, `{"type": "between_tools"}`, or `{"type": "enabled", "budget_tokens": N}` with N at least 1,024 and below `max_tokens`. Omitted, the model's default. Not every model takes every mode. |
| `effort` | `low` \| `medium` \| `high` \| `xhigh` \| `max` | Omitted, the model's default. |

## Grants

Every grant has a `name`: 1 to 32 characters of lowercase letters, digits, and `-`, unique within its list, and never `parent`. The model sees the grant's tools as `<kind>__<name>__<tool>` — see [Tools](/concepts/tools).

MCP servers, sandboxes, and functions also take a policy:

| Field | | |
| --- | --- | --- |
| `default_policy` | `allow` \| `require_approval` \| `deny`, required | For every tool no rule names, including ones added later. |
| `tools` | `[{"name", "policy"}]` | Rules for tools by their exact names. |

### `mcp`

```json
{ "name": "orders", "url": "https://mcp.acme.example/orders", "default_policy": "allow", "tools": [{ "name": "refund", "policy": "require_approval" }] }
```

`url` is the server's URL, exactly as a vault credential for it names it. A server that offers resources also gets `list_resources` and `read_resource` tools.

### `skills`

```json
{ "name": "refund-policy", "skill_id": "<skill-id>", "version": { "type": "pinned", "number": 2 } }
```

`version` is `{"type": "latest"}` — resolved when each session is created — or `{"type": "pinned", "number": N}`. Each skill may be granted once.

### `sandboxes`

```json
{ "name": "build", "environment": { "type": "platform", "release": "2026" }, "network": { "type": "unrestricted" }, "default_policy": "allow" }
```

| Field | | |
| --- | --- | --- |
| `environment` | `{"type": "platform", "release": "2026"}`, required | The platform image line it boots. |
| `network` | `{"type": "unrestricted"}` \| `{"type": "none"}` | The internet, or nothing. `unrestricted` by default. |

Its one tool is `exec`.

### `functions`

```json
{
  "name": "billing",
  "source": { "type": "workspace", "function_id": "<function-id>", "version": { "type": "latest" } },
  "default_policy": "allow",
  "timeout_secs": 120,
  "network": { "type": "allowlist", "hosts": ["billing.acme.example"] },
  "http_credentials": ["https://billing.acme.example"]
}
```

| Field | | |
| --- | --- | --- |
| `source` | required | `{"type": "platform", "package": "files" \| "http"}`, or `{"type": "workspace", "function_id", "version"}` with `version` as for skills. |
| `timeout_secs` | 1–300 | 60 by default. |
| `network` | | `{"type": "none"}` (the default), `{"type": "unrestricted"}`, or `{"type": "allowlist", "hosts": [...]}` with 1 to 64 hosts such as `api.example.com` or `*.example.com`. |
| `http_credentials` | up to 16 | Origins, `https://host[:port]`, whose vault credential is attached to requests there. Each must be reachable under `network`. |

See [Granting functions](/functions/granting).

## `volume`

```json
{ "data": { "type": "enabled" } }
```

`{"type": "disabled"}` by default. Enabled, functions get `/volume/data`, kept until the session is deleted, beside `/volume/tmp`, which they always have.

## `builtin`

### `session_display_name`

`{"when": "never" | "empty" | "until_user_edits"}`, `never` by default. Other than `never`, the agent may name its session: only while it has no name (`empty`), or also revise its own name until a person renames it (`until_user_edits`). A name a person wrote is never overwritten.

### `ask_user`

`{"widgets": [...]}`, 1 to 32 widgets, each listed once. Omitted, the agent cannot ask.

| Widget | |
| --- | --- |
| `{"type": "select"}` | A pick among options |
| `{"type": "text"}` | Free text |
| `{"type": "confirm"}` | Yes or no |
| `{"type": "custom", "id", "description", "props", "answer"}` | A widget your app draws: `id` (1 to 64 of `a`–`z`, `0`–`9`, `_`, `-`), a `description` the model reads to choose it, and JSON Schemas for what the agent fills in (`props`) and what an answer holds (`answer`) |

See [Approvals and forms](/build/approvals-and-forms#forms).

## Reading a version back

`GET /v1/agents/{agent_id}/versions` answers each version's `config` as Subako stores it, which differs a little from what was published — the model's settings sit under `model.config`, and defaults are spelled out. The TypeScript SDK's `readAgentConfig` turns it back into the publish shape.
