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:
nanny run is present.
#[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 cost units against the budget.
- If any check fails, execution stops immediately — the function body never runs.
Cost
Thecost argument is required. It is the number of cost units 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 cost enforcement automatically.
- Checked against the
[tools] allowedlist (tool name:"http_get") - Subject to
[tools.http_get] max_callslimit - Costs 10 units per successful call (configurable via
[tools.http_get] cost_per_call)
nanny run), nanny::http_get makes the request directly with no enforcement overhead.
#[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:
| Field | Type | Description |
|---|---|---|
step_count | u32 | Number of steps completed |
elapsed_ms | u64 | Wall-clock time elapsed |
cost_units_spent | u64 | Total cost units spent so far |
next_tool_cost | u64 | Declared cost of the tool currently being evaluated. 0 when no tool call is in flight. |
tool_call_counts | HashMap<String, u32> | Per-tool call counts |
tool_call_history | Vec<String> | Ordered log of tool names called |
requested_tool | Option<String> | The tool being evaluated right now |
last_tool_args | HashMap<String, String> | Arguments of the tool call currently being evaluated |
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.