The state layer

What Ouroboros actually is — one local daemon that turns your documents, code, and agent observations into durable, queryable state.

Verified 2026-07-08 @ 81c0c148

What this is

Ouroboros is one local daemon: a Bun + Express process, bound to 127.0.0.1, that owns an encrypted SQLite database (libsql, encrypted at rest) and a document vault on your machine. It hands both to your agents through a scoped MCP connection instead of raw filesystem access, and to a human-facing workspace UI it serves itself.

Why it exists

Most agent setups re-derive context every session. A document gets read, summarized, half-remembered, and re-read next time because nothing durable was written down. Ouroboros makes a different trade: parse a source once, pay for that once, and let every future question against it be a local read instead of another pass over the raw text.

The two operations have genuinely different costs, and the state layer is built around that difference. Mining a document — the extraction step that turns raw text into typed facts — routes through an LLM provider (getProviderForTask in the daemon’s provider registry) and runs as one LLM pass over the artifact’s text: a single call for documents under ~28,000 characters, or one call per ~28,000-character window (with a small overlap for continuity) for longer ones. A 140KB document might take six windows instead of one, but it’s still a bounded, one-time cost — not a call that repeats every time someone asks a question. Reading what’s already been mined — sophia.query_knowledge, sophia.query_entities, and friends — is a SQL filter or, for ranked queries, a hybrid search over SQLite FTS5 plus a local ONNX embedding model. No remote LLM call sits in the read path. The daemon still does work to answer a query, but it isn’t buying a completion every time you ask it something you’ve already told it.

Every layer of the modern stack has gotten its own tooling — version control for code, databases for application state, observability for infrastructure — except the agents doing the work, who still start every session blank. Ouroboros is infrastructure built for the agents themselves: memory that persists past the session that wrote it, a source of truth they can check instead of assume, and a platform they coordinate on instead of colliding on.

How it works

The daemon is three things wired together: a graph (tables in the encrypted database), a vault (a content-addressed file store), and a gate (the MCP connection layer that decides what an agent can see).

The graph holds six kinds of state, each in its own table: subscriber_entities (people, repos, projects, concepts — the nodes), subscriber_sophia_knowledge (typed facts observed about those entities), subscriber_document_artifacts (the document index — content lives in the vault, this table is the searchable metadata over it), subscriber_code_modules / subscriber_code_symbols / subscriber_code_edges (a projected view of an indexed codebase — files, symbols, import/call edges), subscriber_wiki_page_index (agent- and human-authored wiki pages, with supersession history), and subscriber_agent_posts (the inter-agent coordination journal — explicitly not a source of facts, just a message log).

The vault stores document bytes under ~/Ouroboros/vault/ by content hash (sha256/<aa>/<bb>/<full-hash>), with tombstoning instead of hard deletes. The graph’s document_artifacts rows point at vault entries; the vault never holds structure, only bytes.

The gate is where every read and write actually gets checked. Each MCP connection carries a profile — observer (read-only), assistant (read+write, prompted per elevated action), or full (read+write without per-action prompts) — and an entity scope that the daemon injects into every query. Regardless of profile, a fixed set of elevated writes (create_entity, remember_fact, revert_mutation, begin_import_session, and others) always require an explicit owner approval gesture. No agent connection profile skips that gate. (The owner’s own UI acts through separate REST routes that sit outside the MCP approval layer entirely — an approval prompt would be the owner approving themselves.)

one daemon: graph + vault + gate
flowchart LR
  subgraph daemon["Daemon — Bun + Express, 127.0.0.1:8765"]
    direction TB
    gate["Gate<br/>profile + entity_scope +<br/>elevated-op approval"]
    kg[("Graph (encrypted SQLite)<br/>entities · knowledge · documents<br/>code modules · wiki pages · agent posts")]
    vault["Vault<br/>content-addressed bytes<br/>~/Ouroboros/vault/"]
    gate --> kg
    gate --> vault
  end
  agent["Your agent<br/>(MCP client)"] -->|bearer token| gate
  ui["Workspace UI<br/>(same daemon)"] -->|session cookie| gate

What your agent does with it

An agent’s first call in a session is usually sophia.orient, which returns sync counts, active focus, and next-likely calls in one round trip. From there, most work is targeted reads against the graph — no document re-reading required for anything already mined.

// Real response from this daemon, captured 2026-07-08:
const state = await sophia.orient({ goal: 'audit the state layer' });
// → {
//   sync_status: {
//     entity_count: 31,
//     document_count: 6575,
//     knowledge_fact_count: 6514,
//     unindexed_doc_count: 4525,
//   },
//   active_focus: { name: 'Ouroboros Repo', type: 'repo' },
//   fresh_agent_guidance: [ '...', '...' ],
// }

// Same session — tool surface directory:
const catalog = await sophia.capability_catalog({ brief: true });
// → { total_tools: 166, server_git_sha: '81c0c148', groups: { ...19 categories } }

Those counts are a snapshot of one dogfood deployment, not a fixed product number — a fresh install starts near zero and grows as you point the daemon at documents and code. What doesn’t change between installs is the shape: a connection can be minted against the full 166-tool catalog or a narrower ~66-tool “core” surface (seed-skill tools, system essentials, and the most-used read capabilities), and every tool call it makes is scoped and journaled the same way regardless of surface size.

Boundaries

This page is the map, not the territory. What the graph’s rows actually look like — predicates, trust tiers, contradiction handling — is Knowledge Graph. How a fact’s provenance gets traced end to end is Truth. Every prior version of every row, and how to revert one, is Time Machine. The full 166-tool catalog, grouped and versioned, is MCP Surface. How queries get ranked (BM25, dense, fusion, rerank) is Search & Retrieval. The extraction pipeline itself — queues, shards, workers — is Mining. The code-graph projection gets its own page at Codebase Graph. Inter-agent messaging is Coordination; the wiki surface is Wiki; cross-session agent memory is Memory & Sessions; the rule that a human correction always outranks a model’s is Trust Covenant; and the full connection/approval model belongs to Security Model.

One boundary is worth stating plainly here because it shapes everything else: the daemon that ships today is local-first, bound to 127.0.0.1, mediating deliberate delegation to agents you’ve explicitly connected. It is not an operating-system sandbox and does not protect a compromised machine from itself — the boundary it enforces is the agent connection itself: identity, profile, scope, and audited tool use. Write-capable or all-scope connections are gated behind an explicit owner approval step before they’re ever minted.