Skip to main content
The Python SDK brings the same enforcement model as the Rust SDK to Python — @tool, @rule, and @agent decorators that enforce limits per function call.

Passthrough mode

When running outside nanny run, every decorator 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:
When the agent calls fetch_page:
  1. Nanny checks: is fetch_page in the [tools] allowed list?
  2. Nanny checks: has fetch_page exceeded [tools.fetch_page] max_calls?
  3. Nanny charges 10 tokens against the budget.
  4. If any check fails, a NannyStop exception is raised — the function body never runs.
Works identically for async functions:

Tokens

The tokens argument is required. 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 Python:
metrics_crew — ToolDenied fires when the analysis agent calls write_report, a tool outside its allowlist

instrument — automatic LLM token tracking

Call nanny_sdk.instrument(client) once at agent startup to automatically report LLM token usage to Nanny’s budget. Every completion response is intercepted and its token counts are debited from the same ledger that @tool charges against.
Supported clients (detected by duck-typing — no provider package is imported):
  • OpenAI, Groq, Together AI, Azure OpenAI, LiteLLM — any client with a chat.completions.create method
  • Anthropicclient.messages.create
  • Mistralclient.chat.complete
  • Google Gemini (google-genai SDK) — client.models.generate_content
  • Cohere v2cohere.ClientV2
instrument returns the same client unchanged — it patches the method in-place. In passthrough mode (outside nanny run), it is a no-op: no wrapping, no 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:
Rules are evaluated client-side on every tool call, before Nanny’s enforcement layer is contacted. When a rule returns False, Nanny raises:
The denied tool never runs and no tokens are charged.

PolicyContext fields

The ctx 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. Use last_tool_args for content-based enforcement:
All fields are live. Before each rule evaluation, the SDK fetches current counters from Nanny’s enforcement layer — step_count, tokens_spent, tool_call_counts, and tool_call_history reflect the actual execution state at the moment your rule runs.
metrics_crew — RuleDenied fires on the loop-detection rule, stopping the analysis agent from repeating the same computation

@agent — activate named limits for a scope

In a multi-agent system, each agent has a different role and a different risk profile. The analysis agent makes expensive API calls and deserves a tight token ceiling. The reporter just writes a file and barely needs a budget at all. @agent activates the right named limit set when each role runs, then reverts automatically when it’s done.
The named set inherits from [limits] and overrides only the declared fields. Works identically for async functions. Limits revert on exit whether the function returns normally or raises.
metrics_crew running under nanny run — ingestion, analysis, visualization, and reporter agent scopes entering and exiting with structured NDJSON events

What happens on stop

When Nanny stops execution, it raises a NannyStop exception. All stop reasons are distinct subclasses:
Catch them by category or individually:
BridgeUnavailable is raised when Nanny’s enforcement layer is active but unreachable during rule evaluation or a tool call. Nanny fails closed — the agent does not continue ungoverned. Like all NannyStop subclasses it extends BaseException, so it propagates through broad except Exception handlers in agent frameworks without being swallowed. You do not need to handle stop reasons in most agent code. They propagate up the call stack and terminate the process via nanny run. Catching them is useful in test code and at the CLI entry point.
metrics_crew — BudgetExhausted stops the analysis agent when it hits its token ceiling

Complete example

Run it under Nanny:
Run it without Nanny (decorators silent, agent runs normally):

Multi-agent pattern

The canonical use case: a pipeline where each agent has a specific role, a specific budget, and access to only the tools it needs. This is the metrics_crew pattern — four specialized agents, each governed independently.
The key properties this gives you:
  • Per-role budget: hitting the analysis budget doesn’t kill the reporter
  • Least-privilege tool access: each agent only receives the tools it needs; calling outside its role raises ToolDenied immediately
  • Loop detection: the @rule fires client-side before Nanny’s enforcement layer is contacted — the denied tool never runs and no tokens are charged
  • Full audit trail: every tool call, every limit activation, every stop reason logged to NDJSON
metrics_crew — MaxStepsReached stops the analysis agent after it exhausts its step allowance
For cross-process and cross-machine enforcement, use the governance server. See examples/python/metrics_crew for the complete working implementation of this pattern with four agents, Plotly chart generation, and a full incident report output.

Framework integration

LangChain

Stack @lc_tool (outer) and @nanny_tool (inner). LangChain registers the function for dispatch; Nanny intercepts every call regardless of which model or API style invoked it:
Execution order: your code calls tool.run(args) → LangChain validates args → Nanny wrapper intercepts → enforcement check → if allowed, file is read.

CrewAI

Same stacking pattern. CrewAI’s @tool decorator and Nanny’s @tool decorator both wrap the function — Nanny’s wrapper fires on every tool.run() call inside the crew:
See examples/python/dev_assist for a complete LangGraph integration and examples/python/metrics_crew for the canonical multi-agent governance example with four specialized agents, per-role limits, and per-role tool allowlists.