unitares

UNITARES enables self-regulating AI agents to monitor and adjust their behavior in real-time.

<picture> <source media="(prefers-color-scheme: dark)" srcset="docs/assets/hero.svg"> <source media="(prefers-color-scheme: light)" srcset="docs/assets/hero.svg"> <img alt="UNITARES — Self-regulating AI agents" src="docs/assets/hero.svg" width="100%"> </picture>

Tests Python 3.12+ License: MIT

Status: live. For architecture details, see docs/UNIFIED_ARCHITECTURE.md and docs/CANONICAL_SOURCES.md.

Most AI agents fly blind: they can't tell when they're thrashing, drifting, or overconfident until a human notices. UNITARES is a runtime layer that lets agents see their own state and regulate themselves — slow down when disorder spikes, ask for review when integrity drops, hand off when they're running on fumes.

Each check-in returns four numbers — EISV: energy, integrity, entropy, valence (the signed energy/integrity imbalance) — plus a verdict, guidance, and calibration. Agents use those numbers to adjust their own behavior before external circuit breakers have to fire. Humans and peer agents read the same state, so one signal serves three consumers: agents regulating themselves, humans watching dashboards, peers coordinating.

Circuit breakers and kill switches are still there — they're just the last line of defense, not the first.

Running continuously in production since November 2025 with 6,200+ passing tests at 77% coverage. Long-run trajectories are stored in PostgreSQL + AGE; the state model is derived from what agents actually do (EMA-smoothed observations, not model predictions).

What it doesGive agents live readings of their own state (EISV) plus a verdict (proceed / guide / pause / reject), so they can regulate themselves — and share the state with humans and peers through the dashboard and knowledge graph.
Workflowonboard()process_agent_update()get_governance_metrics() — details in Getting Started.
TransportsMCP on /mcp/ (Streamable HTTP) · REST on /v1/tools/call · Dashboard on /dashboard
StackPython 3.12+ · PostgreSQL + AGE + pgvector · Redis (optional)

The self-regulation loop

  1. Agent acts — tool call, response, decision.
  2. UNITARES updates state — four numbers that summarize how it's going.
  3. Agent reads its own state back in the check-in response.
  4. Agent applies its own policy — proceed, narrow scope, ask for review, or stop.
# Inside the agent's loop
result = process_agent_update(response_text=output, complexity=0.6, confidence=0.8)

if result["metrics"]["integrity"] < 0.4:
    agent.require_human_review("integrity low — pausing autonomous actions")
elif result["metrics"]["entropy"] > 0.7:
    agent.narrow_scope()            # fewer tools, tighter search
elif result["metrics"]["energy"] < 0.2:
    agent.stop_and_summarize()      # avoid thrashing

The agent reads its own metrics and adjusts before external controls have to fire. Humans see the same state on the dashboard; peer agents read it over the API. UNITARES isn't an output validator (guardrails, evals) or a behavioral sandbox (permissions, container limits) — it's a state layer the agent itself can read.

What makes the signal trustworthy

Self-relative scoring. After ~30 check-ins, the four numbers are graded against your baseline, not a universal threshold. You're flagged when you drift.

Drift from observables, not an ethics oracle. The drift signal comes from calibration accuracy, complexity divergence, coherence, and stability — things the system already measures. No hand-labeled "is this ethical?" classifier.

Trajectory as identity. Long-run EISV patterns answer continuity questions ("still the same agent?") and surface drift no single check-in could see.

Peer review when needed. When an agent's confidence and the system's assessment disagree, UNITARES can run a short adversarial review with peer agents — or with an LLM when no peers are around — before anything halts.


Production snapshot

As of April 2026:

MetricValue
Agents onboarded2,574 total
Unique agents active (last 7 days)2,226 — mostly ephemeral CLI sessions, plus long-running resident agents
Governance events processed94,000+ (≈51K in the last 7 days)
Knowledge graph discoveries578
V operating rangeActive agents often within [-0.1, 0.1]
Tests6,200+ passing · 77% coverage
<p align="center"> <img src="docs/assets/dashboard.png" width="80%" alt="UNITARES dashboard — stats overview with fleet coherence, agent count, discoveries, and system health"/> </p> <details> <summary><strong>More dashboard views</strong> (pulse, EISV charts, agents, dialectic, activity)</summary> <p align="center"> <img src="docs/assets/dashboard-pulse.png" width="80%" alt="Pulse — live event feed and EISV time series"/> </p> <p align="center"><em>Pulse — live event feed, drift indicators, and EISV time series charts</em></p> <p align="center"> <img src="docs/assets/dashboard-agents.png" width="80%" alt="Agents and Discoveries panels"/> </p> <p align="center"><em>Agents (sorted by recency, with trust tiers) and Discoveries (filterable by type and time range)</em></p> <p align="center"> <img src="docs/assets/dashboard-dialectic.png" width="80%" alt="Dialectic sessions — recovery and review history"/> </p> <p align="center"><em>Dialectic sessions — failed, resolved, and active recovery sessions with message counts</em></p> <p align="center"> <img src="docs/assets/dashboard-activity.png" width="80%" alt="Activity timeline — check-ins, verdicts, discoveries"/> </p> <p align="center"><em>Activity timeline — filterable event log across all agents</em></p> </details>

Integrating an agent? Jump to Quick Start.


Quick Start

1. onboard()                    → Get your identity
2. process_agent_update()       → Log your work
3. get_governance_metrics()     → Check your state

Example check-in (non-mirror responses include full metrics, decision, etc.):

process_agent_update({
  "response_text": "Refactored auth module, added rate limiting",
  "complexity": 0.6,
  "confidence": 0.8,
  "task_type": "refactoring",
  "response_mode": "mirror"  // or: minimal, compact, standard, full, auto
})

response_mode: "mirror" shapes the payload for self-awareness: mirror is a list of strings (actionable signals), not a nested object. Optional top-level question and relevant_prior_work surface a targeted nudge and knowledge-graph items when relevant. See _format_mirror in src/mcp_handlers/response_formatter.py.

{
  "verdict": "proceed",
  "_mode": "mirror",
  "mirror": [
    "Fleet calibration: 72% accuracy over 12 fleet-wide decisions (high-conf: 0.8, low-conf: 0.5)",
    "Complexity divergence: you reported 0.60 but system derives 0.45 (divergence=0.15)"
  ],
  "question": "What's driving your sense of difficulty?",
  "relevant_prior_work": [
    { "summary": "Rate limiter bypass in auth …", "by": "agent-abc", "relevance": 0.82 }
  ]
}

Verdict field: Responses expose verdict from decision.action. Governance actions are proceed / guide / pause / reject (Architecture). If action is absent, formatters fall back to continue — see response_formatter.py.

The onboard() response includes agent_uuid — store it and pass it to identity(agent_uuid=..., resume=true) on subsequent connections. See Getting Started for alternative entry paths.

Installation

Prerequisites: Python 3.12+, PostgreSQL 16+ with Apache AGE + pgvector (examples use PostgreSQL 17), Redis optional (session cache only).

Full local server (recommended for MCP + HTTP stack):

git clone https://github.com/CIRWEL/unitares.git
cd unitares
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 8767

Lean dev install (venv, lighter dependency set): use requirements-core.txt and follow CONTRIBUTING.md. Database setup (PostgreSQL 17 + AGE + pgvector): db/postgres/README.md.

The EISV ODE engine ships as the compiled unitares-core package (installed via requirements). See CONTRIBUTING.md for CI and local symlinks.

MCP configuration

Cursor / Claude Code (native type: http):

{
  "mcpServers": {
    "unitares": {
      "type": "http",
      "url": "http://localhost:8767/mcp/"
    }
  }
}

Claude Desktop (via mcp-remote):

{
  "mcpServers": {
    "unitares": {
      "command": "npx",
      "args": ["mcp-remote", "http://localhost:8767/mcp/"]
    }
  }
}

Agents self-identify through onboard(); no hardcoded agent-name header is required.

EndpointTransportUse case
/mcp/Streamable HTTPMCP clients
/v1/tools/callREST POSTCLI, scripts, non-MCP clients
/dashboardHTTPWeb dashboard
/healthHTTPHealth checks

Security: The server binds to 127.0.0.1 by default. For LAN or remote access, set UNITARES_BIND_ALL_INTERFACES=1 and configure UNITARES_MCP_ALLOWED_HOSTS and UNITARES_MCP_ALLOWED_ORIGINS (comma-separated). See scripts/ops/ for an example plist.

For AI agents: Resident agents: save agent_uuid from onboard(), pass it to identity(agent_uuid=..., resume=true). No token management needed. See docs/guides/START_HERE.md and docs/operations/OPERATOR_RUNBOOK.md.


How state works (EISV)

Agents emit text and tool results; they rarely expose a stable notion of internal condition. UNITARES exposes four continuous variables any client can report and any observer can read:

VariableRangeWhat it tracks
E (Energy)[0, 1]Productive capacity
I (Integrity)[0, 1]Information coherence
S (Entropy)[0, 1]Disorder and uncertainty
V (Valence)[-1, 1]Signed energy/integrity imbalance: energetic-but-incoherent (positive) vs coherent-but-depleted (negative)

Behavioral EISV (primary, verdict-driving) — Implemented in src/behavioral_state.py and src/behavioral_assessment.py: EMA-smoothed observations per dimension, no ODE and no universal attractor. After ~30 updates, per-agent Welford baselines enable self-relative scoring (z-score vs your operating point). Earlier check-ins use bootstrap behavior; absolute safety floors still apply.

ODE in governance_core (secondary, diagnostic/fallback) — The same four variables also evolve in a coupled ODE with contraction-style stability analysis. That integration runs in parallel for analysis; governance verdicts normally follow behavioral EISV once behavioral confidence is established, while ODE remains the fallback when behavioral confidence is still insufficient. See Architecture for the full pipeline (drift → entropy, calibration, circuit breaker, dialectic).

<details> <summary><strong>Dynamics (for the curious)</strong> — the coupled ODE behind the fallback path</summary>
dE/dt = α(I - E) - β·E·S           Energy tracks integrity, dragged by entropy
dI/dt = -k·S + β_I·C(V) - γ_I·I   Integrity boosted by coherence, reduced by entropy
dS/dt = -μ·S + λ₁·‖Δη‖² - λ₂·C   Entropy decays, rises with drift, damped by coherence
dV/dt = κ(E - I) - δ·V             Valence accumulates E-I mismatch, decays toward zero
</details>

Architecture

graph LR
    A[AI Agent] -->|check-in| M[MCP Server :8767]
    M -->|observations| BS[Behavioral EISV]
    BS -->|verdict + guidance| M
    M -->|parallel diagnostic| UC[unitares-core ODE]
    UC -.->|analysis only| M
    M -->|verdict + guidance| A
    M <-->|state, audit, calibration| PG[(PostgreSQL + AGE)]
    M <-->|knowledge graph| PG
    M -.->|session cache| R[(Redis)]
    M -->|web UI| D[Dashboard]

    style BS fill:#1a5c1a,stroke:#666,color:#fff
    style UC fill:#2d2d2d,stroke:#666,color:#fff

Use cases: Fleet monitoring and early warning, inter-agent state observation, trajectory-based identity and continuity, outcome-calibrated confidence tracking, dialectic peer review, persistent knowledge graph with staleness awareness.


Documentation

GuidePurpose
Getting StartedSetup, workflows, tool modes
ArchitecturePipeline, verdicts, recovery, storage
Case StudyProject summary and context
TroubleshootingCommon issues
DashboardWeb UI
DatabasePostgreSQL + AGE
ContributingDevelopment setup, testing, style
ChangelogReleases

Paper

UNITARES v6Information-Theoretic Governance of Heterogeneous Agent Fleets. Framework + migration paper (30 pages, latest: paper-v6.8.1). Reframes EISV in Shannon + variational free-energy terms, presents class-conditional calibration as a first-class design constraint, and documents the pipeline-ordering migration mechanism used to re-ground the live system. Headline empirical finding: a 13,310-row verdict counterfactual shows 28.9% of governance basin assignments flip under class-conditional grounded coherence relative to the legacy fleet-wide form, with a strong directional bias into the low basin — direct empirical support for the homogenization-failure-mode argument. Concept DOI: 10.5281/zenodo.19647159 (resolves to latest version; each tagged release has its own version DOI).

Related Projects

Installable client adapters for Codex and Claude live in the companion unitares-governance-plugin repo. This unitares repo is the governance server/runtime; any plugin-side .codex-plugin/, hooks/, skills/, and commands/ content should be treated as belonging to the companion adapter repo, not as canonical copies here.


MIT (server, dashboard, tooling) — see LICENSE. The ODE dynamics engine ships as a compiled dependency (unitares-core); see CONTRIBUTING.md.

Built by @CIRWEL