AgentGuard
Stop runaway agents with runtime checks in Python.
AgentGuard checks budgets, repeated tool calls, retries, and elapsed time in instrumented Python code. Guards raise exceptions so your application can stop the next operation. The base SDK has no runtime dependencies and needs no account.
Names: this repository is agent47, the PyPI package is agentguard47,
and the Python import is agentguard. Requires Python 3.9 or newer.
Getting started
Install in a virtual environment, then run the offline checks:
python -m pip install agentguard47
agentguard doctor
agentguard demo
doctor checks the installation and local trace writing. demo exercises
budget, loop, and retry stops without provider keys or network access. Follow
the trace path printed by the command to inspect its output.
Stop before a third call
Save this as budget_demo.py and run python budget_demo.py. It makes no
network requests.
from agentguard import BudgetExceeded, BudgetGuard
budget = BudgetGuard(max_calls=2)
completed = 0
for _ in range(3):
try:
budget.check() # Check before the operation.
# Put your provider or tool call here.
completed += 1
budget.consume(calls=1) # Record the completed operation.
except BudgetExceeded:
print(f"Stopped before call {completed + 1}")
assert completed == 2
Expected output: Stopped before call 3.
Connect a provider
Install the provider's client separately. For OpenAI:
python -m pip install openai
from agentguard import BudgetGuard, JsonlFileSink, Tracer, patch_openai
budget = BudgetGuard(max_cost_usd=5.00)
tracer = Tracer(
service="my-agent",
sink=JsonlFileSink(".agentguard/traces.jsonl"),
)
patch_openai(tracer, budget_guard=budget)
# Make your OpenAI chat.completions.create calls after this setup.
The patch checks recorded usage before dispatch and records response usage
afterward, including streamed calls once the final usage arrives. A response
can exceed the remaining cost or token allowance. Concurrent requests do not
reserve capacity. OpenAI streams request include_usage unless the caller
already set it. See the getting started guide
for setup, traces, and framework starters.
How enforcement works
flowchart TD
accTitle: AgentGuard operation checks
accDescr: Check a limit before an operation, then record usage.
A[Instrumented operation] --> B{Guard check}
B -->|Limit reached| C[Raise exception]
B -->|Allowed| D[Run operation]
D --> E[Record usage and trace]
E --> A
Text equivalent: check before an operation, run it if allowed, then record usage. A guard exception returns control to your application's error handler.
| Guard | Checks | Raises |
|---|---|---|
BudgetGuard |
Recorded calls, tokens, or estimated cost | BudgetExceeded |
LoopGuard |
Repeated tool calls | LoopDetected |
FuzzyLoopGuard |
Tool frequency and alternating patterns | LoopDetected |
RetryGuard |
Retries per tool | RetryLimitExceeded |
TimeoutGuard |
Elapsed time when checked | TimeoutExceeded |
RateLimitGuard |
Calls within a sliding minute | BudgetExceeded |
X402SpendGuard |
Payment amounts before the payment callback | BudgetExceeded |
For task budgets, use BudgetGuard.goal(...). For signatures and defaults,
read the guard source and
public exports.
Limits and security
- Guards cover operations you instrument. Installing the package does not intercept every action in Cursor, Claude Code, or another agent.
- A guard is not a sandbox or permission system. A permitted operation can still be destructive.
- Timeout checks do not interrupt an already blocked function or cancel an agent running on a provider's server.
- Cost estimates are not invoices. Supply reported cost or use strict cost resolution when an estimate is insufficient.
- The base SDK uses the standard library. Optional framework extras install third-party dependencies and need their own security review.
- Trace content can contain application data. Review it before sharing or configuring a remote sink.
See security reporting, the dated dependency audit, and release notes. Audit results describe their recorded date, not a permanent clean bill of health.
Local traces and optional hosted ingest
The SDK is the free local proof path. Start local. Add hosted ingest only when you need retained history, alerts, team visibility, spend trends, hosted decision history, or dashboard-managed remote kill signals.
Local guards remain authoritative. HttpSink mirrors trace and decision events;
it does not execute remote kill signals by itself. See the
dashboard contract before configuring it.
Local use has no hosted event quota, retention period, or API-key allocation.
Network egress requires an integration you configure, such as HttpSink or
an OpenTelemetry exporter.
Nothing in the local SDK phones home. The AgentGuard website describes the optional hosted service.
Documentation
| You want to | Start here |
|---|---|
| Install and trace a first run | Getting started |
| Find guides and source references | Documentation index |
| Try a runnable example | Examples |
| Connect LangChain, LangGraph, or CrewAI | Integration guides |
| Inspect hosted data through MCP | Read-only TypeScript MCP server |
| Use local budget tools through MCP | Python budget MCP server |
| Navigate with an AI assistant | AI documentation index |
| Contribute a fix | Contributing |
| Check what changed | Changelog |
Help and maintenance
Maintained by Patrick Hughes. Report a bug with the package version, a minimal reproduction, and the expected result. Report vulnerabilities through SECURITY.md.
The source metadata defines the branch version. The PyPI badge links to the published version. Documentation examples and local links are tested in CI. The PyPI README is generated from this README and the changelog.
Latest Release Notes (1.3.2)
(2026-09-17)
Record final usage on streamed provider calls
- OpenAI and Anthropic patches now wrap
stream=Trueresponses and bill the final usage payload once, for both sync and async clients. Anthropicmessages.stream()is included. Chunks without usage are ignored. - OpenAI streaming requests set
stream_options.include_usage=Truewhen the caller did not setinclude_usage. An explicitFalseis left unchanged. - Anthropic
create(stream=True)events split input usage onmessage_startand output usage onmessage_delta; the wrapper now merges those fields before billing. Stream wrappers are iterators (next/anext). A failed stream closes the trace span with the exception soassert_no_errors()sees it. - A stream that ends without usage still counts as one dispatched call with zero tokens and zero cost. Exhausted budgets still refuse the request before dispatch.
- This does not reserve concurrent capacity, predict a response's cost, or preflight goal-level caps. Mid-stream abort without a usage payload cannot recover tokens from partial text.
- Reproduce the before/after token counts without network calls with
examples/streaming_usage_demo.py. The provider is mocked; the installed AgentGuard patch, stream wrapper, and budget consume path are real.
Full changelog: CHANGELOG.md
Release files for agentguard47 1.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| agentguard47-1.3.2.tar.gz | 220.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| agentguard47-1.3.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 339.6 kB
Release files / agentguard47-1.3.2.tar.gz
| Download URL | agentguard47-1.3.2.tar.gz |
|---|---|
| Size | 220.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c3a4f8f251d30fa903ccd56d2ef48036317eab621b6451036bc5e07e6c9828d4
|
|
BLAKE2b-256 checksum How to use checksums |
d22bcc4a1c5a0f90a56a3b2c3b8dacc3157344243f61e88824f155eee5cfc584
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency logRelease files / agentguard47-1.3.2-py3-none-any.whl
| Download URL | agentguard47-1.3.2-py3-none-any.whl |
|---|---|
| Size | 118.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
03b3b876bf97b55a4e8c68b8c115c554c4d3497b30d48b51b236d5d8a8dd17f3
|
|
BLAKE2b-256 checksum How to use checksums |
263334b84ffd4bd1ae7512b8c629bd136f089127410dbfa625aa2158aae87f15
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency log