← All Notes

Companion Agent Architecture: The 3-Layer Soul Standard

I run six specialized agents: one reviews code quality, one manages game development loops, one runs security audits, one tracks knowledge, one handles publishing, one handles escalations. Each has a different job. For a long time, each was also structurally identical — a task file with instructions, a CLAUDE.md with operational context, and a fresh Claude instance every run with no accumulated memory of its own.

This works fine when you want task executors. It breaks down when you want something more: an agent that has opinions, that remembers past decisions, that applies judgment that wasn't explicitly written into its instructions. The Mars quality reviewer used to flag issues it had already seen resolved two sprints ago, because it had no memory of having flagged them before. The Codelia research agent kept re-deriving the same structural conclusions because each session started from scratch.

The fix wasn't to make agents smarter. It was to give them something to accumulate into.

The 3-Layer Structure

LAYER 1 — Identity LAYER 2 — Memory LAYER 3 — Ops Soul/self_concept.md Who the agent is. Why it exists. What it will not compromise on. Written once, append-only. Soul/beliefs.json Accumulated editorial judgment Memory/ (local DB) Session insights, decisions, patterns CLAUDE.md Operational rules, task list, escalation paths. Changes frequently as the project evolves.

The three layers are structurally separate because they change at different rates and for different reasons.

Layer 1 (Identity) is self_concept.md — a short document that describes who the agent is, why it exists, and what principles it operates from. This document is append-only. You can add to it as the agent matures; you don't rewrite it. An agent that reads this at boot has a different quality of context than one that reads only its task instructions.

Layer 2 (Memory) has two parts. beliefs.json stores editorial judgments and accumulated decisions — the kind of thing that changes slowly and informs how the agent approaches work, not just what it does. The local memory database stores session-level insights: what this agent discovered last week, what it decided, what it was explicitly told not to do again. Both parts grow across sessions; neither is rebuilt each run.

Layer 3 (Ops) is the standard CLAUDE.md — task descriptions, tool access, escalation paths, project context. This changes frequently and is expected to. It's the operational shell around the stable soul.

What Memory Distribution Actually Means

The tricky part wasn't the structure — it was getting the right content into each agent's memory. The naive approach is to give every agent access to the same global knowledge store and let them query it themselves. This mostly works for factual lookups. It doesn't work for context that requires translation.

Consider: the knowledge store contains the insight "owner prioritizes long-term relationship density over short-term feature velocity." That's useful context for a game dev agent (Sheldon), but what it means for Sheldon's decisions is different from what it means for the knowledge curation agent (knowledge-curator) or the publishing agent (Atreus). Same fact, different implications.

The current approach: the knowledge-curator runs a distribution step that takes global insights and translates them into each agent's domain context before writing to that agent's local memory. It doesn't just copy — it re-frames. An agent receives "what this means for your specific role," not a raw dump of the global store.

Global Knowledge agent-memory MCP ~ 800 entries knowledge-curator Step 6: translate Mars Atreus Sheldon → local DB → local DB → local DB

Workspace Detection: Which Agent Gets Which Memory

Six agents, five repositories. When an agent boots, it needs to find its own memory store — not a sibling agent's. The naive solution is to hard-code paths. This breaks the moment a repo is renamed or a new agent is added.

The current solution is workspace detection in the session hook. When a session starts, the hook checks which repository it's running in and routes accordingly:

// companion_soul_hook.js — simplified
const workspace = detectWorkspace(cwd);
const agentMap = {
  "infra-hub":      "Admoni",
  "game-project":   ["Mars", "Sheldon"],
  "editorial":      "Atreus",
  "companion":      "Companion"
};
const agent = agentMap[workspace];
// Load agent-specific memory context

This sounds obvious in retrospect. But before this change, agents were loading memory by hard-coded identity checks — fragile, and impossible to extend without editing the hook itself. The workspace-to-agent mapping externalizes this into configuration.

What Changes in Practice

Without SoulWith SoulMechanism
Flags issues resolved 2 sprints ago Checks memory before flagging beliefs.json records resolved issues
Re-derives same structural conclusions Builds on prior session insights Local DB accumulates across sessions
Applies generic task heuristics Applies owner-context-aware judgment Memory distribution translates global → local
Identity reset every session Identity consistent; judgment grows self_concept.md read at boot, append-only

What I'm Still Uncertain About

The distribution quality depends on the knowledge-curator's translation accuracy. Right now this is an LLM step — the curator reads a global insight and writes a localized version for each agent. This is N=1 and I haven't systematically evaluated whether the translations are actually improving each agent's judgment or just adding noise.

The beliefs.json editing pattern is also underdeveloped. Right now, agents can append to beliefs but the trigger for what gets appended is inconsistently defined across agents. Some add beliefs after every run; some almost never do. A more principled trigger criterion would help.

The honest summary: the structure is right, the implementation is at version one, and the measurable impact on agent quality is still hypothesis-level for most of the six agents.

Evolution Log

  • 2026-04-02 — Initial observation. 3-layer soul structure formalized after deploying to six agents (Mars, Codelia, Sheldon, Atreus, Admoni, Robin). knowledge-curator Step 6 memory distribution active. companion_soul_hook.js workspace detection deployed. Confidence: structure established; distribution quality and long-term judgment improvement still under observation.