> ## 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.

# How It Works

> What Nanny actually does when you run a command under it.

## The enforcement model

When you run `nanny run`, Nanny becomes the parent process of your agent.
It reads `[start].cmd` from `nanny.toml`, spawns it as a child, and owns the process lifecycle — it decides when the process lives and when it dies.

```mermaid theme={null}
flowchart TD
    CMD(["$ nanny run"])

    CMD --> NANNY

    subgraph NANNY["Nanny — parent process"]
        direction LR

        subgraph CHILD["Child process"]
            AGENT["python agent.py"]
        end

        subgraph ENFORCE[" "]
            direction TB
            STEPS["steps"]
            TOKENS["tokens"]
            TIMER["timeout"]
        end

        AGENT -- "tool call" --> ENFORCE
        ENFORCE -- "✓  allowed" --> AGENT
    end

    ENFORCE -- "✗  limit reached → killed" --> DEAD(["process exits"])
    DEAD --> LOG["ExecutionStopped\nreason · steps · tokens_spent\n→ stdout"]
```

The moment any limit is crossed, Nanny kills the child process immediately — the process cannot catch, delay, or prevent the stop. An `ExecutionStopped` event is emitted with the reason, and Nanny exits with a non-zero status code.

## Multi-agent governance

When multiple agents run in the same process — as in CrewAI, LangGraph, AutoGen, or any framework that orchestrates agents within a single Python or Rust runtime — the enforcement model above applies to all of them simultaneously. A single `nanny run` governs the entire fleet.

```mermaid theme={null}
flowchart TD
    CMD(["$ nanny run"])
    CMD --> NANNY

    subgraph NANNY["Nanny — parent process"]
        direction TB

        subgraph CHILD["Child process — crew.kickoff()"]
            direction LR
            A1["@agent('ingestion')"]
            A2["@agent('analysis')"]
            A3["@agent('visualization')"]
            A4["@agent('reporter')"]
        end

        subgraph ENFORCE[" "]
            direction TB
            STEPS["steps"]
            TOKENS["tokens"]
            ALLOW["allowlist"]
            RULES["rules"]
        end

        A1 & A2 & A3 & A4 -- "tool call" --> ENFORCE
        ENFORCE -- "✓  allowed" --> A1 & A2 & A3 & A4
    end

    ENFORCE -- "✗  limit reached → killed" --> DEAD(["process exits"])
    DEAD --> LOG["ExecutionStopped\nreason · agent · tool · tokens_spent\n→ stdout"]
```

Each agent activates its own named limit set via `@agent("role")`. Tool calls from any agent flow through Nanny’s enforcement layer. Each agent's budget is tracked independently — hitting the analysis budget does not kill the reporter.

For cross-process and cross-machine enforcement, use the [governance server](/v0.4/guides/governance-server).

***

## What Nanny enforces

All three limits are enforced on every run:

| Limit     | Requirement                  | Behaviour                                                  |
| --------- | ---------------------------- | ---------------------------------------------------------- |
| `timeout` | None — works for any process | Killed when wall-clock time exceeds the configured value   |
| `steps`   | Rust SDK or Python SDK       | Killed when step count reaches the configured limit        |
| `tokens`  | Rust SDK or Python SDK       | Killed when accumulated tokens reach the configured budget |

Timeout enforcement works for any process in any language — no SDK required.
Step and token enforcement require the agent to report tool calls — either via the [Rust SDK](/v0.4/guides/rust-sdk) macros or the Python SDK decorators.

## Passthrough mode

When running outside `nanny run`, every macro becomes a no-op:

```rust theme={null}
#[tool(tokens = 10)]
fn search(query: &str) -> String {
    // runs normally, no enforcement
}
```

This means you can ship instrumented code and run it in development, CI, and production without Nanny — until you explicitly wrap it with `nanny run`. The behaviour is identical either way.
