The working path
Build on it.
Four steps: run the server, point a client at it, run the check-in loop, and decide what to do with what comes back. There is no account, no hosted tier, and no outbound call. The install is a Compose file on hardware you control.
The home page says what UNITARES is and How UNITARES fits together shows how it is put together. Here is the part you type. What the instrument has and has not been shown to do is in §05, and in full in the server's evidence ledger.
What you need
- Server
- cirwel/unitares · Apache 2.0 · Docker Compose
- Endpoint
- http://localhost:8767/mcp/ · Streamable HTTP · REST at /v1/tools/call
- Contract
- unitares-sdk · for agents you write yourself
- Runtime
- Python 3.12+ · PostgreSQL with AGE and pgvector · Redis · optional Elixir/OTP coordination
- Suited to
- operators running several long-lived agents on infrastructure they control. Usually not worth the overhead for short-lived chat turns.
§ IRun the server
One compose file, on your own machine.
Self-hosted by design. Identity, telemetry, evidence, and policy history never leave it.
That brings up PostgreSQL with AGE and pgvector, Redis, the lease plane that decides which agent holds a shared surface, and the server on loopback. MCP clients connect at localhost:8767/mcp/, the self-hosted dashboard is at /dashboard, and /health answers for readiness checks.
That is the server README's own command: it clones the latest verified release tag rather than the default branch, which can run ahead of it.
Then watch it move
The second one is the identity guarantee biting rather than being described: governance exchanges each agent's continuity credential for a single-use, request-bound attestation, refuses one agent's attestation when it claims the other's identifier, refuses a captured attestation on replay, and passes the contested surface through an identity-checked handoff before releasing it.
§ IIConnect a client
Client-neutral at the boundary.
Any client that speaks Streamable HTTP MCP can connect. Nothing about the server assumes a model vendor.
The same server answers Codex, Claude Code, Cursor, Goose, Hermes, hosted connectors, and custom hosts. Add it the way that client adds any HTTP MCP server:
{
"mcpServers": {
"unitares": {
"type": "http",
"url": "http://localhost:8767/mcp/"
}
}
}A client without native HTTP support bridges through stdio. Claude Desktop is the usual case:
{
"mcpServers": {
"unitares": {
"command": "npx",
"args": ["mcp-remote", "http://localhost:8767/mcp/"]
}
}
}No agent-name header is configured anywhere. The agent identifies itself in its first call, which is the point: a name in a config file is a label, and a label is not an identity.
Non-MCP callers post to /v1/tools/call instead. For Codex and Claude Code, session lifecycle and hooks are packaged separately as unitares-governance-plugin.
§ IIIRun the loop
Four calls, and a decision that stays yours.
session = start_session(force_new=True)
sid = session["client_session_id"]
result = sync_state(
response_text=output,
complexity=0.6,
confidence=0.8,
client_session_id=sid,
)
if result.get("state_summary", {}).get("action") == "pause":
return_to_operator(result.get("next_action"))
record_result(
outcome_type="test_passed" if tests_passed else "test_failed",
prediction_id=result.get("prediction_id"),
client_session_id=sid,
)
state = check_working_state(client_session_id=sid)-
Identify
start_session
Binds every later write to this process instance. A fresh process mints fresh identity; continuity across a restart is declared, never inferred from a reused display name.
-
Claim
sync_state
Records what the process says it did, and how confident it is. Returns a policy action of proceed, guide, or pause, always with a named reason and a next step.
-
Ground
record_result
Attaches the real outcome to the claim that predicted it, through the check-in's own prediction_id. Without it, the state estimate rests on the agent's own report.
-
Read
check_working_state
Reads the current policy action without writing anything.
Treat the action, the reason, and the next step as the stable contract; the enforcement record rides alongside them. When the server pauses an agent, it refuses that agent's later check-ins until recovery succeeds. Anything the agent does outside the server is the host's to enforce.
The complete tool catalog is callable on every transport. The initial listing is deliberately small: use list_tools to discover names, describe_tool to inspect parameters, and use_tool to call a tool omitted from the initial listing. The checkpoint loop, shared memory, structured review, advisory consultation, and recovery are reachable from the same catalog.
§ IVBuild a long-running agent
The contract is a package, not the server repository.
For an agent that runs for weeks rather than minutes, the SDK handles connection, identity, check-ins, heartbeats, and knowledge participation. Preserve its identity anchor across restarts with identity(agent_uuid=...) rather than minting a new one each run, or its history restarts with it.
A workload registers its own progress source through the unitares.resident_progress_sources entry-point group, with no change to the server's repository at all. That is the whole plug-and-play claim: an adopter never has to touch the server's code.
The lowercase agents in the server repository are reference clients and operational examples. They are built on it and are explicitly not part of it, so read them as worked examples rather than a framework to subclass. cirwel/unitares-resident is the first-party userland on the same public contract; it is an early skeleton, not yet a usable general-purpose agent.
§ VWhat it does not do
A state instrument, not an outcome oracle.
UNITARES does not decide whether an output is correct or ethical, and it cannot detect deliberate concealment without independent evidence. A process capable enough to optimize against a monitored proxy can do so.
No governed-versus-ungoverned comparison has yet shown an incident prevented or an outcome improved. The circuit breaker demonstrably actuates; that it protects anything is untested.
It also replaces nothing you already run:
Evals
between runs
- Is this model good enough for a defined task?
Guardrails
per action
- Is this action allowed, and is it contained?
UNITARES
continuously
- What has this running process been doing, what evidence supports its claims, and what state is it in now?
Open questions, withdrawn results, and pre-registered reads are kept in the evidence ledger, versioned with the code. The research page lists the papers.
- Manual Install, operate, and configure
- Evidence Evidence and limits, in full
- Vocabulary Public glossary
- Contact founder@cirwel.org