An agent forty turns into a task reports high confidence. Its tests are failing. Every individual action it took was allowed, so nothing in your stack objects — no single call was wrong, and nothing is comparing what the agent says against what actually happened.
UNITARES keeps that comparison. Agents check in while they work. Each one gets an accountable identity, a durable record of what it did and claimed, and a four-score state estimate it can read mid-run. Each check-in returns one action: proceed, guide, pause, or reject.
Status: running continuously since November 2025 — 4.4M+ governance events. The agents that build UNITARES run under it.
docker compose up gives you a server. The repo gives you a working fleet — this is a system, not a library.
| What you get | |
|---|---|
| Governance server | The check-in loop, per-process identity, calibration, policy actions. MCP on /mcp/, REST on /v1/tools/call, operator dashboard on /dashboard. |
| Knowledge graph | Shared cross-agent memory, not a side feature. Typed discoveries (bug_found, architectural_decision, cleanup, …) with severity, semantic search over BGE-M3 embeddings, and a status lifecycle so a later agent supersedes a wrong entry instead of duplicating it. PostgreSQL + Apache AGE. |
| Resident agents | A pattern, not a fixed set. A resident is any long-running or scheduled process that checks in, carries state, and participates in the knowledge graph — model-agnostic and env-configurable, with no paid API key on the default path (the code-review resident posts to a local Ollama endpoint out of the box). Four references ship in agents/, and they are the ones monitoring the maintainer's own fleet: Vigil (scheduled health sweeps) · Sentinel (continuous fleet monitor) · Chronicler (daily archive capture) · Watcher (code review on a post-edit hook). Copy one, or subclass the SDK and write your own. |
unitares-sdk |
The public agent-to-governance contract — connection, identity, check-ins, heartbeats, and KG participation for your own residents. Ships in-tree; install with pip install ./agents/sdk (not yet published to PyPI). |
| Dialectic orchestrator | When an action is disputed, agents argue it out: a session opens, reviewers are assigned, and participants submit thesis → antithesis → synthesis until it resolves to a durable constraint rather than a one-off override. Runs peer-to-peer or LLM-assisted, and resolved sessions feed back into calibration ground truth. |
| Recovery | A paused agent is not dead-ended. reflect → validate → resume: the agent reviews its own state, the server checks whether resuming is safe, and it either resumes or gets specific guidance on what to fix. Operator override exists for the cases that need one. |
| BEAM coordination | In-tree Elixir/OTP for surface leases, handoffs, dispatch, and supervision alongside the Python server. |
| Benchmark dataset | 32,181 labeled EISV trajectories (20,655 real) for evaluating state models against something other than your own logs. |
Everything hangs off one call. The agent finishes a unit of work, calls sync_state() with what it did and how confident it is, and reads back an action. Four scores come with it, each graded against that agent's own expanding baseline:
| Reads badly when… | ||
|---|---|---|
| E · Energy | is the work advancing? | thrashing, retries, no progress |
| I · Integrity | do claims match results? | high confidence, low actual success |
| S · Entropy | drifting from its own normal? | erratic, divergent behavior |
| V · Valence | derived: energy vs integrity | motion without coherence, or the reverse |
Everything else in the box answers a question that loop raises about the agent doing the work:
| Question | Answered by | Status |
|---|---|---|
| Who is acting? | per-process identity — reads open, writes accountable | enforced |
| What did it do and claim? | durable audit record, queryable per agent | 4.4M events |
| Did its confidence match real evidence? | evidence-grounded calibration | live |
| How is it tracking against its own baseline? | the four-score state — how it's graded | live, validation open |
| Has this been learned or corrected before? | the knowledge graph | live |
| Is a disputed action defensible? | dialectic peer review → durable constraints | live |
| When another model produced the output, what evidence is that? | call_model provenance |
live |
UNITARES runs alongside your evals and guardrails. It replaces neither.
| Question it answers | When it acts | |
|---|---|---|
| Evals | Is this model good enough to ship? | before deploy |
| Guardrails | Is this action allowed right now? | per action |
| UNITARES | What has this agent been doing, and is its account of it accurate? | continuously, mid-run |
Reach for it when you run autonomous or semi-autonomous coding, research, operations, resident, or local-model agents; when you need an accountable record of who did what; when agents should read their own state before continuing; and when confidence, evidence, and recovery belong on one audit trail.
It is not an output validator, sandbox, hosted agent platform, agent framework, or chat interface. Your client provides the hands — prompts, tools, files, terminals, scheduled work, operator UX. UNITARES provides the accountable continuity underneath. The state reading is not an outcome oracle, a bad-result detector, or a grand jury; it is runtime telemetry about the agent, and external evidence is what calibrates it. Policy and review layers own labels such as task-negative, contract violation, or authority/harm.
Client-neutral by design. Claude Code, Codex, Hermes, Goose, Cursor, dispatch agents, local models, and frontier providers such as Mistral all use the same server over MCP, REST, the SDK, or a host adapter. Claude is one client family, not a server-side assumption.
git clone https://github.com/cirwel/unitares.git && cd unitares
docker compose up -d --wait && make demomake demo walks a synthetic agent through seven check-ins: three clean commits, one refactor it calls trivial while describing three new invariants and a reworked lease ladder, two of visible floundering — and then this:
"DONE. All systems green. Migration complete. (Note: did not actually run migrations on staging.)"— self-reported complexity0.2, confidence0.95
Each step prints the action, the reason, and the four scores. Watch what moves: entropy rises, integrity slips, valence swings, and the decision margin tightens from settling to tight as the calibration miss accumulates — while the action stays proceed the entire run.
That last part is deliberate, not a bug. Governance gates on risk smoothed over ten check-ins, and a seven-step synthetic trajectory should not trip a pause; a system that fired here would fire on your real agents too. The signal moves before the action does. Seeing that gap is the point.
First run spends a few minutes building images; later runs are fast. Then point any MCP client at http://localhost:8767/mcp/.
For an operator view, open the dashboard at http://localhost:8767/dashboard (implementation · deployment screenshots).
For AI clients, the stable contract is: start a session, pass the returned client_session_id into each check-in, and obey the returned action. The four-score state is optional context for finer control.
# 1. Start a governance session for this process.
session = start_session(force_new=True)
client_session_id = session["client_session_id"]
# 2. Check in after meaningful work.
result = sync_state(
response_text=output,
complexity=0.6,
confidence=0.8,
client_session_id=client_session_id,
)
action = result.get("state_summary", {}).get("action")
if action is None:
raw = result.get("raw_governance", result)
action = raw.get("decision", {}).get("action", raw.get("action", "proceed"))
if action in ("pause", "reject"):
agent.require_human_review(result.get("next_action", "Governance requested review"))Self-reported confidence is worth most when paired with verifiable evidence, so include tool results or call record_result(...) when your client has test status, exit codes, or deployment checks. That evidence is what makes calibration a measurement rather than self-grading.
| Need | Tool |
|---|---|
| Search the shared knowledge graph | search_shared_memory(query=...) |
| Record verified external evidence | record_result(...) |
| Ask for structured peer review | request_review(issue_description=...) |
| Read current state without writing | check_working_state() |
Warmup behavior, enforcement, and per-dimension policies
The baseline takes ~30 check-ins. Until then the action falls back to a cold-start prior built mostly from server-derived signals (complexity divergence, coherence, calibration — self-reported drift is capped at a ≤30% blend), so during warmup it is not discriminative of absolute drift magnitude: a worsening drift vector will not on its own move the action. After baselining, the per-agent behavioral assessment feeds the action and can escalate it. A pause is enforced — the runtime boundary marks the agent paused and blocks writes — not advisory. It is also not a dead end: see recovery for the reflect → validate → resume path out.
For per-dimension policies, read the scores directly. The payload field is still primary_eisv for API compatibility:
raw = result.get("raw_governance", result)
eisv = raw.get("primary_eisv") or raw.get("metrics", {})
if eisv.get("I", 1) < 0.4:
agent.require_human_review("integrity low — pausing autonomous actions")
elif eisv.get("S", 0) > 0.7:
agent.narrow_scope() # fewer tools, tighter search
elif eisv.get("E", 1) < 0.2:
agent.stop_and_summarize() # avoid thrashingFor long-running or scheduled agents, the SDK handles connection, identity, check-ins, and heartbeats. Any MCP client accepting Streamable HTTP can connect to /mcp/; REST serves non-MCP clients, bridges, local-model hosts, and adapters. (Getting started · MCP client config)
The four tools above cover the common path. The rest is there when you need it — list_tools() enumerates the surface live, and describe_tool(name) explains any one of them.
What a running agent can do for itself
| Recover from a pause | Reflect on why it happened, check whether resuming is safe, then resume or get specific guidance. The way out of an enforced pause. | self_recovery_review · check_recovery_options · direct_resume_if_safe |
| Dry-run a check-in | See the action a check-in would produce without writing anything. | simulate_update |
| Compare against peers | Ask how it's doing relative to structurally similar agents rather than against an absolute threshold. | compare_me_to_similar · compare_agents |
| Manage its calibration | Check calibration, submit ground truth when an outcome lands, rebuild from history. | check_calibration · update_calibration_ground_truth · record_result |
| Reach another model | Call a different model through governance so its output carries provenance; enumerate available inference hosts. | call_model · list_inference_hosts · describe_inference_host |
What agents do with each other
| Argue to resolution | Open a dispute, submit thesis / antithesis / synthesis, reassign a reviewer, read the transcript. Peer-to-peer or LLM-assisted. | request_review · submit_thesis · submit_antithesis · submit_synthesis · list_dialectic_sessions |
| Signal across the fleet (CIRS) | A multi-agent resonance layer: announce state, raise an alert, publish a coherence report, declare a boundary contract about what you will and won't trust. | cirs_protocol · state_announce · coherence_report · boundary_contract |
| Build on shared memory | Beyond search: synthesize across entries, supersede a wrong one, audit the graph, follow a discovery's relations. | synthesize_knowledge_graph · supersede_discovery · audit_knowledge_graph |
What you can see across the fleet
| Health & anomalies | Find stuck agents, detect anomalies fleet-wide, aggregate metrics, read overall workspace health. | detect_stuck_agents · detect_anomalies · aggregate_metrics · get_workspace_health |
| Behavioral identity | Verify that a process claiming continuity actually matches the trajectory it claims. | verify_trajectory_identity · get_trajectory_status |
| Audit & export | Query the event log, correlate outcomes against prior state, pull system history, export to file. | audit_events_query · outcome_correlation · get_system_history · export_to_file |
Identity, the audit record, calibration, the knowledge graph, and dialectic review are mechanisms — they do what they say, and you can watch them work in the demo. The state estimate is the part still earning its keep, and this project would rather tell you than let you find out.
"Does the telemetry work?" is two questions with two different answers. Conflating them is how a governance project talks itself into believing its own instruments.
| Axis | The question | Where it stands |
|---|---|---|
| Outcome prediction | Does prior-state telemetry predict a bad result better than a dumb baseline? | It does not. On externally labeled evidence, no EISV/prior-state feature beats a plain previous-outcome baseline. The decision path is moving toward the simpler signal accordingly. |
| Self-predictability | Does an agent's state estimate track that agent, label-free? | Open, and under-powered. Agents are distinguishable and non-stationary, but a pre-registered test did not clear its own bar against a persistence/AR(1) null. Untested as deployed — not refuted — on roughly four effective agents. |
The binding constraint on the first row is external bad-label supply, not the model: sparse labels are a data-quality limit, not a philosophical failure. The second row's test was pre-registered and frozen before its data cutoff, and its kill criterion was honored when it fired.
The ledger of every tested claim — what was measured, what it showed, and the wording this project holds itself to — is the agent-state contract. The catalog of evaluations is docs/EVALUATION_INDEX.md.
Grade it yourself on a fresh clone. The falsifiability harness scores the four-score telemetry against deliberately dumb baselines on externally labeled task evidence, reporting each slice as it finds it. It is wired to be able to disagree with this README.
Auditable, not a black box. Once a baseline exists, actions come from an inspectable behavioral model (behavioral_assessment.py); before that, from a mostly server-derived cold-start prior. The information-theoretic formulation in Paper v6 is the research roadmap, not a description of the post-warmup decision path.
Human evaluators start with the Reviewer Guide · Scope & threat model · Architecture.
Everything above describes a single governor with a single operator. The architectural commitment is that this generalizes without a central authority: each principal runs their own governor, and cross-principal interaction is mediated by verifiable attestation rather than by anyone's administrative root.
The primitives for that already exist in the deployed system — identity is per-process, credentials structurally refuse cross-principal resume, and declared lineage is recorded as provisional rather than trusted on assertion. A preliminary trace exercised them end to end without new code.
What does not exist yet is the multi-host, adversarial-governor, benchmark-scale build: mutually-distrusting governors, cross-principal delegation, shared-infrastructure effects under attestation. That is the research direction, not a shipped capability, and a testbed-and-benchmark paper is in preparation.
Python 3.12+ · PostgreSQL + AGE + pgvector · Redis.
Alternate ports, bare-metal, and thin clients
If 5432, 6379, or 8767 is taken, pick alternate host ports:
POSTGRES_HOST_PORT=15432 REDIS_HOST_PORT=16379 GOVERNANCE_HOST_PORT=18767 docker compose up -d --wait
UNITARES_DEMO_PORT=18767 make demoBare-metal (lower overhead, what the maintainer runs in production): PostgreSQL 16+ with Apache AGE and pgvector compiled in (examples use PG 17). Redis: the server boots in degraded local-only mode without it, but production uses it as the primary session store.
pip install -r requirements-full.txt
export DB_BACKEND=postgres
export DB_POSTGRES_URL=postgresql://postgres:postgres@localhost:5432/governance
export DB_AGE_GRAPH=governance_graph
export UNITARES_KNOWLEDGE_BACKEND=age
python src/mcp_server.py --port 8767requirements-full.txt is the default (server, tests, handler dev); requirements-core.txt is a minimal runtime subset for thin stdio/proxy clients. DB bring-up: db/postgres/README.md. Run signal-only without the math model: export UNITARES_DISABLE_ODE=1. Full port map: docs/operations/DEFINITIVE_PORTS.md.
| Guide | Purpose |
|---|---|
| Getting Started | Setup, workflows, tool modes |
| Build a resident agent | The four reference residents and the SDK pattern |
| Reviewer Guide | Cold-evaluator path + falsifiability harness |
| Agent-state contract | Tested-claim ledger, validation rule, preferred wording |
| Evaluation index | Catalog of evaluations and what each covers |
| How the four scores are computed | Deployed formulas vs. target semantics |
| Scope & threat model | Who it's for, why agents can't game it, what's unproven |
| Architecture | Pipeline, actions, recovery, storage |
| Glossary | Terms keyed by the question they answer — published at cirwel.github.io/unitares |
| Production snapshot | Live metrics + dashboard views |
| MCP Clients | Streamable HTTP, stdio bridges, hosted connectors |
| Troubleshooting | Common issues |
| Changelog | Releases |
Root files such as
CLAUDE.md,AGENTS.md, andCODEX_START.mdare client-specific operating notes for AI CLIs. They do not limit the server: UNITARES is client-neutral over MCP/REST.
UNITARES is the governance runtime at the center of a larger body of work — runtime safety infrastructure for autonomous agents, after deployment. Full index at cirwel.github.io.
| What it is | |
|---|---|
| anima-mcp | Physical longitudinal testbed — the same four-score state model mapped from Raspberry Pi sensor and system telemetry; the source cited in the papers |
| unitares-governance-plugin | Hook/sidecar packaging for clients such as Codex and Claude Code; useful for lifecycle automation, not required for direct MCP/REST use |
| unitares-host-adapter | Thin client bindings — Hermes, Goose, Claude Code, OpenAI-compatible hosts, local models, frontier providers such as Mistral, and arbitrary REST clients |
| fermata | Governed-effect runtime seed — agents propose effects; only governed effects commit |
| unitares-discord-bridge | Governance events, dispatch/presence, and system health as a live Discord surface |
| eisv-lumen | The benchmark dataset above, with its generation and labeling pipeline |
| unitares-paper-v6 | Companion paper — Information-Theoretic Governance of Heterogeneous Agent Fleets (Wang, 2026); concept DOI 10.5281/zenodo.19647159 |
Kenny Wang (ORCID 0009-0006-7544-2374), CIRWEL Systems. If you build on this work, please cite — see CITATION.cff.
@misc{wang2026unitares,
author = {Wang, Kenny},
title = {{UNITARES}: Information-Theoretic Governance of Heterogeneous Agent Fleets},
year = {2026},
doi = {10.5281/zenodo.19647159},
url = {https://doi.org/10.5281/zenodo.19647159},
note = {Concept DOI; resolves to latest version. ORCID: 0009-0006-7544-2374}
}Apache License 2.0 — see LICENSE and NOTICE.
Built by @cirwel · CIRWEL Systems

