Installation
The SDK ships inside the same crate as the CLI binary. Add it to your project:Passthrough mode
If your agent runs withoutnanny run, every macro is a no-op. The function executes normally with no enforcement overhead:
#[tool] — declare a governed tool
Mark a function as a tool that Nanny should track and charge against the budget:
fetch_page:
- Nanny checks: is
fetch_pagein the[tools] allowedlist? - Nanny checks: has
fetch_pageexceeded[tools.fetch_page] max_calls? - Nanny charges 10 tokens against the budget.
- If any check fails, execution stops immediately — the function body never runs.
Tokens
Thetokens argument is required. It is the number of tokens charged per call.
Set it to 0 for tools you want tracked but not charged:
Matching the tool allowlist
The tool name used for allowlist checks is the function name as declared in Rust:nanny::http_get — built-in HTTP tool
nanny::http_get is a built-in governed HTTP GET function. It requires no #[tool] annotation — Nanny applies allowlist, call-count, and token enforcement automatically.
- Checked against the
[tools] allowedlist (tool name:"http_get") - Subject to
[tools.http_get] max_callslimit - Costs 10 tokens per successful call (configurable via
[tools.http_get] tokens_per_call)
nanny run), nanny::http_get makes the request directly with no enforcement overhead.
nanny::report_usage — report LLM token usage
#[tool(tokens = N)] charges a declared token cost per call. To charge the actual tokens an LLM used, report them after the call with nanny::report_usage. Hand Nanny the token counts already present on the response — Nanny debits input + output from the budget.
input and output are required. You can optionally attach model and provider labels — identifiers only, never prompt or response content:
LlmUsageRecorded event to the log. report_usage is fire-and-forget: it never blocks your agent and never panics. In passthrough mode (no nanny run) it is a no-op.
Rust reports usage explicitly, one call per LLM response. In Python,
nanny_sdk.instrument(client) does the same thing automatically by wrapping the client — Rust cannot patch a client at runtime, so the reporting is an explicit call instead.#[rule] — declare an enforcement rule
A rule is a function that returns a verdict on whether execution should continue.
Return true to allow, false to deny:
false, Nanny stops execution with:
PolicyContext fields
Thectx parameter gives you a snapshot of the current execution state:
Rules are evaluated before the tool runs —
requested_tool is set to the tool name being checked.
#[agent] — activate named limits for a scope
Mark a function to run under a named limit set from nanny.toml.
When the function is entered, Nanny switches to those limits; when it exits, limits revert:
[limits] and overrides only the declared fields.
Nesting #[agent] functions is supported — limits revert to the caller’s set on exit.

Complete example
What happens on stop
When Nanny stops execution inside an instrumented function, the macro propagates the stop signal by panicking with a structured message. The panic is caught by the Nanny runtime — your agent process exits cleanly with a non-zero code and anExecutionStopped event in the log.
You do not need to handle stop reasons in your agent code. Nanny handles the exit path.