agentguard47 1.2.13
pip install agentguard47
Released:
Zero-dependency runtime control for production Python agents - stop loops, retry storms, and budget burn
Navigation
Verified details
These details have been verified by PyPIProject links
GitHub Statistics
Maintainers
๐ Avatar for pat9000 from gravatar.compat9000
Unverified details
These details have not been verified by PyPIProject links
Meta
-
License Expression: MIT
SPDX License Expression - Author: BMD PAT LLC
- Tags agents , coding-agents , ai-agents , multi-agent , llm , guardrails , runtime-guardrails , loop-detection , budget-guard , retry-guard , runtime-enforcement , runtime-control , production-agents , coding-agent-safety , local-first , retry-storms , budget-control , langchain , openai , anthropic
- Requires: Python >=3.9
-
Provides-Extra:
langchain,langgraph,crewai,otel
Classifiers
- Development Status
- Intended Audience
- Programming Language
- Topic
- Typing
Project description
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.
๐ PyPI
๐ Downloads
๐ Python
๐ CI
๐ Coverage
๐ License: MIT
๐ agent47 MCP server
๐ GitHub stars
Install
As a Python package
pipinstallagentguard47
As a skill (Claude Code, Cursor, Cline, and more)
npxskillsaddbmdhodl/agent47
Or with GitHub CLI:
ghskillinstallbmdhodl/agent47agentguard
Why AgentGuard
Most agent tooling tells you what happened after the run. AgentGuard stops the bad run while it is happening.
AgentGuard is an in-process agentic-loop guard, not an LLM cost router. It runs inside the agent's process, sees the call graph, and raises exceptions that kill the run before the next bad call lands. Routers and gateways like Manifest or Vercel AI Gateway sit at the network layer and shape egress traffic. The layers are complementary โ see the competitive notes for when each fits.
| 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:
fromagentguardimport 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.
Microsoft โ engineers told to ease off Claude Code over inference cost (May 2026)
Microsoft engineering management reportedly asked teams to reduce Claude Code usage after monthly inference bills exceeded budget. If Microsoft cannot absorb coding-agent inference cost without a memo, runaway agent spend is no longer a solo-founder problem.
Source: TheNextWeb
A memo asks engineers to self-throttle. A BudgetGuard makes the cap a
config value enforced inside the process:
fromagentguardimport BudgetGuard BudgetGuard(max_cost_usd=5.00, max_calls=50, warn_at_pct=0.8)
The guard raises BudgetExceeded before the run blows the cap. Same
conversation, one config line instead of a memo.
Local Proof in 60 Seconds
pipinstallagentguard47 agentguarddoctor agentguarddemo agentguardquickstart--frameworkraw--write pythonagentguard_raw_quickstart.py agentguardreport.agentguard/traces.jsonl
This stays fully local. No API key, dashboard, or network call is required after installation.
What you should see:
doctorverifies the installed package and writes a local trace.demovisibly trips budget, loop, and retry guards offline.quickstart --writecreatesagentguard_raw_quickstart.py.- The generated file exits cleanly after catching simulated budget and loop stops.
reportshows local trace counts, cost, savings, and guard events.
Notebook version:
๐ Open In Colab
Copy-Paste Repo Setup
Use this when you want a coding agent or teammate to add AgentGuard safely:
pipinstallagentguard47 agentguarddoctor agentguardquickstart--frameworkraw--write pythonagentguard_raw_quickstart.py agentguardreport.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
fromagentguardimport 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:
agentguardreport.agentguard/traces.jsonl agentguardincident.agentguard/traces.jsonl
Auto-Patch Provider SDKs
If you already call OpenAI or Anthropic directly, patch once and keep using the provider normally:
fromagentguardimport 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.
agentguardquickstart--frameworkraw agentguardquickstart--frameworkopenai agentguardquickstart--frameworkanthropic agentguardquickstart--frameworklangchain agentguardquickstart--frameworklanggraph agentguardquickstart--frameworkcrewai
Optional integration extras are opt-in. The core SDK stays stdlib-only.
pipinstall"agentguard47[langchain]" pipinstall"agentguard47[langgraph]" pipinstall"agentguard47[crewai]" pipinstall"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:
- AgentGuard vs Vercel AI Gateway
- AgentGuard vs Manifest (LLM router)
- Where AgentGuard fits in the agent security stack
Decision Traces
Capture proposal, human edit, approval, override, and binding events through the same event pipeline:
fromagentguardimport 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.
fromagentguardimport 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:
agentguardincident.agentguard/traces.jsonl--formatmarkdown agentguardincident.agentguard/traces.jsonl--formathtml
Fail CI when a trace violates safety expectations:
fromagentguardimport 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 |
| Releasing | docs/RELEASING.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.
Threat model: agent data exfiltration
A recurring class of agent attack uses the agent's own write surface as an outbound channel. Example pattern from Microsoft Copilot Cowork (May 2026): the agent emails the user's own inbox with no approval, the rendered message fetches an external image, and the image URL encodes data the attacker wanted out. AgentGuard does not replace an egress firewall or tool-permission layer, but it gives the agent runtime hard stops for runaway loops, retries, and budget burn that can turn one bad tool call into a sustained incident.
Citation: https://simonwillison.net/2026/May/26/copilot-cowork-exfiltrates-files/
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-mpytestsdk/tests/-v python-mruffchecksdk/agentguard/ pythonscripts/sdk_release_guard.py
Useful links:
License
MIT. See LICENSE.
Latest Release Notes (1.2.13)
Release Operations
- Made post-PyPI GitHub Release creation a separate idempotent job and
dispatch release announcements explicitly, so the release-content workflow no
longer depends on
GITHUB_TOKENrelease events. - Hardened generated GitHub Release notes and release-content announcements so
they start from the last published GitHub Release instead of a stale raw tag.
This lets
v1.2.13supersede the failedv1.2.11andv1.2.12tags without truncating public release notes. - Includes the release candidate originally prepared under the failed
v1.2.11tag. That tag did not publish to PyPI and has no GitHub Release. - Supersedes the stale
v1.2.12tag, which was pushed from a checkout still carryingsdk/pyproject.tomlversion1.2.10. That tag did not publish a new PyPI version and has no GitHub Release.
Reliability
- Hardened
agentguard.__version__so malformed local package metadata falls back to0.0.0-devinstead of crashing source-checkout imports. - Fixed the coding-agent review-loop proof to record cumulative guard spend as
total_cost_usd, preventing local reports from double-counting the stopped budget event.
Public Docs
- Corrected the README threat-model copy so AgentGuard is positioned as local runtime hard stops for loops, retries, and budget burn, not as a replacement for egress firewalls or tool-permission layers.
- Added release runbook documentation for tag-triggered PyPI publish and GitHub Release creation.
Profiles
- Added a
deployed-agentguard profile (agentguard.init(profile="deployed-agent")) for unattended production agents. Tightens defaults toloop_max=2,retry_max=1,warn_pct=0.5. Motivated by the arxiv:2605.00055 ambient-persuasion incident where a deployed agent installed 107 unauthorized components and overrode its own oversight gate.
Release Proof
- Added a deterministic sticky agent proof example that simulates a CrewAI-style retry storm, repeated tool loop, budget burn, local incident output, and dashboard-compatible hosted NDJSON without adding dependencies.
- Added contract tests that post the sticky proof NDJSON to the local hosted ingest harness so SDK proof events stay aligned with dashboard expectations.
Activation
- Added
python -m agentguard.cli ...fallback guidance todoctor,demo, andquickstartso first-run users are not blocked when console scripts install outsidePATH. - Added a post-demo next-step block so
agentguard demopoints directly toagentguard quickstart --framework raw --write, the generated starter, and the follow-up local report command. - Added an MCP read-path proof to the proof gallery and test coverage that catches stale local example and sample-doc references.
- Added an optional local-first Pydantic AI starter recipe using Pydantic AI's
TestModel, so users can try the pattern without API keys or network calls after installing the optional framework package. - Clarified incident-report dashboard handoff copy so hosted ingest is framed as useful when incidents need retained history, alerts, spend trends, or team-visible follow-up, not as a requirement for local safety.
- Added a concise local-vs-hosted adoption table to the README and dashboard contract docs so the dashboard CTA is explicit without making local SDK use feel limited.
Release Security
- Switched the PyPI publish workflow from long-lived
PYPI_TOKENauthentication to OIDC Trusted Publishing for thepypiGitHub environment, with PyPI attestations enabled for release artifacts. - Added release documentation for the required PyPI trusted-publisher tuple and post-release verification steps.
- Added an MCP package publishing checklist and normalized npm package metadata
so the
@agentguard47/mcp-serverrelease path does not rely on npm publish autocorrections. - Added an optional release-guard npm check so release operators can verify the repo MCP package version is actually published as npm latest without making normal CI depend on the network.
Release Operations
- Added a release cadence document that separates the weekly MCP / Glama distribution train from the monthly SDK release train.
- Added a scheduled release cadence workflow that opens or updates one active release queue issue with SDK, npm MCP, and Glama indexing status.
- Added tag/version validation to the PyPI publish workflow and creates the GitHub Release only after PyPI publish succeeds.
- Changed release announcement automation to run from a published GitHub Release instead of a raw tag push, so failed PyPI publishes cannot announce as shipped.
- Refreshed the MCP server lockfile so
npm auditno longer reports the transitivefast-uriorqsadvisories.
Full changelog: CHANGELOG.md
Project details
Verified details
These details have been verified by PyPIProject links
GitHub Statistics
Maintainers
๐ Avatar for pat9000 from gravatar.compat9000
Unverified details
These details have not been verified by PyPIProject links
Meta
-
License Expression: MIT
SPDX License Expression - Author: BMD PAT LLC
- Tags agents , coding-agents , ai-agents , multi-agent , llm , guardrails , runtime-guardrails , loop-detection , budget-guard , retry-guard , runtime-enforcement , runtime-control , production-agents , coding-agent-safety , local-first , retry-storms , budget-control , langchain , openai , anthropic
- Requires: Python >=3.9
-
Provides-Extra:
langchain,langgraph,crewai,otel
Classifiers
- Development Status
- Intended Audience
- Programming Language
- Topic
- Typing
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agentguard47-1.2.13.tar.gz.
File metadata
- Download URL: agentguard47-1.2.13.tar.gz
- Upload date:
- Size: 174.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
55610ed2256a955b7fd22558e4c61cbaae59c49a60f82a9caded1f8123cb5ee2
|
|
| MD5 |
1092806c5e35f75d83af6d49f720307a
|
|
| BLAKE2b-256 |
09cbb62562f4a916443352623ce5bacb239f3ad37feb7b6576d1dadb1509e05c
|
Provenance
The following attestation bundles were made for agentguard47-1.2.13.tar.gz:
Publisher:
publish.yml on bmdhodl/agent47
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agentguard47-1.2.13.tar.gz -
Subject digest:
55610ed2256a955b7fd22558e4c61cbaae59c49a60f82a9caded1f8123cb5ee2 - Sigstore transparency entry: 1675925950
- Sigstore integration time:
-
Permalink:
bmdhodl/agent47@ed0f1ee439116207cc3182294290b276f42f39b2 -
Branch / Tag:
refs/tags/v1.2.13 - Owner: https://github.com/bmdhodl
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ed0f1ee439116207cc3182294290b276f42f39b2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file agentguard47-1.2.13-py3-none-any.whl.
File metadata
- Download URL: agentguard47-1.2.13-py3-none-any.whl
- Upload date:
- Size: 93.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
beeee75b1796c85a49abca9cb0e0d82eb90a094ed8a25f3d409befa5d576eeff
|
|
| MD5 |
58031673d275f9de38b8523137b07286
|
|
| BLAKE2b-256 |
68e02b877d73be7a8804357cfd9f38996a2cd3b419a1561339cad036245c267e
|
Provenance
The following attestation bundles were made for agentguard47-1.2.13-py3-none-any.whl:
Publisher:
publish.yml on bmdhodl/agent47
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agentguard47-1.2.13-py3-none-any.whl -
Subject digest:
beeee75b1796c85a49abca9cb0e0d82eb90a094ed8a25f3d409befa5d576eeff - Sigstore transparency entry: 1675926002
- Sigstore integration time:
-
Permalink:
bmdhodl/agent47@ed0f1ee439116207cc3182294290b276f42f39b2 -
Branch / Tag:
refs/tags/v1.2.13 - Owner: https://github.com/bmdhodl
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ed0f1ee439116207cc3182294290b276f42f39b2 -
Trigger Event:
push
-
Statement type:
