Prompts are a weak place to store hard limits. If an agent is only "not supposed to" call a tool, spend a budget, or send data outward, the real boundary is still missing. Agent Contracts is my attempt to move those limits into code.

Hand-drawn agent contract diagram showing YAML flowing into an SDK gate, then tools, budget checks, and audit events.
The contract sits at the runtime boundary, where tool calls and effects can be checked before execution.

An agent contract is a YAML file validated by JSON Schema. It declares identity, allowed tools, budgets, effects, and postconditions. The SDK can then enforce those checks around the runtime instead of hoping the model remembers them.

agent: invoice-reviewer
tools:
  allow:
    - read_invoice
    - extract_totals
budget:
  max_usd: 2.00
effects:
  external_email: deny

The useful default is deny first. If a tool is not allowed, block it. If a budget is exhausted, stop the run. If an output needs a postcondition, evaluate it outside the model's prose. Prompt injection can still confuse the model, but it should not get a free path around the SDK boundary.

I am careful not to claim this solves agent security by itself. It does not. Contracts are one layer. They are strongest when paired with narrow tools, sandboxing, audit logs, and human gates for high-impact actions.

The first version supports a few adoption levels:

  • Document: write down what the agent is allowed to do.
  • Enforce: gate tool calls, budgets, and effects at runtime.
  • Compose: check compatibility when one agent delegates to another.

The reason I like contracts is that they make the argument concrete. Instead of asking whether an agent is "safe," you can inspect the boundary: what tools, what budget, what effects, what logs, what failure mode.

GitHub / PyPI