Skip to main content

Nanny

nanny-sdk

Python SDK for Nanny — the enforcement primitive for autonomous AI agents.

@tool, @rule, and @agent decorators that enforce step limits, token budgets, tool allowlists, and custom rules per function call. Works with LangChain, CrewAI, or any Python agent framework.

pip install nanny-sdk

Full docs: docs.nanny.run


How it works

Nanny runs as a parent process via nanny run. The SDK decorators communicate with it at each tool call to check limits before the function body executes. Outside nanny run, every decorator is a no-op — zero overhead in development and CI.

# Governed — enforcement active
nanny run

# Passthrough — decorators silent, agent runs normally
python agent.py
uv run agent.py

@tool — declare a governed tool

from nanny_sdk import tool

@tool(tokens=10)
def fetch_page(url: str) -> str:
    import httpx
    return httpx.get(url).text

Before fetch_page runs, Nanny checks the allowlist, per-tool call limits, and charges 10 tokens against the budget. If any check fails, a NannyStop exception is raised and the function body never executes.

Async functions work identically:

@tool(tokens=10)
async def fetch_page(url: str) -> str:
    async with httpx.AsyncClient() as client:
        r = await client.get(url)
        return r.text

instrument — automatic LLM token tracking

import nanny_sdk, openai

client = openai.OpenAI()
nanny_sdk.instrument(client)   # one line — done

Call once at startup. Every LLM completion response is intercepted and its token counts are reported to Nanny's budget automatically — no @tool decorator needed on the LLM call itself.

Supported: OpenAI, Groq, Together AI, Azure OpenAI, LiteLLM, Anthropic, Mistral, Google Gemini (google-genai), Cohere v2. No-op in passthrough mode.

For providers that report prompt-caching usage (OpenAI, Anthropic, DeepSeek, Gemini), instrument also captures cache_read/cache_write — a finer, reporting-only split of input, never additional tokens and never used for enforcement.


@rule — enforce a custom policy

from nanny_sdk import rule

@rule("no_sensitive_files")
def block_sensitive(ctx) -> bool:
    path = ctx.last_tool_args.get("path", "")
    return ".env" not in path and "secret" not in path

Rules run before every @tool call. Return False to stop execution with RuleDenied. The ctx object exposes requested_tool, last_tool_args, and counters.


@agent — activate named limits for a scope

In a multi-agent system, each agent has a different role and a different risk profile. @agent activates the right named limit set when each role runs, then reverts automatically when it's done:

from nanny_sdk import agent

@agent("researcher")
def run_research_loop(query: str) -> str:
    ...

Activates [limits.researcher] from nanny.toml for the duration of the function. Limits revert on exit, including on exception. Each role gets its own tool allowlist — the analysis agent cannot call the reporter's tools. Budgets are a different story: tokens spent and steps taken are one running total for the whole run, not a separate pool per role, so hitting the analysis ceiling stops the run there, the reporter never gets to run at all. Want each role to genuinely start from a clean budget instead? See fresh_run below.

metrics_crew — ingestion, analysis, visualization, and reporter agent scopes entering and exiting


fresh_run — starting a genuinely independent budget

@agent changes which ceiling the run's one running total is checked against; it does not give a role its own budget (see above). If your process runs multiple independent phases back to back and want each one to start from zero instead, that's a new run:

import nanny_sdk

nanny_sdk.fresh_run()   # everything governed after this point is a fresh run

Only meaningful under a network server (nanny run --serve / --join), which tracks each run's budget independently. Under local nanny run, one process is already always exactly one run, so it's a safe no-op there.


nanny.toml example

[start]
cmd = "uv run agent.py"

[limits]
steps   = 50
tokens  = 200
timeout = 120000

[limits.researcher]
steps  = 30
tokens = 100

[tools]
allowed = ["fetch_page", "search"]

Cloud sync isn't a config field. Run nanny auth login once on a machine and every nanny run there forwards its event log automatically. No login, no sync.


Stop reasons

When a limit is exceeded, a NannyStop exception is raised with one of these reasons:

Reason Cause
BudgetExhausted Token ceiling reached
MaxStepsReached Step limit reached
TimeoutExpired Wall-clock limit reached
ToolDenied Tool not in the allowlist
RuleDenied A rule returned False
AgentCompleted Clean exit
AgentNotFound Named limit set in @agent does not exist in nanny.toml
BridgeUnavailable Enforcement was active but became unreachable — fails closed, never continues ungoverned

Requirements

  • Python 3.11+
  • httpx (only runtime dependency)
  • nanny CLI:
    • macOS: brew tap nanny-run/nanny && brew install nannyd
    • Linux: curl -fsSL https://install.nanny.run | sh
    • Windows: irm https://install.nanny.run/windows | iex

Links

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nanny_sdk-0.5.0.tar.gz (56.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nanny_sdk-0.5.0-py3-none-any.whl (23.1 kB view details)

Uploaded Python 3

File details

Details for the file nanny_sdk-0.5.0.tar.gz.

File metadata

  • Download URL: nanny_sdk-0.5.0.tar.gz
  • Upload date:
  • Size: 56.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for nanny_sdk-0.5.0.tar.gz
Algorithm Hash digest
SHA256 54734610174b777b0f25616fa580422253fe89529b9d67346e4b6852e55f3e16
MD5 24567bd56f4d8c95d90ca013577a0638
BLAKE2b-256 a965a315e3214714e5dfa63cf7d436da60a902bbbc229244116a96bd274393cf

See more details on using hashes here.

Provenance

The following attestation bundles were made for nanny_sdk-0.5.0.tar.gz:

Publisher: release.yml on nanny-run/nanny

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file nanny_sdk-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: nanny_sdk-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 23.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for nanny_sdk-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b9258d96f77751c74378ad566721cb1490b080b41987fc864a990a061b45f53e
MD5 3cf49a87780037c0d78a496be3ecc6d0
BLAKE2b-256 d1a083a7e35fff5d058ba40c3b51b3864a9be80c8da5890a881f3cb26e82eb11

See more details on using hashes here.

Provenance

The following attestation bundles were made for nanny_sdk-0.5.0-py3-none-any.whl:

Publisher: release.yml on nanny-run/nanny

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 files

0.4.2

2 files

0.4.1

2 files

0.4.0

2 files

0.3.0

2 files

0.2.0

2 files

0.1.8

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page