Provides runtime checks in Python to prevent runaway AI agents by monitoring budgets, tool call loops, retries, and elapsed time.
Also known as bmdhodl/agent47, agent47, @agentguard47/mcp-server
- Stars
- 4
- Tools
- —
- Downloads, 30 days
- 192
- Latest version
- 0.2.2
- Last commit
- Nov 13, 2026
- License
- MIT
What is AgentGuard MCP?
AgentGuard provides runtime checks in Python to prevent runaway AI agents by monitoring budgets, tool call loops, retries, and elapsed time.
Summary generated from the project's README
About AgentGuard MCP server
AgentGuard provides a Python SDK designed to prevent autonomous AI agents from consuming excessive resources through runtime checks. It allows developers to monitor and limit agent behavior by raising exceptions when specific thresholds are met. The tool works locally with no required accounts or network access for its base functionality, making it suitable for private development environments. Users can instrument their own code or use the command line to patch existing OpenAI and Anthropic clients.
The library includes several specialized guards to manage different types of runaway behavior. BudgetGuard monitors estimated costs, tokens, or total calls, while LoopGuard detects repetitive tool usage or patterns that show no progress. Other available protections include TimeoutGuard for elapsed time, RetryGuard for excessive retries, and RateLimitGuard for call frequency. Developers can also use the agentguard run command to apply these constraints to a script without modifying the source code directly.
What you can do with it
- 1Prevent excessive API spendingSet a specific dollar limit to stop an agent script if it exceeds a defined budget.
- 2Protect Claude Code sessionsInstall a hook to prevent Claude Code from making too many identical tool calls in a row.
Written from the project's README. Every use case is checked against a quote from it.
How to install AgentGuard MCP
Formats verified 10 Nov 2026Add to CursorAdd to GooseInstall AgentGuard MCP in Claude Code
$ claude mcp add --env 'AGENTGUARD_API_KEY=<YOUR_AGENTGUARD_API_KEY>' agent47 -- npx -y @agentguard47/mcp-serverInstall AgentGuard MCP in Cursor
~/.cursor/mcp.json
{
"mcpServers": {
"agent47": {
"command": "npx",
"args": [
"-y",
"@agentguard47/mcp-server"
],
"env": {
"AGENTGUARD_API_KEY": "<YOUR_AGENTGUARD_API_KEY>"
}
}
}
}Install AgentGuard MCP in VS Code
.vscode/mcp.json
{
"servers": {
"agent47": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@agentguard47/mcp-server"
],
"env": {
"AGENTGUARD_API_KEY": "<YOUR_AGENTGUARD_API_KEY>"
}
}
}
}Install AgentGuard MCP in VS Code CLI
$ code --add-mcp '{"name":"agent47","type":"stdio","command":"npx","args":["-y","@agentguard47/mcp-server"],"env":{"AGENTGUARD_API_KEY":"<YOUR_AGENTGUARD_API_KEY>"}}'Install AgentGuard MCP in Claude Desktop
claude_desktop_config.json
{
"mcpServers": {
"agent47": {
"command": "npx",
"args": [
"-y",
"@agentguard47/mcp-server"
],
"env": {
"AGENTGUARD_API_KEY": "<YOUR_AGENTGUARD_API_KEY>"
}
}
}
}Install AgentGuard MCP in Codex
$ codex mcp add agent47 --env 'AGENTGUARD_API_KEY=<YOUR_AGENTGUARD_API_KEY>' -- npx -y @agentguard47/mcp-serverInstall AgentGuard MCP in Codex config.toml
~/.codex/config.toml
[mcp_servers.agent47] command = "npx" args = ["-y", "@agentguard47/mcp-server"] [mcp_servers.agent47.env] AGENTGUARD_API_KEY = "<YOUR_AGENTGUARD_API_KEY>"
Install AgentGuard MCP in Gemini CLI
$ gemini mcp add -s user -e 'AGENTGUARD_API_KEY=<YOUR_AGENTGUARD_API_KEY>' agent47 npx -- -y @agentguard47/mcp-serverInstall AgentGuard MCP in Gemini settings.json
~/.gemini/settings.json
{
"mcpServers": {
"agent47": {
"command": "npx",
"args": [
"-y",
"@agentguard47/mcp-server"
],
"env": {
"AGENTGUARD_API_KEY": "<YOUR_AGENTGUARD_API_KEY>"
}
}
}
}Configuration
AGENTGUARD_API_KEYRequiredSecretAgentGuard read API key for querying traces, alerts, costs, usage, and savings.
AGENTGUARD_URLOptional AgentGuard API base URL. Defaults to production.
| Name | Description | |
|---|---|---|
| AGENTGUARD_API_KEY | AgentGuard read API key for querying traces, alerts, costs, usage, and savings. | RequiredSecret |
| AGENTGUARD_URL | Optional AgentGuard API base URL. Defaults to production. |
Automated checks
Ran Nov 12, 2026Full report →Passed our automated checks. That is not a security audit: read the code and give the server the narrowest access it needs. How checks work
- Source repository linked and reachablePass
- Open source license (OSI)Pass
- Commit or release in the last yearPass
- Package name not close to a popular packagePass
- Remote endpoint uses HTTPSNot checked
- Destructive tools are labelledNot checked
- No hidden instructions to the modelPass
- No critical advisory in the package or its dependenciesPass
README
View on GitHubAgentGuard
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. AgentGuard 2.0.0 requires Python 3.11 or newer.
On Python 3.9 or 3.10, pin agentguard47==1.4.0. See the
Python migration guide before upgrading.
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.
agentguard demo --feedback prints a local redacted report; nothing is sent.
For a fresh PowerShell install and a runnable raw starter, follow the published-release walkthrough.
Share a stop receipt (new in 2.0.0)
agentguard receipt agentguard_demo_traces.jsonl prints a receipt of each stop
with the trace's SHA-256 drawn as a barcode. Add --format markdown to paste it
into a PR or issue. The hash identifies the trace file; it is not a signature.
This stop receipt records a covered guard refusal. Anthropic's official
/receipts plugin
summarizes past Claude Code work (30 days by default). Neither output proves
prevented spend or provides a signed attestation. The agentguard receipt
command stays the same.
Guard a Claude Code session (new in 2.0.0)
agentguard hook claude-code --install --write
This installs a Claude Code hook that refuses the third identical tool call in
a row and a call that already failed twice. "Identical" ignores JSON key order
and preserves case and whitespace in values. The optional no_progress_max
rule refuses a tool after repeated empty or same-error results even when input
changes; it is off by default. Refusals omit raw input and go to
.agentguard/claude-code/trace.jsonl. It
checks tool calls, not tokens or subscription quota. See the
Claude Code hook guide.
Guard a script without editing it (new in 2.0.0)
agentguard run --budget-usd 5 agent.py
This patches the OpenAI and Anthropic clients, then runs agent.py in the same
interpreter. Settings come from flags, then environment variables, then
.agentguard.json. A guard stop exits 1. Every run ends with the trace path on
stderr, ready for agentguard receipt. agentguard run python -m mypkg works too. The bounds are
the same as patching the client yourself; see
enforcement boundary.
Subprocesses start a separate interpreter and are not patched by the parent. A detached, uninstrumented child can keep running after the guarded script exits. The offline reproduction demonstrates that boundary with two simulated calls and no network access.
agentguard run prices every patched call at paid rates, including a local
model behind an OpenAI-compatible URL such as Ollama. A dollar budget can then
stop a model that costs nothing. For a local model, patch the client in the
script with free_local_clients=[client] and a BudgetGuard token or call
cap, then run the script with python; see
free local clients.
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.
Stop a reworded loop
A stuck agent often rewords each retry, so no call repeats exactly.
max_no_progress counts results instead: the same tool coming back empty, or
with the same error, N times in a row stops the run whatever the arguments.
normalize=True canonicalizes containers while preserving case and whitespace
in argument values. Both options are off by default.
from agentguard import LoopDetected, LoopGuard
loop = LoopGuard(normalize=True, max_no_progress=3)
for pattern in ["retry_count", "retryCount", "retries"]:
loop.check("grep", {"pattern": pattern})
matches = [] # Put your search here. This one finds nothing.
try:
loop.record_result("grep", matches, tool_args={"pattern": pattern})
except LoopDetected as stop:
print(stop)
Expected output: No progress: grep came back empty 3 times in a row (limit: 3). Change the approach instead of rewording the call. Functions wrapped with trace_tool feed results to the guard
automatically. Any other result in between starts the count over, so
pagination and edit-then-test cycles do not trip it.
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 or responses.create calls after this setup.
Standard OpenAI clients created earlier are covered too, including resource
objects obtained before the patch. Activate the patch before sending requests
or saving bound methods and raw/streaming response helpers. Those saved
references can retain the original callable; recreate them after activation.
patch_openai_async() covers async clients, and agentguard.init() enables
both. See the enforcement boundary.
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. Chat Completions streams request include_usage unless the
caller already set it.
The OpenAI Agents SDK runs on responses.create, so agentguard.init() before
the Runner puts every model call under the budget
(example). Hosted tools and
background=True responses are not covered. 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; opt in to normalize=True and max_no_progress=N for reworded ones |
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.
Budgets can also persist across runs: configure JsonFileStateStore, a shared
key, and period="day" for a daily counter. Set warn_at_pct=0.8 and an
on_warning callback for an 80% warning. Workers must explicitly share the
store and key; child-agent budget inheritance is not automatic. Monthly SDK
limits are not implemented. See the capability matrix.
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.
- Recorded-budget preflight refuses the next instrumented call when stored usage is already at a cap. It does not reserve concurrent in-flight requests, predict the next response, or cap a provider subscription. See the enforcement boundary.
- The base SDK uses the standard library. Optional framework extras install third-party dependencies and need their own security review.
- The optional
[crewai]extra pulls ChromaDB. The 2026-09-12 audit found four unresolved advisories, including PYSEC-2026-311 / CVE-2026-45829. Review that exposure before installing the extra. Base SDK installs do not include ChromaDB. - 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 |
|---|---|
| See which paths actually stop a call | Enforcement boundary |
| 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.
AgentGuard MCP questions
How do I add AgentGuard MCP to Claude Code?
Run claude mcp add --env 'AGENTGUARD_API_KEY=<YOUR_AGENTGUARD_API_KEY>' agent47 -- npx -y @agentguard47/mcp-server in your terminal. Add --scope user to make it available in every project.
How do I add AgentGuard MCP to Cursor?
Open ~/.cursor/mcp.json and add the server under mcpServers, using the Cursor config shown in the install section above.
Does AgentGuard require an account or network access to work?
No, the base SDK has no runtime dependencies and needs no account, allowing for offline checks.
Can AgentGuard stop a local model like Ollama?
Yes, it can price patched calls at paid rates even for local models behind an OpenAI-compatible URL, allowing a dollar budget to stop a model that costs nothing.
Does AgentGuard act as a sandbox for my code?
No, it is not a sandbox or permission system; a permitted operation can still be destructive.