Skip to main content
Glama

Accountability infrastructure for long-running AI agents.

A self-hosted record your agents write to. Across sessions and runtimes, any agent or operator can look up who claimed what, on what evidence, who disputed it, and what replaced it.

Tests Python License DOI Glama score

Agent work outlives the process that started it. Git, scratchpads, and handoff notes carry code and in-flight task state; UNITARES keeps the shared record of claims, reviews, and outcomes across runs. When a finding is corrected or a change is challenged, the next session reads the updated record instead of acting on a superseded claim.

UNITARES is a server you run that keeps that record. Any agent or model that speaks MCP or HTTP can connect (with ready integrations for Claude Code, Codex, and Hermes Agent) and write its findings, reviews, and results to one operator-owned record. A later agent, or you, can read it back and see where each piece came from.

See one incident without installing anything → · Read the evidence · Install

What the record answers

Question

Mechanism

Who said it?

Identity and lineage: every write to the record is bound to the process that made it, and a successor can declare which process it continues.

What supports it?

Claims and evidence: findings keep their sources and corrections outside any single context window. When a newer finding replaces an older one, the older one links to it.

Who challenged it?

Governed review: objections, conditions, and their resolution stay on the work they concern. Asking for review is not the same as passing it.

What happened?

Outcome grounding: test, build, and task results are recorded against the check-ins that predicted them.

What can a successor recover?

Reconstruction: a new process can search or export prior findings, open review conditions, and outcomes before it acts.

Digital proprioception runs on the check-in path: EISV summarizes behavioral observations over time and returns state feedback and a policy recommendation (computation contract). Second opinions let consult ask a connected local or orchestrated model, and structured dialectic records thesis, challenge, and resolution on the work.

Related MCP server: hejdar-mcp

See the record before installing

Agent A (Codex) finds a bug, records it, and exits. Agent B (Claude Code) later finds the real cause and records a finding that supersedes A's. Agent C (Hermes Agent) works on the same area in a later session and reads the record before touching the code (reading needs no identity): its search returns A's finding marked superseded, with a link to B's. C then declares lineage from A. This API sketch is separate from the hosted service-reload incident.

# Agent A (Codex)
start_session  {"force_new": true}                                     -> agent A's id
store_finding  {"summary": "upload retry test is flaky", ...}           -> finding a
record_result  {"outcome_type": "test_failed", ...}

# Agent B (Claude Code), in its own session, later
start_session  {"force_new": true}                                     -> agent B's id
store_finding  {"summary": "upload retry fails on clock skew", ...}     -> finding b
use_tool       {"tool_name": "knowledge", "arguments": {"action": "supersede", "discovery_id": "<b>", "supersedes_id": "<a>"}, ...}

# Agent C (Hermes Agent), in a later session
search_shared_memory {"query": "upload retry test"}   -> finding a (superseded, points to b), finding b
start_session  {"force_new": true, "parent_agent_id": "<A's id>", "spawn_reason": "explicit"}

The Claude Code and Codex plugin's session start points each new session at the record. For a complete call-by-call sequence, see the captured two-process walkthrough.

Install

Homebrew preview, recommended for an Apple Silicon desktop Mac: the cirwel/unitares tap installs the services natively; follow its install and first-time setup. The packaged unitares update coordinates writer shutdown, verified backup, migrations, prior-state restoration, and deep health when writers restart (schema verification when they remain stopped); kegs that predate it use the tap's one-time manual transition.

Docker Compose, on any platform: with Git, curl, and Docker Compose installed, one command starts the latest published release of the local stack (the server, PostgreSQL with AGE and pgvector, Redis, and the coordination plane; add docker-compose.full.yml for local semantic search and hybrid ranking, or use the core profile to run only the first two):

v=$(curl -fsSL https://raw.githubusercontent.com/cirwel/unitares/master/PUBLISHED_VERSION) && git clone --branch "v$v" --depth 1 https://github.com/cirwel/unitares.git && cd unitares && docker compose up -d --wait
  • Endpoints and updates: connect MCP clients at http://localhost:8767/mcp/, or open the dashboard at http://localhost:8767/dashboard (Docker quickstart). On Docker, ./scripts/unitares update backs up the database, applies migrations, and verifies deep health (updating).

  • One stack per machine: Docker and Homebrew keep separate data (installation choices). Container names are fixed, so run docker compose down (without -v) in an earlier checkout before starting another (stop is not enough, because stopped containers still hold their fixed container_name values, and restart: unless-stopped revives un-stopped containers when the Docker daemon restarts), or use the managed launcher (scripts/install/launch.sh), which checks ownership first.

Connect your agents and models (Integrating agents):

  • Claude Code and Codex: unitares-governance-plugin wires MCP, lifecycle hooks, skills, and per-file edit leases (via the stack's lease plane, so concurrent work in the same checkout does not overwrite another agent's file).

  • Hermes Agent and OpenAI-compatible clients: the host adapter.

  • Any other agent, model, or hosted connector: Streamable HTTP MCP (with npx mcp-remote for stdio-only clients, or Bearer / OAuth on a dedicated public listener for hosted connectors like Claude.ai and ChatGPT), the Python SDK (pip install unitares-sdk), or the resident agent runtime.

  • Optional server-side models (choose a model): no model connection is configured by default; the core record runs model-free with no API keys. Run ./scripts/unitares model to connect a local OpenAI-compatible server (Ollama, vLLM, LM Studio, llama.cpp) for consult and in-process review, or add the agent orchestrator for cross-family CLI review.

Who it is for

For an operator running several long-lived AI agents across vendors on infrastructure they control, who wants one queryable record of identities, findings, reviews, and outcomes across the fleet.

UNITARES works alongside Git, issue trackers, handoff notes, scratchpads, evals, and guardrails: those carry code, task state, and runtime checks, while UNITARES keeps the shared record that ties the agents' claims, reviews, and outcomes together. Each agent keeps its own loop and model. Inferred pauses are advisory by default, and the operator decides when hard holds are enforced. Identity, authorization, archive, and coordination boundaries are enforced by the server.

How it fits together

UNITARES is self-hosted accountability infrastructure for operators running multiple AI agents. Its single-operator federation kernel connects independent runtimes to one operator-controlled server over MCP or HTTP, where they share a durable record while keeping their own models, tools, and runtimes. They interoperate with each other over their own transports or A2A; UNITARES is the record behind them, not the transport between them. Together this is an operator-owned accountability layer for coding, research, background, and resident agents. What it adds to an activity log is lineage and supersession: claims and evidence, reviews, and outcomes stay bound to the process that recorded them, and a replaced claim points to its replacement, for review and for reconstruction later.

Storage is PostgreSQL (with Apache AGE for supersession graph links and pgvector for embeddings) and Redis, with no required external model API. The check-in's behavioral state estimate is a form of runtime proprioception; its policy recommendation is retained in the record and is advisory by default, with optional hard-hold enforcement.

Empirical evaluations, operational measurements, and scope are documented in Evidence and limits and the Reviewer Guide.

Start here

Goal

Guide

Try it

Install → two-process walkthrough

Connect an agent or application

MCP integration · Python SDK

Operate a deployment

Operator manual

Understand the product and architecture

Product definition · Architecture

Research behind it

Evidence and limits · Paper · Public dataset

Contribute

Contributing · Development guide

Everything else

Documentation index

Citation and license

Kenny Wang (ORCID 0009-0006-7544-2374), CIRWEL Systems. See CITATION.cff for the versioned citation.

@misc{wang2026unitares,
  author = {Wang, Kenny},
  title  = {{UNITARES}: Information-Theoretic Governance of Heterogeneous Agent Fleets},
  year   = {2026},
  doi    = {10.5281/zenodo.19647159}
}

Apache License 2.0. See LICENSE and NOTICE.

Available Tools

13 tools
check_working_stateA
Read-onlyIdempotent

Read your current governance state and verdict without running a cycle, writing, or minting an identity. Only proof sent with the call reads your state (start_session's client_session_id, an X-Session-ID header or a verified continuity_token), never an inferred binding; otherwise a self-read is unbound and next_action says how to recover. agent_id, dropped on /mcp/, names the agent to read through use_tool or REST unless you are bound as a different agent (identity_mismatch); that read is marked identity_assurance.caller_proven=false on an inferred session. verbosity='standard' adds mode and basin with their meanings under raw_governance; verbosity='full' (alias lite=false) returns the full canonical diagnostics. sync_state also logs work and returns the effective action. get_governance_metrics returns this read's raw payload. With behavioral-sensor inputs, EISV fields: E=Energy [0,1] (observations and prior judgments); I=Information Integrity [0,1] (calibration and consistency features); S=Entropy [0,1] (deviations and activity features); V=Valence [-1,1] (separate EMA of raw E_obs-I_obs; positive=positive smoothed gap, negative=negative smoothed gap). Read primary_eisv_source / measurement_source for the producer; other producers share these field names.

Inputs: lite, verbosity, include_state, continuity_token, +1 more.

consultA

Ask a model or council to critique a design or assumption (no review record; thorough/council is opt-in; on-record: request_review).

Inputs: brief (required), model, effort, host_id, +8 more.

describe_toolA
Read-onlyIdempotent

Return one named tool's description, stability tier, operation, examples, and advertised JSON input schema. Use list_tools(lite=true) for the compact capability-name index or list_tools(lite=false) to browse rich catalog metadata. An unqualified describe call returns the full record because lite=false is the advertised default; pass lite=true for a first-line-plus-key-parameters summary. On a consolidated router, action=... narrows the response to that action's parameters.

Inputs: tool_name (required), lite, action, agent_id, +4 more.

identityA

Resolve which agent this MCP session is bound to, or set a cosmetic display name. Not a plain read: a call carrying no proof argument at all is gated to a fresh mint, so it persists a new agent and reports on that one, marked caller_proven=false. A call carrying only a cosmetic name= — with no session or ownership signal and no explicit session header — is also gated to a fresh mint — pass client_session_id to read or rename your own session. name= persists a cosmetic label only and never looks an agent up. For a fresh process call onboard(force_new=true). continuity_token is per-process ownership proof, not a transport-level claim: carrying it into another process re-opens silent resurrection.

Inputs: name, resume, agent_id, force_new, +4 more.

list_toolsA
Read-onlyIdempotent

Discover the complete governance capability catalog, including names omitted from the initial progressive tools/list advertisement. The default lite=true response is the compact federation handshake: every public capability appears once as a name-only record beside the interface contract. Use lite=false for descriptions, categories, tiers, workflows, relationships, and direct-advertisement status. Use describe_tool for one capability's parameters, then use_tool to invoke a capability absent from the initial listing. Callable before an identity is bound.

Inputs: lite, tier, verbose, agent_id, +6 more.

record_resultA

Record a measurable outcome and pair it with this agent's EISV snapshot so verdicts can be graded against what really happened. Pass the prediction_id from a sync_state reply to bind the outcome to that check-in's confidence; it is consumed on first use and TTL-bound (an hour by default). Needs a bound or explicit agent_id, and refuses under strict identity from an ephemeral session. Provenance cannot be self-attested here: verification_source is forced and provenance keys in detail are stripped. Use store_finding for durable knowledge. outcome_event is the canonical twin; this name adds a digest envelope and keeps the raw payload under raw_governance only with response_mode='full' or include_semantics=true, or when the write returned no outcome_id. EISV field definitions: describe_tool(tool_name='check_working_state').

Inputs: outcome_type (required), detail, is_bad, agent_id, +10 more.

request_reviewA

Open a governed, on-record review. issue_description is the thesis by default; set use_brief_as_thesis=false for two calls. Proxy-filed reviews should pass reviewed_work_author_agent_ids to recuse declared authors. Requires a session-owned registered identity; refuses with SESSION_EXISTS if one is active, and skips without a session while waiting_input. dialectic advances the session; consult is advisory.

Inputs: reason, agent_id, reasoning, root_cause, +6 more.

search_shared_memoryA

Search shared memory (the knowledge graph) before you write; to add a finding use store_finding.

Searches the cross-agent knowledge graph. Archived and cold rows appear only when you set status or include_archived / include_cold, or when a query finds under 3 other rows; resolved and closed ones always do. Each successful search appends a knowledge_read audit row (the reader and a redacted copy of the query), so this tool is not annotated read-only. It serves unbound callers, so it works before start_session, unlike the writes: use store_finding to add a finding and use_tool(tool_name='update_finding', ...) to revise one.

Inputs: tags, limit, query, status, +21 more.

self_recoveryA
Destructive

Lifts a pause or other hold on your own agent. action='check', the default, changes no stored state, and both resuming actions verify you own the agent. Neither resume path runs while a void is active; quick also caps risk at 0.40, review at 0.65 plus a written reflection (20+ characters) on what happened, which is recorded in the shared knowledge graph under your agent whether or not it resumes. An attempt that reaches the safety checks stamps a fresh recovery_attempt_at even when they refuse it, so a retry is not a no-op; a missing reflection is rejected before that stamp. To resume an agent you do not own use operator_resume_agent.

Inputs: action, reason, agent_id, conditions, +3 more.

start_sessionA

Register this process-instance and mint its agent identity; keep the returned client_session_id for later calls. Call with force_new=true — a bare call with no ownership proof is defaulted to force_new or refused under strict identity, never resumed onto another process's uuid. parent_agent_id claims succession from an EXITED predecessor: naming a still-live parent is rejected as coincidental and the claim cleared, unless spawn_reason marks a dispatched child or a compaction continuation. Use identity to inspect or rename an existing binding. onboard is the canonical twin; this name adds a digest envelope. Read the uuid from agent_uuid; response_mode='full' keeps the raw payload under raw_governance.

Inputs: name, resume, agent_id, force_new, +14 more.

store_findingA

Write a durable finding to the knowledge graph; search first, to revise one use update_finding.

Writes one new finding into the cross-agent knowledge graph and returns its discovery_id. summary is required at call time even though the schema marks every field optional; severity high or critical is refused unless the session is bound to a registered agent, while low and medium fall back to an anonymous writer id. Every call mints a NEW discovery — search_shared_memory first, and revise one with use_tool(tool_name='update_finding', ...). Use it for a discovery, root cause or correction, and record_result for task, tool or test outcomes; budget 20 findings an hour.

Inputs: tags, content, details, summary, +10 more.

sync_stateA

Record a check-in: persist EISV, preserve the raw recommendation, and return the effective action. Inferred pauses are observational unless the operator enables actuation. A prediction_id — only when you pass confidence — to grade that check-in later with record_result. The first call auto-binds an identity, except under strict identity, which refuses and points at start_session. simulate_update previews a proposed check-in without advancing state, though it still appends an audit event; check_working_state reads the current verdict without writing. process_agent_update is the canonical twin; this name returns a digest envelope, and a routine check-in omits the raw payload (response_mode='full' adds it under raw_governance). EISV field definitions: describe_tool(tool_name='check_working_state').

Inputs: lite, logprobs, task_type, complexity, +19 more.

use_toolA
Destructive

Invoke one public capability omitted from the initial progressive tools/list advertisement. Find the exact name with list_tools and inspect its arguments with describe_tool, then pass that argument object here. The target's normal identity, validation, authorization, timeout and response middleware all run; this is a discovery gateway, not an authorization bypass. It refuses recursive use_tool calls.

Inputs: tool_name (required), agent_id, arguments, continuity_token, +1 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.2/5.0

    Scored across 13 tools

    Disambiguation3/5

    Most tools have distinct roles, but identity handling is spread across start_session, identity, sync_state, and check_working_state, and consult overlaps conceptually with request_review. The verbose descriptions do help clarify boundaries, but the set still requires careful reading to avoid selecting the wrong identity or state tool.

    Naming Consistency4/5

    Names consistently use snake_case and mostly follow a verb_noun pattern such as search_shared_memory, start_session, record_result, and request_review. A few deviations like identity, consult, and self_recovery are readable but less patterned.

    Tool Count5/5

    Thirteen advertised tools is well within a reasonable range and fits the governance domain, with list_tools/describe_tool/use_tool providing progressive disclosure for the larger catalog. Each advertised tool appears to serve a specific lifecycle or discovery purpose.

    Completeness4/5

    The surface covers identity, check-ins, state reads, outcomes, reviews, recovery, knowledge-graph search/store, and tool discovery, which is strong lifecycle coverage. Minor gaps remain because operations like update_finding and some operator/session controls are reachable only through use_tool rather than direct tools.

    Maintenance

    ActivityActive
    ResponsivenessSyncing

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      A
      quality
      D
      maintenance
      Provides policy-based access control, incident tracking, and compliance monitoring to govern AI agent behavior. It enables organizations to enforce security rules and maintain audit trails by validating agent actions against trust levels and pattern-based policies.
      6
      1
      -
    • A
      license
      A
      quality
      C
      maintenance
      Runtime policy enforcement for AI agents. Evaluate every agent action against your organization's policies before execution, with observe and enforce modes.
      1
      1
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables AI agents to self-govern by scanning code for hardcoded secrets, structural violations, and AI drift in real-time, providing fix packets for automatic remediation.
      29
      MIT