Agentguard47
AgentGuard47 is runtime safety infrastructure for AI agents. It adds budget caps, loop detection, retry limits, timeouts, local traces, and incident reports so agents can stop bad runs while they are happening, not just explain them afterward.
README
AgentGuard
Stop runaway Python agents before they burn money.
AgentGuard47 is a zero-dependency runtime control SDK for Python agents. Add hard budget caps, loop detection, retry limits, timeouts, local traces, and incident reports without changing agent frameworks or sending data anywhere by default.
Use it when an agent can call tools, retry work, review code, or run long enough to create surprise spend.
pip install agentguard47
Why AgentGuard
Most agent tooling tells you what happened after the run. AgentGuard stops the bad run while it is happening.
| Problem | What AgentGuard does |
|---|---|
| Agent loops on the same tool | Raises LoopDetected |
| Flaky tool retries forever | Raises RetryLimitExceeded |
| Run spends too much | Raises BudgetExceeded |
| Run hangs | Raises TimeoutExceeded |
| Team needs proof | Writes local JSONL traces and incident reports |
| Dashboard comes later | HttpSink mirrors events only when you opt in |
Design constraints:
- zero runtime dependencies
- MIT licensed
- local-first by default
- no API key required for local proof
- no network calls unless you configure
HttpSink - guards raise exceptions inside the running process
Real Incidents AgentGuard Prevents
PocketOS — agent deleted prod DB and backups in 9 seconds (May 2026)
A Cursor agent ran a destructive sequence against PocketOS production and wiped the live database. Backups went with it.
Reported root cause from the team's postmortem:
- one API key had write + delete on both prod and backups
- backups lived in the same Railway environment as prod
- no confirmation step before destructive actions
- the agent was given enough rope to chain the calls in one turn
Source: r/devops thread
The "AI did it" framing buries the actual lesson: the blast radius was infra, not the model. AgentGuard does not replace least-privilege creds or isolated backups. It does kill the run before a loop, retry storm, or runaway turn finishes the job.
A BudgetGuard plus LoopGuard wired around the agent loop caps how much
it can do in one session:
from agentguard import BudgetGuard, LoopGuard, RateLimitGuard, Tracer
budget = BudgetGuard(max_calls=20, max_cost_usd=1.00)
loop = LoopGuard(max_repeats=2)
rate = RateLimitGuard(max_calls_per_minute=10)
tracer = Tracer(service="cursor-agent", guards=[loop, rate])
with tracer.trace("agent.run"):
budget.consume(calls=1)
# tool call here — guards raise on overrun
A 9-second sequence of destructive calls trips LoopGuard or
RateLimitGuard long before it finishes. The exception kills the run
in-process. Pair this with scoped credentials and out-of-environment
backups for the rest of the blast radius.
Local Proof In 60 Seconds
agentguard doctor
agentguard demo
agentguard quickstart --framework raw
doctor verifies the install and local trace writing.
demo proves budget, loop, and retry stops offline.
quickstart prints the smallest starter for your stack.
Installed-package proof:
agentguard demo
Source-checkout proof with local incident output and hosted-compatible NDJSON:
git clone https://github.com/bmdhodl/agent47.git
cd agent47
PYTHONPATH=sdk python examples/sticky_agent_proof.py --out-dir proof/sticky-agent-proof
agentguard incident proof/sticky-agent-proof/sticky_agent_proof_traces.jsonl
Expected first value moment:
BudgetGuard stops simulated spend.
LoopGuard stops repeated tool calls.
RetryGuard stops a retry storm.
No API keys. No dashboard. No network calls.
Copy-Paste Repo Setup
Use this when you want a coding agent or teammate to add AgentGuard safely:
pip install agentguard47
agentguard doctor
agentguard quickstart --framework raw --write
python agentguard_raw_quickstart.py
agentguard report .agentguard/traces.jsonl
Optional shared local defaults, saved as .agentguard.json in the repo root:
{
"profile": "coding-agent",
"service": "my-agent",
"trace_file": ".agentguard/traces.jsonl",
"budget_usd": 5.0
}
Keep the first PR local-only. Add hosted ingest later only when retained incidents, alerts, or team visibility matter.
Quickstart: Guard One Agent Run
from agentguard import BudgetGuard, JsonlFileSink, LoopGuard, Tracer
budget = BudgetGuard(max_cost_usd=5.00, max_calls=50, warn_at_pct=0.8)
loop = LoopGuard(max_repeats=3)
tracer = Tracer(
sink=JsonlFileSink(".agentguard/traces.jsonl"),
service="support-agent",
guards=[loop],
)
with tracer.trace("agent.run") as span:
budget.consume(calls=1, cost_usd=0.02)
loop.check("search", {"query": "refund policy"})
span.event("tool.call", data={"tool": "search", "query": "refund policy"})
# Call your agent or tool here.
Inspect the local proof:
agentguard report .agentguard/traces.jsonl
agentguard incident .agentguard/traces.jsonl
Auto-Patch Provider SDKs
If you already call OpenAI or Anthropic directly, patch once and keep using the provider normally:
from agentguard import BudgetGuard, Tracer, patch_openai
budget = BudgetGuard(max_cost_usd=5.00, warn_at_pct=0.8)
tracer = Tracer(service="support-agent")
patch_openai(tracer, budget_guard=budget)
# OpenAI chat completions are now traced and budget-enforced.
When accumulated cost crosses the hard limit, BudgetExceeded is raised and
the agent stops.
Guards
| Guard | Stops | Example |
|---|---|---|
BudgetGuard |
dollar, token, or call overruns | BudgetGuard(max_cost_usd=5.00) |
LoopGuard |
exact repeated tool calls | LoopGuard(max_repeats=3) |
FuzzyLoopGuard |
similar calls and A-B-A-B loops | FuzzyLoopGuard(max_tool_repeats=5) |
RetryGuard |
retry storms on the same tool | RetryGuard(max_retries=3) |
TimeoutGuard |
long-running jobs | TimeoutGuard(max_seconds=300) |
RateLimitGuard |
calls per minute | RateLimitGuard(max_calls_per_minute=60) |
BudgetAwareEscalation |
hard turns that need a stronger model | BudgetAwareEscalation(...) |
Guards are static runtime checks. They do not ask another model whether a run is safe. They raise exceptions.
Examples
All examples are local-first. No API key is required unless the example says so.
| Example | What it proves |
|---|---|
examples/try_it_now.py |
budget, loop, and retry stops |
examples/sticky_agent_proof.py |
one CrewAI-style retry storm proof with local incident and hosted NDJSON outputs |
examples/coding_agent_review_loop.py |
review/refinement loop stopped by budget and retry guards |
examples/per_token_budget_spike.py |
one oversized token-heavy turn can blow a run budget |
examples/budget_aware_escalation.py |
when to escalate from a cheap model to a stronger one |
examples/decision_trace_workflow.py |
proposal, edit, approval, and binding decision events |
Sample incident:
docs/examples/coding-agent-review-loop-incident.md
Proof gallery:
docs/examples/proof-gallery.md
Starter files:
examples/starters/
Framework Integrations
AgentGuard can wrap raw Python code or integrate with common agent stacks.
agentguard quickstart --framework raw
agentguard quickstart --framework openai
agentguard quickstart --framework anthropic
agentguard quickstart --framework langchain
agentguard quickstart --framework langgraph
agentguard quickstart --framework crewai
Optional integration extras are opt-in. The core SDK stays stdlib-only.
pip install "agentguard47[langchain]"
pip install "agentguard47[langgraph]"
pip install "agentguard47[crewai]"
pip install "agentguard47[otel]"
Runtime Control vs Observability
AgentGuard is not a generic tracing platform. It is the local runtime stop layer.
| Capability | AgentGuard |
|---|---|
| In-process hard budget caps | Yes |
| Kill a bad run by raising an exception | Yes |
| Loop and retry-storm detection | Yes |
| Local JSONL traces | Yes |
| Local incident reports | Yes |
| Hosted ingest | Optional |
| Required dashboard | No |
| Runtime dependencies | None |
Competitive notes:
Decision Traces
Capture proposal, human edit, approval, override, and binding events through the same event pipeline:
from agentguard import JsonlFileSink, Tracer, decision_flow
tracer = Tracer(sink=JsonlFileSink(".agentguard/traces.jsonl"))
with tracer.trace("agent.run") as run:
with decision_flow(
run,
workflow_id="deploy-review",
object_type="pull_request",
object_id="123",
actor_type="human",
actor_id="pat",
) as decision:
decision.proposed({"action": "merge"})
decision.approved(comment="Looks safe")
decision.bound(binding_state="merged", outcome="success")
Supported event types:
decision.proposeddecision.editeddecision.overriddendecision.approveddecision.bound
Guide: docs/guides/decision-tracing.md
MCP Server
AgentGuard also ships a read-only MCP server for coding-agent workflows:
npx -y @agentguard47/mcp-server
Use the SDK to enforce local safety where the agent runs. Use MCP when a client like Codex, Claude Code, or Cursor needs read access to traces, decisions, costs, usage, and budget health.
Hosted Dashboard Boundary
The SDK is the free local proof path. The hosted dashboard is for retained history, alerts, team visibility, spend trends, hosted decision history, and dashboard-managed remote kill signals.
| Use local SDK when | Use hosted dashboard when |
|---|---|
| You are proving AgentGuard in one repo | Multiple people need the same incident history |
| You need hard stops for loops, retries, timeouts, or budget burn | Runs need retained alerts and follow-up outside the terminal |
| You want JSONL traces and reports without an API key | You need spend trends across traces, services, or teammates |
| You are testing an agent before production | Operators need dashboard-managed remote kill signals |
Start local. Add hosted ingest when the work becomes shared, expensive, or risky enough that local files are no longer enough.
from agentguard import HttpSink, Tracer
tracer = Tracer(
sink=HttpSink(
url="https://app.agentguard47.com/api/ingest",
api_key="ag_...",
)
)
HttpSink mirrors trace and decision events to the dashboard. It does not
execute remote kill signals by itself.
Dashboard contract:
docs/guides/dashboard-contract.md
Reports And CI Gates
Generate a local incident report:
agentguard incident .agentguard/traces.jsonl --format markdown
agentguard incident .agentguard/traces.jsonl --format html
Fail CI when a trace violates safety expectations:
from agentguard import EvalSuite
result = (
EvalSuite(".agentguard/traces.jsonl")
.assert_no_loops()
.assert_budget_under(tokens=50_000)
.assert_no_errors()
.run()
)
assert result.passed
Package Facts
- Package:
agentguard47 - Python: 3.9+
- License: MIT
- Core runtime dependencies: zero
- Trace format: JSONL
- Local commands:
doctor,demo,quickstart,report,incident,eval - MCP package:
@agentguard47/mcp-server - Glama listing:
AgentGuard47
Docs
| Topic | Link |
|---|---|
| Getting started | docs/guides/getting-started.md |
| Coding-agent setup | docs/guides/coding-agents.md |
| Safety pack | docs/guides/coding-agent-safety-pack.md |
| Dashboard contract | docs/guides/dashboard-contract.md |
| Decision traces | docs/guides/decision-tracing.md |
| Managed sessions | docs/guides/managed-agent-sessions.md |
| Activation metrics design | docs/guides/activation-metrics-design.md |
| Proof gallery | docs/examples/proof-gallery.md |
| Release cadence | docs/release/cadence.md |
| PyPI Trusted Publishing | docs/release/trusted-publishing.md |
Architecture
agent code
|
v
Tracer
|
+-- guards raise exceptions locally
|
+-- sinks write traces locally or mirror to hosted ingest
Repository layout:
sdk/ Python SDK package
mcp-server/ read-only MCP server
docs/ guides and competitive notes
examples/ runnable local examples
ops/ repo operating docs
memory/ SDK-only state and decisions
Security
- No secrets are required for local mode.
- Do not put API keys in
.agentguard.json. - Hosted ingest API keys should be stored in environment variables.
- Local guards remain authoritative even when hosted ingest is configured.
Report security issues through GitHub Security Advisories or by email:
pat@bmdpat.com.
Contributing
Contributions are welcome when they keep the SDK small, local-first, and zero-dependency.
Before opening a PR:
python -m pytest sdk/tests/ -v
python -m ruff check sdk/agentguard/
python scripts/sdk_release_guard.py
Useful links:
License
MIT. See LICENSE.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。