Skip to content

seslak/agent-governor

Repository files navigation

Agent Governor

Deterministic run-scoped governance for local coding agents: budget profiles, SQLite ledgering, patch/test checks, and advisory continue/warn/ask/stop decisions.

What it provides

  • Expanded budget profiles: research_only, analysis, documentation_read, documentation_write, data_intake, tiny_fix, small_patch, medium_refactor, feature_work, architecture_review, debug_failure, test_work, exploratory_work, general_work, maintenance_work, supervised_work.
  • SQLite-backed run ledger at state/governor/governor.sqlite.
  • Queryable runs/events/tests/patches with recent/search/get actions.
  • Patch guard from unified git diff analysis.
  • Test recording and summaries.
  • Deterministic policy decisions: continue, warn, ask_confirmation, stop.
  • CLI and MCP surfaces backed by the same service layer.

State location

  • Default: <AGENT_GOVERNOR_ROOT>/state/governor/governor.sqlite
  • Override directory with: AGENT_GOVERNOR_STATE_DIR
  • Legacy .agent-governor folders are tolerated but no longer used as default.

Quick start

python -m pip install -e .
python -m agent_governor init
python -m agent_governor start --task "fix thrift prompt loop" --profile small_patch
python -m agent_governor check-budget
python -m agent_governor patch-check
python -m agent_governor record-test --command "python -m unittest" --exit-code 0 --summary "tests passed"
python -m agent_governor status
python -m agent_governor finish --status success

Local source usage without install:

$env:PYTHONPATH="src"
python -m agent_governor profiles

CLI commands

python -m agent_governor init
python -m agent_governor profiles
python -m agent_governor doctor
python -m agent_governor version
python -m agent_governor start --task "..." --profile small_patch
python -m agent_governor start --task "..." --profile small_patch --allow-parallel
python -m agent_governor event --kind tool_call --data '{"tool":"thrift.file_window","path":"README.md"}'
python -m agent_governor event --kind tool_call --run-id "<run_id>" --data '{"tool":"thrift.file_window","path":"README.md"}'
python -m agent_governor record-test --command "python -m unittest" --exit-code 0 --summary "ok"
python -m agent_governor check-budget
python -m agent_governor check-budget --read-only
python -m agent_governor patch-check
python -m agent_governor status
python -m agent_governor status --read-only
python -m agent_governor finish --status success --report
python -m agent_governor finish --result success
python -m agent_governor sync-thrift
python -m agent_governor stats --since-days 30
python -m agent_governor reset --yes

finish --result is an alias for finish --status. If both are provided, they must match.

status --read-only and check-budget --read-only pass record_check=false through the shared service layer and MCP gateway. Use them for passive polling that must not bump governance counters, mutate run decisions, or create diagnostic stability rows.

MCP server

  • Module: src/agent_governor/mcp_server.py
  • Root selection: AGENT_GOVERNOR_ROOT (defaults to current working directory)
  • State override: AGENT_GOVERNOR_STATE_DIR
  • Public tool surface: exactly one MCP tool, governor

Gateway input shape

{
  "action": "start_run",
  "params": {
    "task": "Fix failing tests",
    "profile": "small_patch"
  }
}

Supported gateway actions

  • doctor
  • version
  • list_profiles
  • start_run
  • record_event
  • record_tool_call
  • record_test
  • patch_check
  • check_budget
  • status
  • finish_run
  • reset_run
  • recent_runs
  • get_run
  • search_runs
  • recent_events
  • search_events
  • get_event
  • maintenance
  • sync_thrift
  • stats

Maintenance action values

  • doctor
  • stale_runs
  • close_stale_runs_dry_run
  • close_stale_runs_apply (requires confirm=true)
  • prune_old_events_dry_run
  • prune_old_events_apply (requires confirm=true)
  • prune_old_runs_dry_run
  • prune_old_runs_apply (requires confirm=true)
  • export_jsonl

Query params

  • get_run(include_events=true) accepts events_limit (default 200, max 2000)
  • recent_runs, recent_events, search_runs, and search_events accept offset
  • run-scoped actions accept optional run_id

PowerShell quoting

Use single quotes around the outer JSON payload:

python -m agent_governor event --kind tool_call --data '{"tool":"thrift.file_window","path":"README.md","detail":"x,y"}'

Suite integration

  • Set AGENT_SUITE_SESSION_ID for Governor run/session correlation.
  • Set THRIFT_SESSION_ID=$AGENT_SUITE_SESSION_ID in the same client config so sync_thrift can match both time window and session id.
  • sync_thrift imports thrift economy_events from THRIFT_SQLITE_FILE or state/thrift/thrift.sqlite.
  • The thrift_sqlite tool argument is bounded to the governor root, while THRIFT_SQLITE_FILE is treated as trusted user configuration and is not root-bounded.
  • finish --report writes a Markdown run summary under state/governor/reports/.

Run ledger model

Governor stores run metadata in runs and run chronology in run_events, with normalized run_tests and run_patches tables. Searches use FTS5 when available and fall back to LIKE queries otherwise.

Exports from maintenance(action="export_jsonl") are restricted to paths inside the governor root.

Running tests

python -m compileall -q .
python smoke_test.py
python mcp_smoke_test.py
python -m unittest discover -s . -p "test*.py"

License

MIT