This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
uv sync --extra dev # Install dependencies
uv run pytest -q # Run all tests
uv run pytest tests/<file> -q # Run single test file
uv run pytest -k "test_name" # Run single test by name
make docs-drift # Validate instruction/docs alignment
make check # Lint + typecheck + test (all at once)Embeddable, self-hosted governance framework for autonomous agent runtimes. Separates control plane (policy, approvals, budgets, kill switches) from data plane (actual execution of side effects). See docs/architecture.md for full design rationale.
engine/— Core engines (policy, routing, approvals, budgets, concurrency, kill switch, events, sessions, agent registry, action policy, condition evaluator, parallel evaluator). Each is a standalone class; caller manages DB transactions.evaluators/— Pluggable evaluator framework:Evaluatorprotocol,EvaluatorRegistry(manual + entry-point discovery), built-inRegexEvaluatorandListEvaluator.storage/— Repository protocol interfaces (protocols.py) + SQLAlchemy backends (async & sync). Decouples engines from any specific DB.mcp/—McpGatewayfor governing MCP tool calls through the control plane.sync.py—SyncControlPlane/ControlPlaneFacade— synchronous high-level API wrapping the async engines.recovery/— Crash recovery (stale cycle release) and timeout escalation.types/— Pydantic v2 DTOs and enums:enums,policies,proposals,approvals,agents,frames,sessions,steering,conditions.models/—ModelRegistryfor lazy ORM resolution, SQLAlchemy mixins, and ready-to-use reference models (reference.py).
- Repository protocols in
storage/protocols.pydefine the DB abstraction. Engines depend on protocol interfaces, not concrete backends. - ModelRegistry: Host apps register ORM models at startup; engines resolve via
ModelRegistry.get("ModelName"). - Engines don't own transactions — the caller manages
commit(). - Public API is centralized in
__init__.py: Import fromagent_control_planedirectly, not from submodules.
PolicyEngine.classify()→ risk level + action tier (incl.STEER)ConditionEvaluator.evaluate()→ optional tree-based auto-approve rulesProposalRouter.route()→ routing decision (withSteeringContextif steered)ParallelPolicyEvaluator.evaluate_all()→ optional concurrent evaluator checksApprovalGate→ session-scope check or ticket creationBudgetTracker→ budget check + incrementConcurrencyGuard→ resource lockKillSwitch→ emergency stop check- Execution (caller's data plane)
EventStore.append()→ audit event
Higher-level entry points: McpGateway (MCP tool calls) and SyncControlPlane (synchronous facade) orchestrate this flow automatically.
- Use conventional commits:
feat:,fix:,refactor:,test:,docs:,chore: - Don't add domain-specific business logic into core engine modules
state_bearing=Truepersistence errors must fail closed (raise), never swallow- Don't bypass control engines for state transitions — always go through the engine API
- Ruff and mypy config lives in
pyproject.toml— runmake checkto verify - Tests use
pytest-asynciowithasyncio_mode = "auto"
docs/architecture.md— Full architecture and deployment posturedocs/security_model.md— Trust boundaries and security posturedocs/integration_identity.md— Identity integration guidedocs/operations_runbook.md— Production operations workflow