# Agent configuration

An agent is the durable identity Jazz runs on every surface. Its JSON selects the primary model,
persona, tools, memory, and optional specialist companions. Run budgets and output belong to the
application, workflow, or individual run, not the agent.

Agent files live under `$JAZZ_HOME/agents/`, normally `~/.jazz/agents/`. The easiest starting point
is `jazz agent create`; edit the generated file for fields the wizard does not expose.

## Start with an agent

```bash
jazz agent create
jazz agent show reviewer
jazz agent edit reviewer
```

Replace `reviewer` with the name you give the agent. Alternatively, skip the wizard and save this as
`~/.jazz/agents/reviewer.json`, using a provider you configured and a model it offers:

```json
{
  "id": "reviewer",
  "name": "Reviewer",
  "config": {
    "persona": "coder",
    "llm": {
      "provider": "openai",
      "model": "gpt-5.4-mini"
    }
  }
}
```

```bash
jazz config validate
jazz agent chat reviewer
```

## Extended example

```json
{
  "id": "incident-briefing",
  "name": "incident-briefing",
  "description": "Correlates incident evidence and produces an executive visual briefing.",
  "config": {
    "persona": "coder",
    "llm": {
      "provider": "openai",
      "model": "gpt-5.4-mini",
      "summarizerModel": "openai/gpt-5.4-mini",
      "reasoning": "medium",
      "temperature": 0.2,
      "maxContextTokens": 64000
    },
    "deniedTools": ["execute_command"],
    "tools": ["publish_briefing"],
    "customTools": [
      {
        "name": "publish_briefing",
        "description": "Publish the approved incident briefing to the team's webhook.",
        "parameters": {
          "type": "object",
          "properties": {
            "title": { "type": "string" },
            "summary": { "type": "string" }
          },
          "required": ["title", "summary"]
        },
        "handler": {
          "type": "command",
          "command": [
            "curl",
            "--fail-with-body",
            "--request",
            "POST",
            "--header",
            "Content-Type: application/json",
            "--data-binary",
            "@-",
            "https://briefings.example.com/hooks/incidents"
          ],
          "timeoutMs": 30000
        }
      }
    ],
    "companions": {
      "analyze:image": "provider/vision-model",
      "analyze:audio": "provider/audio-model",
      "generate:image": "provider/image-generation-model"
    }
  }
}
```

Replace provider, model, and endpoint placeholders. Keep credentials out of agent files; use Jazz's
provider configuration, the system keyring, or narrowly allowlisted environment variables.

## Models and context

- `persona` names a built-in or installed persona. It defaults to `default` when Jazz creates an
  agent.
- `llm` groups every model setting below. `llm.provider` and `llm.model` select the primary reasoning and tool-use model.
- `llm.summarizerModel` is a `provider/model` used for context compaction and command risk
  classification. If it is missing or invalid, Jazz uses the primary model.
- `llm.reasoning` selects an effort: `disable`, `minimal`, `low`, `medium`, `high`,
  `xhigh`, or `max`. Jazz maps that one user-facing value to the selected
  provider/model control surface before serializing a request. A model runs at `xhigh` or `max`
  only when Jazz knows it accepts them: ChatGPT models report their own levels, OpenAI's GPT-6
  models have built-in profiles, and OpenRouter takes `xhigh` (`max` is sent as `xhigh`). Any
  other model runs at `high`, with a warning. Add an [`llm.capabilityOverrides`](providers.md#model-capability-overrides) entry to raise it.
- `llm.temperature` accepts `0` through `2`. Jazz omits it when unset; models that reject custom
  temperature ignore it.
- `llm.numCtx` sets Ollama's `num_ctx` to a positive token count.
- `llm.maxContextTokens` places a positive per-agent ceiling on the effective context window across
  providers. Jazz warns and compacts against that ceiling.
- `companions` binds specialist models independently for `analyze` and `generate` across `image`,
  `audio`, and `video`. See [Model companions](../concepts/media.md).

`llm.apiKeys` can override provider keys inside an agent file, but plaintext credentials make the
file difficult to share safely. Prefer `jazz config set <provider>` (it prompts for the key), environment variables, or the keyring.

## Tool access

`tools` adds named tools, MCP servers, or custom tools to the built-in bundle permitted by the
persona. It is **not an allowlist**. Omitting `execute_command` from `tools` does not remove shell
access. When `tools` is omitted, Jazz also inherits the selectable Browser Use and Peers
categories. An explicit list (including `[]`) grants selectable tools only by name; the
built-in bundle still applies. A persona's explicit category profile takes precedence over
these defaults. Peers offers `ask_peer` only when a peer with a URL is configured.

Use `deniedTools` for a hard per-agent restriction. Jazz applies it after built-in, persona, MCP,
peer, and custom capabilities are assembled, so an earlier grant cannot add the tool back. Use
exact tool names from `/tools` in a chat or the [tool inventory](../tools/index.md).

`webSearchProvider` selects the configured search backend. `envAllowlist` may exempt at most 32
uppercase environment-variable names from command secret scrubbing. Treat each exemption as a
credential grant to every command the agent can run.

## Custom tools

`customTools` exposes a narrow function to the model without writing a Jazz plugin. A definition is
registered only when its name also appears in `tools`.

- Names are 2–64 lowercase letters, digits, or underscores, start with a letter, and cannot start
  with `mcp_` or collide with another tool or alias.
- `description` is 1–1024 characters and should say when to call the tool.
- `parameters` is a JSON Schema object with `type: "object"`.
- A `record` handler returns fixed text and is read-only.
- A `command` handler spawns the argv directly, never through a shell, and writes validated arguments
  as JSON to stdin. It runs in the current working directory, uses Jazz's scrubbed environment,
  and is always high-risk: every call asks first, and runs unasked only under the `high-risk`
  policy or when the tool is in `--auto-approve-tools`. `timeoutMs` may be 1–300000.

For authenticated SaaS actions, prefer an MCP server whose schema, authentication, and errors are
explicit. A command-backed webhook is useful when the HTTP endpoint itself is the stable interface.

## Memory

`memoryScopes` controls which long-term memory namespaces the agent can read and write. The default
Memory is shared by every agent. A scope is a topic — `personal` by default, or a project or
role scope when the context calls for one — and every agent reads and writes every scope, so a
lesson learned with one agent is available to all of them. See
[Conversations, working state, and memory](../concepts/conversations-and-memory.md).
The memory tools (`view_memory`, `manage_memory`) are part of every agent's built-in bundle, like
the scratchpad, so they cannot be unticked in `jazz agent create`. To keep an agent from writing
memory, deny `manage_memory` with `deniedTools`, or run it with `jazz run --ephemeral`.

Run `jazz agent show <name>` to inspect the resolved agent and `/tools` inside chat to see the tools
available to that run.

On the `jazz` home screen, type `/agents`, select an agent, and press Enter to
inspect its configuration. The detail screen shows provider, model, reasoning, persona, input and
output prices per million tokens, the effective host URL for a self-hosted model, model settings,
tool access, companions, and timestamps. Use Up/Down to scroll and Escape to return to the list.
Prices are shown as unknown when the model catalog has no rate; local models running on your own
server show $0 for provider inference. API keys and custom tool commands remain hidden.