{"id":47633712,"url":"https://github.com/ryanwi/agent-control-plane","last_synced_at":"2026-06-02T07:00:23.648Z","repository":{"id":342477034,"uuid":"1174057780","full_name":"ryanwi/agent-control-plane","owner":"ryanwi","description":"Production-oriented governance control plane for autonomous AI agents. Policy engine, approval gates, budget tracking, kill switches, and auditable event sourcing.","archived":false,"fork":false,"pushed_at":"2026-06-02T05:53:12.000Z","size":808,"stargazers_count":0,"open_issues_count":11,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-02T06:11:24.315Z","etag":null,"topics":["agent-control-plane","agent-governance","ai-agents","human-in-the-loop","policy-engine"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ryanwi.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/security_model.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-06T02:55:06.000Z","updated_at":"2026-06-02T05:53:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ryanwi/agent-control-plane","commit_stats":null,"previous_names":["ryanwi/agent-control-plane"],"tags_count":51,"template":false,"template_full_name":null,"purl":"pkg:github/ryanwi/agent-control-plane","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanwi%2Fagent-control-plane","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanwi%2Fagent-control-plane/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanwi%2Fagent-control-plane/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanwi%2Fagent-control-plane/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ryanwi","download_url":"https://codeload.github.com/ryanwi/agent-control-plane/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanwi%2Fagent-control-plane/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33810343,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-02T02:00:07.132Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-control-plane","agent-governance","ai-agents","human-in-the-loop","policy-engine"],"created_at":"2026-04-01T23:56:26.854Z","updated_at":"2026-06-02T07:00:23.633Z","avatar_url":"https://github.com/ryanwi.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# agent-control-plane\n\n[![CI](https://github.com/ryanwi/agent-control-plane/actions/workflows/ci.yml/badge.svg)](https://github.com/ryanwi/agent-control-plane/actions/workflows/ci.yml)\n\nSafety and approval controls for AI agents.\n\nThe **control plane** decides when/how an agent may act. The **data plane** executes side effects.\n\n## Watch Demo\n\n[Watch interactive terminal recording](https://asciinema.org/a/Mrl2E8gMbNLzNKuM)\n\n[![Agent story terminal demo](docs/demo/control-plane-agent-story.gif)](https://asciinema.org/a/Mrl2E8gMbNLzNKuM)\n\n## Why This Exists\n\nAgent stacks handle execution well; governance is the gap. This package provides:\n\n- Deterministic policy enforcement before execution.\n- Human/risk approval gates for high-impact actions.\n- Budget guardrails and kill-switch semantics.\n- Durable event history for audit, replay, and recovery.\n\nGood fit:\n\n- Platform teams running production agent workflows.\n- Teams needing explicit human-in-the-loop and policy controls.\n- Multi-agent systems requiring auditable decisions.\n\nLess useful:\n\n- One-off demos with no side effects.\n- Prompt/tooling projects that do not need governance.\n\n## Adoption tiers\n\nPick the tier that matches your use case — each builds on the previous one.\n\n### Tier 1 — Cost tracking only (5 minutes)\n\nToken budget enforcement and per-call usage ledger. No sessions, no governance. Works standalone.\n\n```bash\nuv run python examples/tenant_budget_tracking.py\n```\n\n### Tier 2 — Audit trail (add sessions)\n\nWrap agent runs in a tracked session. Records cost, duration, and outcome without any approval gates.\n\n```bash\nuv run python examples/audit_trail.py\n```\n\n### Tier 3 — Full governance\n\nPolicy enforcement, human approval gates, kill switch, multi-agent revocation.\n\n```bash\nuv run python examples/quickstart_sync.py\n```\n\n---\n\n## Install\n\n```bash\npip install agent-control-plane\n```\n\n## Local Dev\n\n```bash\nuv sync --extra dev\nmake check\n```\n\n## Quickstart\n\nUse the runnable sync quickstart:\n\n```bash\nuv run python examples/quickstart_sync.py\n```\n\nACP-first continuous loop examples:\n\n```bash\nuv run python examples/single_agent_continuous_loop.py\nuv run python examples/multi_agent_continuous_loop.py\nuv run python examples/continuous_loop_governance.py\nuv run python examples/long_running_autonomous_agent.py --horizon day\n```\n\nOptional SDK integrations (requires provider SDK + API key):\n\n```bash\nuv run python examples/openai_agents_sdk_integration.py\nuv run python examples/claude_agent_sdk_integration.py\n```\n\nFor the narrated terminal walkthrough used in the demo video:\n\n```bash\nmake demo-asciicast-agent\n```\n\n## Core Capabilities\n\n- Policy and routing: `PolicyEngine`, `ProposalRouter`\n- Steering: `ActionTier.STEER` with corrective `SteeringContext` guidance and suggested alternatives\n- Human approvals: `ApprovalGate`, scoped ticket decisions\n- Budget enforcement: `BudgetTracker`\n- Token governance: `TokenBudgetTracker` (identity-scoped token/cost budgets), `ModelGovernor` (model tier access policy)\n- Concurrency and kill switches: `ConcurrencyGuard`, `KillSwitch`\n- Condition trees: `ConditionEvaluator` with recursive `and`/`or`/`not` rules for policy composition\n- Pluggable evaluators: `EvaluatorRegistry` with entry-point discovery, built-in `RegexEvaluator` and `ListEvaluator`\n- Parallel evaluation: `ParallelPolicyEvaluator` with cancel-on-deny semantics\n- Egress governance: `EgressEvaluator` — capability-grant model (destination + capability must both be explicitly allowed)\n- Durable events and replay: `EventStore`\n- Session lifecycle and recovery: `SessionManager`, `CrashRecovery`, `TimeoutEscalation`, session state integrity validation\n- Host wrappers: `ControlPlaneFacade` (sync), `AsyncControlPlaneFacade` (async)\n\n## Token Budget Tracking\n\nIdentity-scoped, persistent token/cost budgets — useful as a first integration point for consumers (much smaller surface than the full proposal lifecycle).\n\n```python\nfrom agent_control_plane import (\n    ControlPlaneSetup, GovernanceConfig, IdentityContext, OrgId, ModelId, TokenUsage,\n)\n\ncp = ControlPlaneSetup(database_url, governance=GovernanceConfig(token_budget_configs=[...])).build_async()\n\nasync with cp.token_budget_tracker() as tracker:\n    identity = IdentityContext(org_id=OrgId(\"tenant-acme\"))\n    usage = TokenUsage(\n        model_id=ModelId(\"claude-haiku-4-5\"),\n        input_tokens=1234,\n        output_tokens=567,\n        total_tokens=1801,\n        estimated_cost_usd=0.0042,  # float accepted, coerced via Decimal(str(...))\n    )\n    await tracker.record_usage(None, identity, usage)  # session_id is optional\n```\n\nRunnable end-to-end example covering seeding, tenant scoping, exhaustion, and cross-process persistence:\n\n```bash\nuv run python examples/tenant_budget_tracking.py\n```\n\nNotes:\n\n- `session_id=None` records usage without a control-plane session FK. Use a real session UUID if you want the `TOKEN_USAGE_RECORDED` event to land in the event log.\n- The context manager opens a fresh DB session and commits on clean exit. For shared-transaction recording, use `TokenBudgetTracker.from_session(your_session)` instead.\n- **Pre-call enforcement caveat:** `tracker.check_budget(...)` exists as a pre-call hook, but using it requires you to know the prompt token count in advance. OpenAI-compatible SDKs don't expose this without a separate tokenizer (e.g. `tiktoken`). For OpenAI-compatible consumers, the practical pattern is post-call `record_usage` with a local soft-ceiling as defense-in-depth.\n- **Ledger reflects actual spend, including blocked attempts.** `record_usage` writes the ledger row *before* raising `TokenBudgetExhaustedError`, so over-budget calls that already incurred provider cost are still recorded. Callers catching the exception cannot assume \"raised ⇒ nothing written\" — the row and the `TOKEN_USAGE_RECORDED` event have already landed. This keeps the ledger accurate as a cost-reporting source under post-call enforcement.\n\n## Runtime Notes\n\n- Treat `state_bearing=True` events as fail-closed.\n- Prefer `ScopedModelRegistry` for production embedding.\n- Use SQLite for local/single-process; use Postgres for multi-worker production.\n\n## Docs \u0026 API\n\n- Architecture: [docs/architecture.md](docs/architecture.md)\n- Operations runbook: [docs/operations_runbook.md](docs/operations_runbook.md)\n- Continuous operation playbook (1h/day/week/month): [docs/continuous_operation_playbook.md](docs/continuous_operation_playbook.md)\n- Security model: [docs/security_model.md](docs/security_model.md)\n- Identity integration: [docs/integration_identity.md](docs/integration_identity.md)\n- Compatibility \u0026 upgrading: [docs/compatibility.md](docs/compatibility.md)\n- OpenAPI contract (companion gateway): [docs/openapi/control-plane-v1.yml](docs/openapi/control-plane-v1.yml)\n- Public API exports: [src/agent_control_plane/__init__.py](src/agent_control_plane/__init__.py)\n\n## Examples\n\n- Audit trail (Tier 2): [examples/audit_trail.py](examples/audit_trail.py)\n- Sync quickstart: [examples/quickstart_sync.py](examples/quickstart_sync.py)\n- Async quickstart: [examples/quickstart.py](examples/quickstart.py)\n- Single-agent continuous loop: [examples/single_agent_continuous_loop.py](examples/single_agent_continuous_loop.py)\n- Multi-agent continuous loop: [examples/multi_agent_continuous_loop.py](examples/multi_agent_continuous_loop.py)\n- Asciicast sync demo: [examples/asciinema_sync_demo.py](examples/asciinema_sync_demo.py)\n- Continuous-loop governance example: [examples/continuous_loop_governance.py](examples/continuous_loop_governance.py)\n- Long-running autonomous example: [examples/long_running_autonomous_agent.py](examples/long_running_autonomous_agent.py)\n- OpenAI Agents SDK integration: [examples/openai_agents_sdk_integration.py](examples/openai_agents_sdk_integration.py)\n- Claude Agent SDK integration: [examples/claude_agent_sdk_integration.py](examples/claude_agent_sdk_integration.py)\n- Asciicast story runner: [scripts/run_asciicast_agent_story.sh](scripts/run_asciicast_agent_story.sh)\n- Audit replay: [examples/audit_viewer.py](examples/audit_viewer.py)\n- Token governance demo: [examples/token_governance_demo.py](examples/token_governance_demo.py)\n- MCP gateway demo: [examples/mcp_tool_gateway.py](examples/mcp_tool_gateway.py)\n- Steering demo: [examples/steering_demo.py](examples/steering_demo.py)\n- Condition trees and evaluator plugins: [examples/condition_tree_evaluator_demo.py](examples/condition_tree_evaluator_demo.py)\n- Companion REST/dashboard starter: [examples/companion_gateway](examples/companion_gateway)\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryanwi%2Fagent-control-plane","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fryanwi%2Fagent-control-plane","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryanwi%2Fagent-control-plane/lists"}