> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nanny.run/llms.txt
> Use this file to discover all available pages before exploring further.

# nanny.toml reference

> Complete schema for the nanny.toml configuration file.

## Full schema

```toml theme={null}
# ── Runtime ─────────────────────────────────────────────────────────────────────────────

[runtime]
mode = "local"   # "local" | "managed"

# ── Start ─────────────────────────────────────────────────────────────────────

[start]
cmd = "python agent.py"   # required, the command nanny run executes

# ── Limits ────────────────────────────────────────────────────────────────────

[limits]
steps   = 100
tokens  = 1000
timeout = 30000

# Named limit sets — inherit from [limits], override only declared fields.
[limits.researcher]
steps   = 200
tokens  = 5000
timeout = 120000

# ── Tools ─────────────────────────────────────────────────────────────────────

[tools]
allowed = ["http_get", "read_file"]   # empty list denies every tool call

# Per-tool configuration — tool name must match the function name in code.
[tools.http_get]
max_calls       = 10    # max number of calls in one execution
tokens_per_call = 20    # overrides the decorator/macro default if set

# ── Observability ─────────────────────────────────────────────────────────────

[observability]
log      = "stdout"          # "stdout" | "file"
log_file = "nanny.log"       # Required when log = "file"

# ── Proxy ─────────────────────────────────────────────────────────────────────

[proxy]
allowed_hosts = ["api.openai.com", "*.anthropic.com"]   # required when proxy mode is used

# ── Managed (Cloud) ───────────────────────────────────────────────────────────

[managed]
endpoint = "https://api.nanny.run/v1"
# The key comes from the NANNY_API_KEY environment variable:
#   export NANNY_API_KEY="nny_..."
```

***

## \[runtime]

| Field  | Type                     | Default   | Description                                                                                                         |
| ------ | ------------------------ | --------- | ------------------------------------------------------------------------------------------------------------------- |
| `mode` | `"local"` \| `"managed"` | `"local"` | `"local"` uses the local enforcement bridge. `"managed"` connects to a Nanny Cloud endpoint (requires `[managed]`). |

***

## \[start]

| Field | Type   | Default | Description                                                                                                                      |
| ----- | ------ | ------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `cmd` | string | —       | **Required.** The shell command `nanny run` executes. Examples: `"python agent.py"`, `"cargo run --release"`, `"node agent.js"`. |

***

## \[limits]

The global execution ceiling. Any one limit stopping the agent stops the entire run.

| Field     | Type         | Default | Description                                                                         |
| --------- | ------------ | ------- | ----------------------------------------------------------------------------------- |
| `steps`   | integer      | —       | Maximum tool calls allowed. Requires SDK instrumentation.                           |
| `tokens`  | integer      | —       | Maximum tokens allowed. Requires SDK instrumentation.                               |
| `timeout` | integer (ms) | —       | Maximum wall-clock time in milliseconds. Enforced for any process, no SDK required. |

**Named limit sets** — `[limits.<name>]` inherits all fields from `[limits]` and overrides only the fields it declares:

```toml theme={null}
[limits]
steps   = 50
tokens  = 500
timeout = 15000

[limits.researcher]
steps   = 200       # overrides 50
tokens  = 5000      # overrides 500
# timeout inherits 15000

[limits.reporter]
tokens  = 100       # overrides 500 only; steps and timeout inherit
```

Activate a named set from the CLI:

```bash theme={null}
nanny run --limits=researcher
```

Or from inside agent code using `@agent("researcher")` (Python) or `#[nanny::agent("researcher")]` (Rust).

***

## \[tools]

| Field     | Type         | Default | Description                                                                                                                      |
| --------- | ------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `allowed` | string array | —       | Explicit allowlist of tool names. **An empty array denies every tool call.** If `[tools]` is not present, all tools are allowed. |

### Per-tool configuration — `[tools.<name>]`

```toml theme={null}
[tools.http_get]
max_calls       = 10
tokens_per_call = 20
```

| Field             | Type    | Default               | Description                                                                                                                           |
| ----------------- | ------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `max_calls`       | integer | unlimited             | Maximum number of calls to this tool in one execution. Exceeding this limit fires `RuleDenied` with `rule_name = "<tool>.max_calls"`. |
| `tokens_per_call` | integer | decorator/macro value | Tokens charged per call. Overrides the value declared in `@tool(tokens=N)` or `#[tool(tokens = N)]`.                                  |

The tool name in `[tools.<name>]` must exactly match the function name used in the `@tool` decorator or `#[nanny::tool]` macro.

***

## \[observability]

| Field      | Type                   | Default    | Description                                            |
| ---------- | ---------------------- | ---------- | ------------------------------------------------------ |
| `log`      | `"stdout"` \| `"file"` | `"stdout"` | Destination for the NDJSON event stream.               |
| `log_file` | string                 | —          | Required when `log = "file"`. Path to the output file. |

***

## \[proxy]

Optional. Enables HTTP CONNECT proxy mode on the governance server.

Proxy mode is active only when `allowed_hosts` is present and non-empty. An empty list — or omitting `[proxy]` entirely — disables proxy mode.

| Field           | Type         | Default | Description                                                                                                                                                                                         |
| --------------- | ------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `allowed_hosts` | string array | `[]`    | Hostnames the proxy may forward to. Supports exact names (`api.openai.com`) and `*.suffix` wildcard patterns. Loopback, link-local, and RFC-1918 ranges are always blocked regardless of this list. |

See [HTTP proxy mode](/v0.4/guides/http-proxy-mode) for full details.

***

## \[managed]

Only read when `[runtime] mode = "managed"`. Cloud connection config.

| Field      | Type   | Default | Description                                                                                                                          |
| ---------- | ------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `endpoint` | string | —       | Nanny Cloud API endpoint.                                                                                                            |
| `api_key`  | string | —       | **Optional, and not recommended.** A local-experimentation escape hatch. Prefer `NANNY_API_KEY` (below), which overrides this field. |

### Supplying the API key

The key is read from the **`NANNY_API_KEY`** environment variable, so `nanny.toml`
stays safe to commit:

```bash theme={null}
export NANNY_API_KEY="nny_..."
nanny run
```

Resolution order:

1. `NANNY_API_KEY` — wins whenever it is set to a non-empty value.
2. `[managed] api_key` in `nanny.toml` — fallback.

A blank or whitespace-only `NANNY_API_KEY` counts as **unset** (an unset CI secret
usually surfaces as `""`), so it falls through to the config file rather than
authenticating with an empty string.

If no key is found, Nanny prints a warning and **keeps enforcing locally** — it
simply does not forward events to the cloud. Enforcement never depends on the
network.

<Note>
  Your organization is derived from the API key on the cloud side, so there is no
  `org_id` field to configure.
</Note>
