Metadata-Version: 2.4
Name: agentguard47
Version: 1.2.13
Summary: Zero-dependency runtime control for production Python agents - stop loops, retry storms, and budget burn
Author-email: BMD PAT LLC <pat@bmdpat.com>
License-Expression: MIT
Project-URL: Homepage, https://agentguard47.com
Project-URL: Documentation, https://github.com/bmdhodl/agent47#readme
Project-URL: Repository, https://github.com/bmdhodl/agent47
Project-URL: Issues, https://github.com/bmdhodl/agent47/issues
Project-URL: Changelog, https://github.com/bmdhodl/agent47/releases
Keywords: 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
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Testing
Classifier: Topic :: System :: Monitoring
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: langchain
Requires-Dist: langchain-core>=0.3.84; extra == "langchain"
Provides-Extra: langgraph
Requires-Dist: langgraph>=0.6.11; extra == "langgraph"
Provides-Extra: crewai
Requires-Dist: crewai>=0.28; extra == "crewai"
Provides-Extra: otel
Requires-Dist: opentelemetry-api>=1.41.0; extra == "otel"
Requires-Dist: opentelemetry-sdk>=1.41.0; extra == "otel"
Dynamic: license-file

<!-- Generated by scripts/generate_pypi_readme.py. Edit README.md and CHANGELOG.md instead. -->

# 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](https://img.shields.io/pypi/v/agentguard47)](https://pypi.org/project/agentguard47/)
[![Downloads](https://img.shields.io/pypi/dm/agentguard47)](https://pypi.org/project/agentguard47/)
[![Python](https://img.shields.io/pypi/pyversions/agentguard47)](https://pypi.org/project/agentguard47/)
[![CI](https://github.com/bmdhodl/agent47/actions/workflows/ci.yml/badge.svg)](https://github.com/bmdhodl/agent47/actions/workflows/ci.yml)
[![Coverage](https://img.shields.io/badge/coverage-93%25-brightgreen)](https://github.com/bmdhodl/agent47)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://github.com/bmdhodl/agent47/blob/v1.2.13/LICENSE)
[![agent47 MCP server](https://glama.ai/mcp/servers/bmdhodl/agent47/badges/score.svg)](https://glama.ai/mcp/servers/bmdhodl/agent47)
[![GitHub stars](https://img.shields.io/github/stars/bmdhodl/agent47?style=social)](https://github.com/bmdhodl/agent47)

## Install

### As a Python package

```bash
pip install agentguard47
```

### As a skill (Claude Code, Cursor, Cline, and more)

```bash
npx skills add bmdhodl/agent47
```

Or with GitHub CLI:

```bash
gh skill install bmdhodl/agent47 agentguard
```

## 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](#runtime-control-vs-observability) 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](https://www.reddit.com/r/devops/comments/1t4au5h/pocketos_lost_their_prod_db_backups_to_a_cursor/)

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:

```python
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.

### 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](https://thenextweb.com/news/microsoft-claude-code-retreat-ai-cost)

A memo asks engineers to self-throttle. A `BudgetGuard` makes the cap a
config value enforced inside the process:

```python
from agentguard import 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

```bash
pip install agentguard47
agentguard doctor
agentguard demo
agentguard quickstart --framework raw --write
python agentguard_raw_quickstart.py
agentguard report .agentguard/traces.jsonl
```

This stays fully local. No API key, dashboard, or network call is required
after installation.

What you should see:

- `doctor` verifies the installed package and writes a local trace.
- `demo` visibly trips budget, loop, and retry guards offline.
- `quickstart --write` creates `agentguard_raw_quickstart.py`.
- The generated file exits cleanly after catching simulated budget and loop
  stops.
- `report` shows local trace counts, cost, savings, and guard events.

Notebook version:
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/bmdhodl/agent47/blob/v1.2.13/examples/quickstart.ipynb)

## Copy-Paste Repo Setup

Use this when you want a coding agent or teammate to add AgentGuard safely:

```bash
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:

```json
{
  "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

```python
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:

```bash
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:

```python
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`](https://github.com/bmdhodl/agent47/blob/v1.2.13/examples/try_it_now.py) | budget, loop, and retry stops |
| [`examples/sticky_agent_proof.py`](https://github.com/bmdhodl/agent47/blob/main/examples/sticky_agent_proof.py) | one CrewAI-style retry storm proof with local incident and hosted NDJSON outputs |
| [`examples/coding_agent_review_loop.py`](https://github.com/bmdhodl/agent47/blob/v1.2.13/examples/coding_agent_review_loop.py) | review/refinement loop stopped by budget and retry guards |
| [`examples/per_token_budget_spike.py`](https://github.com/bmdhodl/agent47/blob/v1.2.13/examples/per_token_budget_spike.py) | one oversized token-heavy turn can blow a run budget |
| [`examples/budget_aware_escalation.py`](https://github.com/bmdhodl/agent47/blob/v1.2.13/examples/budget_aware_escalation.py) | when to escalate from a cheap model to a stronger one |
| [`examples/decision_trace_workflow.py`](https://github.com/bmdhodl/agent47/blob/v1.2.13/examples/decision_trace_workflow.py) | proposal, edit, approval, and binding decision events |

Sample incident:
[`docs/examples/coding-agent-review-loop-incident.md`](https://github.com/bmdhodl/agent47/blob/main/docs/examples/coding-agent-review-loop-incident.md)

Proof gallery:
[`docs/examples/proof-gallery.md`](https://github.com/bmdhodl/agent47/blob/main/docs/examples/proof-gallery.md)

Starter files:
[`examples/starters/`](https://github.com/bmdhodl/agent47/tree/v1.2.13/examples/starters)

## Framework Integrations

AgentGuard can wrap raw Python code or integrate with common agent stacks.

```bash
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.

```bash
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:

- [AgentGuard vs Vercel AI Gateway](https://github.com/bmdhodl/agent47/blob/v1.2.13/docs/competitive/vercel-ai-gateway.md)
- [AgentGuard vs Manifest (LLM router)](https://github.com/bmdhodl/agent47/blob/v1.2.13/docs/competitive/manifest.md)
- [Where AgentGuard fits in the agent security stack](https://github.com/bmdhodl/agent47/blob/main/docs/competitive/agent-security-stack.md)

## Decision Traces

Capture proposal, human edit, approval, override, and binding events through the
same event pipeline:

```python
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.proposed`
- `decision.edited`
- `decision.overridden`
- `decision.approved`
- `decision.bound`

Guide: [`docs/guides/decision-tracing.md`](https://github.com/bmdhodl/agent47/blob/main/docs/guides/decision-tracing.md)

## MCP Server

AgentGuard also ships a read-only MCP server for coding-agent workflows:

```bash
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.

```python
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`](https://github.com/bmdhodl/agent47/blob/main/docs/guides/dashboard-contract.md)

## Reports And CI Gates

Generate a local incident report:

```bash
agentguard incident .agentguard/traces.jsonl --format markdown
agentguard incident .agentguard/traces.jsonl --format html
```

Fail CI when a trace violates safety expectations:

```python
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`](https://pypi.org/project/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`](https://github.com/bmdhodl/agent47/tree/v1.2.13/mcp-server)
- Glama listing: [`AgentGuard47`](https://glama.ai/mcp/servers/bmdhodl/agent47)

[![agent47 MCP server](https://glama.ai/mcp/servers/bmdhodl/agent47/badges/card.svg)](https://glama.ai/mcp/servers/bmdhodl/agent47)

## Docs

| Topic | Link |
|---|---|
| Getting started | [`docs/guides/getting-started.md`](https://github.com/bmdhodl/agent47/blob/v1.2.13/docs/guides/getting-started.md) |
| Coding-agent setup | [`docs/guides/coding-agents.md`](https://github.com/bmdhodl/agent47/blob/v1.2.13/docs/guides/coding-agents.md) |
| Safety pack | [`docs/guides/coding-agent-safety-pack.md`](https://github.com/bmdhodl/agent47/blob/v1.2.13/docs/guides/coding-agent-safety-pack.md) |
| Dashboard contract | [`docs/guides/dashboard-contract.md`](https://github.com/bmdhodl/agent47/blob/main/docs/guides/dashboard-contract.md) |
| Decision traces | [`docs/guides/decision-tracing.md`](https://github.com/bmdhodl/agent47/blob/main/docs/guides/decision-tracing.md) |
| Managed sessions | [`docs/guides/managed-agent-sessions.md`](https://github.com/bmdhodl/agent47/blob/main/docs/guides/managed-agent-sessions.md) |
| Activation metrics design | [`docs/guides/activation-metrics-design.md`](https://github.com/bmdhodl/agent47/blob/v1.2.13/docs/guides/activation-metrics-design.md) |
| Proof gallery | [`docs/examples/proof-gallery.md`](https://github.com/bmdhodl/agent47/blob/main/docs/examples/proof-gallery.md) |
| Releasing | [`docs/RELEASING.md`](https://github.com/bmdhodl/agent47/blob/v1.2.13/docs/RELEASING.md) |
| Release cadence | [`docs/release/cadence.md`](https://github.com/bmdhodl/agent47/blob/main/docs/release/cadence.md) |
| PyPI Trusted Publishing | [`docs/release/trusted-publishing.md`](https://github.com/bmdhodl/agent47/blob/main/docs/release/trusted-publishing.md) |

## Architecture

```text
agent code
   |
   v
Tracer
   |
   +-- guards raise exceptions locally
   |
   +-- sinks write traces locally or mirror to hosted ingest
```

Repository layout:

```text
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:

```bash
python -m pytest sdk/tests/ -v
python -m ruff check sdk/agentguard/
python scripts/sdk_release_guard.py
```

Useful links:

- [`CONTRIBUTING.md`](https://github.com/bmdhodl/agent47/blob/v1.2.13/CONTRIBUTING.md)
- [`GOLDEN_PRINCIPLES.md`](https://github.com/bmdhodl/agent47/blob/v1.2.13/GOLDEN_PRINCIPLES.md)

## License

MIT. See [`LICENSE`](https://github.com/bmdhodl/agent47/blob/v1.2.13/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_TOKEN` release 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.13` supersede the failed `v1.2.11` and `v1.2.12` tags without
  truncating public release notes.
- Includes the release candidate originally prepared under the failed
  `v1.2.11` tag. That tag did not publish to PyPI and has no GitHub Release.
- Supersedes the stale `v1.2.12` tag, which was pushed from a checkout still
  carrying `sdk/pyproject.toml` version `1.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 to `0.0.0-dev` instead 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-agent` guard profile (`agentguard.init(profile="deployed-agent")`)
  for unattended production agents. Tightens defaults to `loop_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 to `doctor`, `demo`,
  and `quickstart` so first-run users are not blocked when console scripts
  install outside `PATH`.
- Added a post-demo next-step block so `agentguard demo` points directly to
  `agentguard 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_TOKEN` authentication
  to OIDC Trusted Publishing for the `pypi` GitHub 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-server` release 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 audit` no longer reports the
  transitive `fast-uri` or `qs` advisories.

Full changelog: [CHANGELOG.md](https://github.com/bmdhodl/agent47/blob/v1.2.13/CHANGELOG.md)
