RFC: Composable Peers — Universal Identity Containers for Honcho

Status: Draft Owner: vineeth Last updated: 2026-03-22

1. Problem Statement

Honcho’s peer model is intended to represent arbitrary concepts — people, agents, groups, organizations, projects — but in practice peers are treated as individual interlocutors in conversations. The system’s rigidity manifests in several ways:

  1. Peers are not composable. You can’t express “engineering-team contains alice, bob, charlie” or “alice has a work context and a personal context.” Each peer is an island. There’s no way to segment a peer’s identity or aggregate knowledge across related peers.

  2. Data can only flow into peers through conversations. Sessions → messages → deriver is the only ingestion path. There’s no way to feed a peer arbitrary documents or external data without creating synthetic sessions and injecting fake messages with hacky metacommentary.

  3. No per-peer or per-session extraction guidance. The deriver treats every peer and every session the same way. But extracting personality traits from a person, architectural decisions from a project, and policy compliance from an organization are fundamentally different tasks.

  4. The reasoning chain is immutable. Messages can’t be deleted, peers can’t be renamed, conclusions can’t be corrected without potentially invalidating the entire DAG of derived knowledge above them.

  5. No developer-extensible reasoning. The dreamer runs fixed consolidation logic. Developers can’t define custom reasoning tasks like “maintain a weekly engagement summary” or “auto-segment this peer’s identity facets.”

  6. Files aren’t native. There’s no clean place to store peer cards, dream outputs, reference knowledge, or agent memory files. These get stuffed into internal_metadata or faked as messages.

Competitive Context

This RFC was informed by analysis of how Endearing (an AI companion product) uses Supermemory for memory. Key observations:

  • Supermemory uses arbitrary container tags (e.g., user_123, groupchat_456, user_123-chat_789) that are created implicitly and carry per-container extraction guidance (“entity context”).
  • Containers are isolated by default. Cross-container search requires explicit fan-out.
  • There’s no enforced relationship model. Containers are flat and semantically meaningless to the system — all meaning lives in the entity context and naming conventions.

Supermemory’s flexibility comes at the cost of having no cognitive layer — it stores and retrieves but doesn’t reason, model perspectives, or build theory of mind. Honcho’s advantage is its reasoning pipeline (deriver, dreamer, dialectic). The goal is to achieve Supermemory’s flexibility while preserving and extending Honcho’s cognitive differentiation.

2. Goals

  1. Make peers composable through a sub-peer model — any peer can have sub-peers, any peer can belong to multiple parent peers, and knowledge aggregates upward naturally.
  2. Add custom instructions / extraction context at the peer, session, and message levels so the deriver can tailor its reasoning. (Note: this work is already in progress separately.)
  3. Introduce peer-scoped markdown files for storing peer cards, dream outputs, reference knowledge, and agent memory.
  4. Enable restructuring operations (rename, merge, split) with managed invalidation of the reasoning chain.
  5. Extend the dreamer to support developer-defined materialized dreams — scheduled reasoning tasks that produce and maintain living documents.
  6. Add session-level filtering to dialectic and conclusion queries for fine-grained isolation.

3. Non-Goals

  1. Storing binary files (PDFs, images, etc.). Peer files are markdown/text only. External content continues to be converted to messages for ingestion.
  2. Turning Honcho into a general-purpose vector database. The value is in reasoning, not just retrieval.
  3. Breaking backward compatibility. Existing peers continue to work exactly as they do today — sub-peers are purely additive.
  4. Introducing a new entity type. Sub-peers are just peers. The peer_memberships table is the only new concept.

4. Design

4.1 Sub-peers: Hierarchical Peer Composition

The core idea: a peer can have sub-peers, and a peer can belong to multiple parent peers. Sub-peers are not a new type — they are regular peers with a membership relationship. Every peer can function independently: participate in sessions, have conclusions, have files, be queried directly.

Knowledge aggregation is directional:

  • Query a parent peer → sees the parent’s own knowledge + all sub-peers’ knowledge (aggregation)
  • Query a sub-peer → sees only that sub-peer’s knowledge (isolation)

This naturally provides both composition and isolation without scope tags, permissions, or special filtering. Think of it like a file system:

alice/                          ← query here: sees everything
├── alice-dm/                   ← query here: only DM knowledge
│   └── sessions, conclusions
├── alice-groupchat-standup/    ← query here: only group chat knowledge
│   └── sessions, conclusions
├── alice-gmail/                ← query here: only gmail knowledge
│   └── sessions, conclusions
├── sessions                    ← alice's own direct sessions
├── conclusions                 ← alice's own top-level conclusions
└── files/
    ├── card.md
    └── profile.md

alice.message("hello") stores at the alice level. alice_dm.message("hello") stores at the sub-peer level. Both are valid. The parent peer is just a peer that happens to have members.

Schema:

CREATE TABLE peer_memberships (
    id TEXT PRIMARY KEY,
    workspace_name TEXT NOT NULL,
    parent_peer TEXT NOT NULL,
    child_peer TEXT NOT NULL,
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMPTZ DEFAULT now(),
    UNIQUE (workspace_name, parent_peer, child_peer),
    FOREIGN KEY (parent_peer, workspace_name) REFERENCES peers(name, workspace_name),
    FOREIGN KEY (child_peer, workspace_name) REFERENCES peers(name, workspace_name)
);

API surface:

POST   /v3/workspaces/{id}/peers/{parent_peer}/members           -- add a sub-peer
GET    /v3/workspaces/{id}/peers/{parent_peer}/members           -- list sub-peers
DELETE /v3/workspaces/{id}/peers/{parent_peer}/members/{child}   -- remove a sub-peer
GET    /v3/workspaces/{id}/peers/{peer_id}/parents               -- list parent peers

Aggregation behavior:

When querying a peer’s representation, conclusions, or via the dialectic:

  • The query includes the peer’s own knowledge
  • Plus all immediate sub-peers’ knowledge (depth 1 by default)
  • Configurable via depth parameter: 0 = self only, 1 = self + immediate children (default), 2 = two levels, all = full tree
  • Cycle detection enforced at membership creation time (adding A as child of B fails if B is already a descendant of A)

Many-to-many membership:

A peer can belong to multiple parents. Alice can be a sub-peer of both engineering-team and project-alpha. Her knowledge aggregates upward to both. This is the same peer — not a copy.

Interaction with the existing observer/observed model:

The collection model (observer/observed) is unchanged. Collections store conclusions at the individual peer level. Sub-peer aggregation happens at query time, not storage time. The deriver continues to write conclusions to the specific peer that owns the session/messages — aggregation to parent peers is a read-time concern.

4.2 Custom Instructions (Context Fields)

Note: this work is already in progress separately. Included here for completeness and to show how it integrates with sub-peers.

Peers, sessions, and messages each gain a freeform context / custom_instructions field that the deriver incorporates into its extraction prompt:

  • Peer-level: what kind of entity, what to focus on
  • Session-level: what this session represents, how to interpret its contents
  • Message-level: what this specific content is, who authored it

The deriver constructs its prompt from the full hierarchy. This replaces the hacky metacommentary pattern — instead of faking a message from Alice, you provide real content with context that explains its provenance.

4.3 Peer Files (Markdown)

Peers gain a lightweight file storage layer for markdown/text content:

CREATE TABLE peer_files (
    id TEXT PRIMARY KEY,
    workspace_name TEXT NOT NULL,
    peer_name TEXT NOT NULL,
    path TEXT NOT NULL,
    content TEXT NOT NULL,
    managed_by TEXT,                -- null = user-created, 'system' = honcho-managed, 'dream:{name}' = dream output
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMPTZ DEFAULT now(),
    updated_at TIMESTAMPTZ DEFAULT now(),
    UNIQUE (workspace_name, peer_name, path)
);

What files are for:

  • Peer cards: move from internal_metadata to /card.md — readable and editable via API
  • Summaries: session summaries as inspectable files
  • Dream outputs: materialized dreams write their results to files
  • Reference knowledge: skills, org policies, agent instructions, style guides
  • Agent memory: Claude Code-style .md files that agents read/write

What files are NOT for:

  • Binary file storage (PDFs, images). These get converted to messages.
  • Replacing the conclusion/collection model. Files are supplementary storage, not the reasoning substrate.

API surface:

POST   /v3/workspaces/{id}/peers/{peer_id}/files           -- create a file
GET    /v3/workspaces/{id}/peers/{peer_id}/files            -- list files
GET    /v3/workspaces/{id}/peers/{peer_id}/files/{path}     -- read a file
PUT    /v3/workspaces/{id}/peers/{peer_id}/files/{path}     -- update a file
DELETE /v3/workspaces/{id}/peers/{peer_id}/files/{path}     -- delete a file

Enrichment: Files can optionally be chunked and embedded for semantic search. The dialectic gains a search_files(peer_id, query) tool. Files are NOT automatically processed by the deriver — they’re reference material, not conversation. If a developer wants a file’s content to produce conclusions, they ingest it as messages in a session.

Aggregation with sub-peers: When searching files on a parent peer, sub-peers’ files are included (respecting the same depth parameter as conclusion queries).

4.4 Reasoning Chain Invalidation

To enable restructuring operations (rename, merge, delete, correct), the system needs managed invalidation of derived knowledge.

Approach: Tombstone + staleness propagation with dreamer reconciliation.

  1. Staleness flag. Conclusions gain a stale boolean and stale_reason text field.
  2. Source tracking. Conclusions already have source_ids (JSONB array of premise document IDs). When a source is tombstoned or marked stale, downstream conclusions referencing it are also marked stale.
  3. Dreamer reconciliation. The dreamer gains a new task type: reconcile_stale. It re-evaluates stale conclusions against current evidence and either confirms, updates, or tombstones them.
  4. Bounded propagation. Staleness propagates through the source_ids DAG but is bounded — semantically independent downstream conclusions can be unmarked without re-derivation.

Restructuring operations:

OperationMechanism
Delete messageTombstone message; mark directly-derived conclusions stale; dreamer reconciles
Rename peerCreate new peer; migrate conclusions, memberships, files; tombstone old peer
Merge peersCreate target peer; migrate data from sources; dreamer resolves duplicates; tombstone sources
Split peerCreate sub-peers; move conclusions by criteria; mark affected derived conclusions stale
Correct conclusionUpdate content; mark downstream conclusions stale; dreamer reconciles

Open concern: Data flowing in while old data hasn’t been reconciled. New conclusions could be derived from stale premises. Mitigation: the deriver should skip stale conclusions as premises, and the dreamer should prioritize reconciliation over new dream tasks.

4.5 Materialized Dreams

The dreamer gains the ability to run developer-defined reasoning tasks that produce and maintain living outputs.

Schema:

CREATE TABLE dream_definitions (
    id TEXT PRIMARY KEY,
    workspace_name TEXT NOT NULL,
    name TEXT NOT NULL,
    peer_name TEXT,
    prompt TEXT NOT NULL,
    sources JSONB NOT NULL,
    output_type TEXT NOT NULL,        -- 'conclusions', 'file'
    output_path TEXT,                 -- file path if output_type = 'file'
    trigger_type TEXT NOT NULL,       -- 'cron', 'on_change', 'on_demand'
    cron_expression TEXT,
    debounce_seconds INTEGER DEFAULT 300,  -- min time between on_change triggers
    enabled BOOLEAN DEFAULT true,
    last_run_at TIMESTAMPTZ,
    next_run_at TIMESTAMPTZ,
    run_count INTEGER DEFAULT 0,
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMPTZ DEFAULT now(),
    UNIQUE (workspace_name, name)
);

API surface:

POST   /v3/workspaces/{id}/dreams                    -- create
GET    /v3/workspaces/{id}/dreams                    -- list
GET    /v3/workspaces/{id}/dreams/{dream_id}         -- get definition + last output
PATCH  /v3/workspaces/{id}/dreams/{dream_id}         -- update
DELETE /v3/workspaces/{id}/dreams/{dream_id}         -- delete
POST   /v3/workspaces/{id}/dreams/{dream_id}/trigger -- manually trigger

Output types:

  • conclusions: Dream produces conclusions stored in the target peer’s collection.
  • file: Dream produces a markdown document written to a peer file at output_path. The file’s managed_by is set to dream:{name}.

Trigger system:

  • cron: Scheduler checks periodically, enqueues due dreams.
  • on_change: Fires when new conclusions are added to source peers. Debounced by debounce_seconds to prevent rapid re-runs during batch ingestion.
  • on_demand: Only via explicit API trigger.

Built-in system dream — identity segmentation:

Honcho runs an automatic dream for every peer that discovers natural facets of their identity (professional, personal, interests, relationships, current-state, etc.). Conclusions are tagged with discovered facets via a facets field. This is a differentiator from Supermemory’s static developer-assigned categories.

4.6 Session-Level Filtering

The dialectic and conclusion query endpoints gain session-level filtering for fine-grained isolation within a peer:

# Only see conclusions derived from specific sessions
honcho.peers.get_representation(
    peer_id="alice",
    session_ids=["session-123", "session-456"]
)
 
# Exclude conclusions from specific sessions
honcho.peers.get_representation(
    peer_id="alice",
    exclude_session_ids=["private-session-789"]
)

This composes with sub-peers:

  • Sub-peers = coarse isolation (work vs home, DM vs group chat)
  • Session filter = fine isolation (this specific conversation)
  • Metadata filter = arbitrary isolation (existing capability)

For derived conclusions (deductive, inductive) that have no direct session: filter on the direct session_name field. Derived conclusions with null session are general knowledge — included by default, excludable via a exclude_derived: true flag.

4.7 Dialectic Enhancement

The dialectic agent gains new tools:

  • list_sub_peers(peer_id) — discover sub-peers
  • list_parent_peers(peer_id) — discover parent peers
  • search_files(peer_id, query, top_k) — semantic search across a peer’s files
  • get_materialized_dream(peer_id, dream_name) — read a dream output
  • get_identity_facets(peer_id) — list discovered identity facets
  • get_representation_by_facet(peer_id, facet) — scoped representation

The existing tools (search_memory, get_representation, get_peer_card) continue to work. When called on a parent peer, they automatically include sub-peer knowledge (respecting depth).

5. Mapping: Endearing’s Supermemory Architecture

Supermemory PatternComposable Peers Equivalent
user_{id} containerParent peer alice — query here for full knowledge
groupchat_{chatId} containerSub-peer alice-groupchat-123 — query here for group-only knowledge
user_{id}-chat_{chatId} (force-scoped)Sub-peer alice-chat-456 or session filter on parent peer
Entity context per containerextraction_context / custom instructions per peer
Filter prompt (org-wide)Workspace-level configuration (existing)
client.profile() (core + dynamic)Representation on parent peer + materialized dream
Personalization agents (Gmail/LinkedIn)Sub-peer alice-gmail with ingestion sessions
Memory categories (personal/professional)Automatic identity segmentation (discovered facets)
Fan-out search across containersQuery parent peer (aggregates sub-peers automatically)
Container isolationQuery specific sub-peer (only that sub-peer’s knowledge)
Container mergingPeer merge operation with dreamer reconciliation
Conversation compactionSession summaries (existing)

6. Schema Changes Summary

Modified tables:

-- peers: add extraction context (custom instructions work may handle this separately)
ALTER TABLE peers ADD COLUMN extraction_context TEXT;
 
-- sessions: add context field
ALTER TABLE sessions ADD COLUMN context TEXT;
 
-- messages: add context field
ALTER TABLE messages ADD COLUMN context TEXT;
 
-- documents (conclusions): add staleness tracking and facets
ALTER TABLE documents ADD COLUMN stale BOOLEAN DEFAULT false;
ALTER TABLE documents ADD COLUMN stale_reason TEXT;
ALTER TABLE documents ADD COLUMN facets JSONB DEFAULT '[]';

New tables:

-- peer_memberships: sub-peer composition
CREATE TABLE peer_memberships (
    id TEXT PRIMARY KEY,
    workspace_name TEXT NOT NULL,
    parent_peer TEXT NOT NULL,
    child_peer TEXT NOT NULL,
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMPTZ DEFAULT now(),
    UNIQUE (workspace_name, parent_peer, child_peer),
    FOREIGN KEY (parent_peer, workspace_name) REFERENCES peers(name, workspace_name),
    FOREIGN KEY (child_peer, workspace_name) REFERENCES peers(name, workspace_name)
);
 
-- peer_files: markdown file storage
CREATE TABLE peer_files (
    id TEXT PRIMARY KEY,
    workspace_name TEXT NOT NULL,
    peer_name TEXT NOT NULL,
    path TEXT NOT NULL,
    content TEXT NOT NULL,
    managed_by TEXT,
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMPTZ DEFAULT now(),
    updated_at TIMESTAMPTZ DEFAULT now(),
    UNIQUE (workspace_name, peer_name, path)
);
 
-- dream_definitions: materialized dreams
CREATE TABLE dream_definitions (
    id TEXT PRIMARY KEY,
    workspace_name TEXT NOT NULL,
    name TEXT NOT NULL,
    peer_name TEXT,
    prompt TEXT NOT NULL,
    sources JSONB NOT NULL,
    output_type TEXT NOT NULL,
    output_path TEXT,
    trigger_type TEXT NOT NULL,
    cron_expression TEXT,
    debounce_seconds INTEGER DEFAULT 300,
    enabled BOOLEAN DEFAULT true,
    last_run_at TIMESTAMPTZ,
    next_run_at TIMESTAMPTZ,
    run_count INTEGER DEFAULT 0,
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMPTZ DEFAULT now(),
    UNIQUE (workspace_name, name)
);

7. Implementation Phases

Phase 1: Custom Instructions + Peer Enhancements

  • Add extraction_context to peers (may be handled by parallel custom instructions work)
  • Add context to sessions and messages
  • Deriver reads and incorporates context hierarchy
  • Validates: does context-aware extraction meaningfully improve quality?

Phase 2: Sub-peers

  • Implement peer_memberships table and CRUD endpoints
  • Aggregation logic in representation, conclusion queries, and search
  • Cycle detection at insertion time
  • Configurable aggregation depth
  • Validates: does sub-peer composition cover the target modeling scenarios?

Phase 3: Peer Files

  • Implement peer_files table and CRUD endpoints
  • Migrate peer cards and summaries from internal_metadata to files
  • File chunking and embedding for search
  • Dialectic search_files tool
  • Validates: is the file interface useful for developers and for system-managed outputs?

Phase 4: Invalidation & Restructuring

  • Staleness propagation on conclusion DAG
  • Dreamer reconcile_stale task type
  • Peer rename, merge, split operations
  • Validates: can the system recover coherent state after restructuring?

Phase 5: Materialized Dreams

  • dream_definitions table and CRUD API
  • Dreamer task types: materialize_conclusions, materialize_file
  • Trigger system: cron scheduler, on_change hooks with debouncing, on_demand
  • Built-in identity segmentation dream
  • Validates: can developers define useful custom reasoning tasks?

8. Open Questions

  1. Aggregation depth default. Should the default be 1 (immediate children) or 0 (self only, opt-in aggregation)? Default 1 is more useful but could surprise developers with unexpected data inclusion.

  2. Collection model interaction. Collections use (observer, observed, workspace). When querying a parent peer’s representation, should we query all collections where the observed is any sub-peer? Or create aggregate collections? Query-time fan-out is simpler but potentially slower.

  3. Dream cost control. Developer-defined dreams run LLM calls. Per-workspace quotas? Max runs per day?

  4. Staleness during active ingestion. New conclusions could be derived from stale premises while reconciliation is pending. Should the deriver check for stale premises and skip them?

  5. File embedding and search. Should peer files be automatically embedded for semantic search, or opt-in? Auto-embedding is convenient but adds cost.

  6. Facet stability. Auto-segmentation could produce different facet names on each run. Should the dreamer reference previous facets to ensure consistency?

  7. Multi-parent knowledge exposure. When a peer belongs to multiple parents, its knowledge aggregates to all parents. This is usually desired but could leak context across boundaries. Developers need to understand this implication.

  8. Context field length limits. How long can custom instructions be? Must fit in the deriver’s prompt budget alongside actual content.

9. Success Criteria

  1. A developer can model people, teams, brands, codebases, documents, and multi-agent systems using composable peers with sub-peers (see Appendix A).
  2. Querying a parent peer aggregates knowledge from sub-peers. Querying a sub-peer provides isolation. Both work without special configuration.
  3. A developer can ingest external data via sessions with context, and the deriver produces meaningfully different extractions based on that context.
  4. Peer cards, dream outputs, and reference knowledge are stored as inspectable, editable markdown files.
  5. A developer can define materialized dreams with cron, on_change, or on_demand triggers.
  6. Peers can be renamed, merged, and split with the system recovering coherent state.
  7. Existing API consumers experience no breaking changes.

Appendix A: Modeling Scenarios

A.1 People

Alice uses an AI companion across DMs and group chats. The application needs DM knowledge isolated from group chat knowledge, but wants the full picture when queried at the top level.

alice/                              ← query here: full picture of alice
├── alice-fae-dm/                   ← query here: only DM knowledge
│   └── sessions, conclusions
├── alice-groupchat-standup/        ← query here: only group chat knowledge
│   └── sessions, conclusions
├── alice-gmail/                    ← query here: only gmail knowledge
│   └── sessions (ingestion), conclusions
├── sessions                        ← alice's own direct sessions
├── conclusions                     ← top-level, cross-cutting knowledge
└── files/
    ├── card.md                     ← peer card (system-managed)
    └── profile.md                  ← materialized dream output
  • DM agent queries alice → sees everything
  • Group chat agent queries alice-groupchat-standup → only group context, isolated from DMs
  • Personalization system writes to alice-gmail via ingestion sessions with context
  • Dreamer consolidates across all sub-peers into top-level conclusions on alice

A.2 Teams

Engineering team of 5. Want collective knowledge + access to individual knowledge.

engineering-team/
├── alice/          ← same alice peer from above (many-to-many membership)
├── bob/
├── charlie/
├── sessions        ← team-level sessions (standups, planning)
├── conclusions     ← team-level decisions ("we chose Rust for the rewrite")
└── files/
    └── team-norms.md
  • Query engineering-team → team conclusions + alice’s + bob’s + charlie’s knowledge
  • Query alice directly → alice’s knowledge only (does NOT include team-level conclusions — aggregation flows up, not down)
  • Team standup sessions belong to engineering-team peer, deriver attributes conclusions there

Design decision: aggregation depth. When querying engineering-team, do we recurse into alice’s sub-peers (alice-dm, alice-gmail, etc.)? With depth=1, we see alice’s top-level knowledge but not her sub-peer details. With depth=all, we see everything. Default depth=1 is likely correct — the team sees what alice has made available at her top level, not her private sub-contexts.

A.3 A Brand

Modeling a company’s brand identity — voice, values, audience, competitive landscape.

acme-brand/
├── acme-voice/                 ← tone, style, do's and don'ts
│   └── sessions (ingestion of style guides), conclusions
├── acme-audience/              ← target demographics, research
│   └── sessions, conclusions
├── acme-competitors/           ← competitive intelligence
│   └── sessions, conclusions
├── conclusions                 ← top-level brand facts
└── files/
    ├── card.md                 ← brand summary
    ├── style-guide.md          ← reference doc
    └── dreams/
        └── competitive-brief.md    ← materialized dream
  • Brand assistant queries acme-brand → full brand knowledge
  • Content writer queries acme-voice → just tone/style
  • Custom instructions on acme-brand: “This peer represents a brand. Focus on voice, positioning, audience fit, and competitive differentiation.”
  • Materialized dream: “Weekly competitive brief from acme-competitors conclusions”

A.4 A Codebase

AI coding assistant that understands a project.

my-project/
├── my-project-architecture/       ← design decisions
│   └── sessions (ingestion of design docs), conclusions
├── my-project-api/                ← API contracts, endpoints
│   └── sessions (ingestion of specs), conclusions
├── my-project-bugs/               ← known issues, past incidents
│   └── sessions (issue tracker data), conclusions
├── my-project-conventions/        ← coding standards
│   └── sessions, conclusions
├── conclusions                    ← cross-cutting project knowledge
└── files/
    ├── card.md
    ├── CLAUDE.md                  ← agent instructions (reference file)
    └── dreams/
        └── architecture-overview.md
  • Coding agent queries my-project → full project context
  • Code review agent queries my-project-conventions → just patterns
  • Custom instructions: “This peer represents a software project. Extract: architectural decisions, API contracts, conventions, known issues.”
  • Materialized dream: “Maintain architecture overview from design decision conclusions”

A.5 A Document / A Person’s Writings

Modeling a person based on their published writing. Two approaches:

Option A — sub-peer per document:

author-jane/
├── jane-paper-on-llms/
├── jane-blog-post-march/
├── jane-book-chapter-3/
├── conclusions           ← cross-document knowledge
└── files/
    └── dreams/
        └── writing-style-analysis.md

Each document is a sub-peer with its own conclusions. Granular isolation per document. Works well for a small number of important documents.

Option B — sub-peer for the category (recommended for most cases):

jane/
├── jane-writings/
│   └── sessions (one per document), conclusions
├── jane-conversations/
│   └── sessions, conclusions
├── conclusions

Fewer peers. Session filtering within jane-writings provides per-document scoping. Better for prolific authors.

Principle: sub-peers for meaningfully different contexts or identity facets. Sessions for different instances within a context. Don’t create a sub-peer where a session would suffice.

A.6 An Autonomous Agent

An agent that acts independently, calls tools, learns from its own experience.

research-agent/
├── research-agent-web/            ← knowledge from web browsing
│   └── sessions (per research task), conclusions
├── research-agent-tools/          ← tool usage patterns
│   └── sessions, conclusions
├── research-agent-tasks/          ← past task outcomes
│   └── sessions (one per task), conclusions
├── sessions                       ← direct conversations with humans
├── conclusions                    ← agent self-knowledge
└── files/
    ├── card.md                    ← agent capabilities
    ├── skills.md                  ← reference: known skills
    └── dreams/
        └── tool-effectiveness.md  ← materialized: which tools work for what
  • Agent queries itself → full self-knowledge
  • Supervisor queries research-agent-tasks → task history only
  • Custom instructions: “This peer represents an autonomous research agent. Extract: task outcomes, tool effectiveness, failure modes, learned strategies.”
  • Tool calls are ingested as messages with context: “Agent called search API, returned 5 results about X”

A.7 Multi-Agent Orchestration

Coordinator agent with sub-agents working on a shared project.

project-alpha/                              ← the project
├── researcher-for-alpha/                   ← research agent's work on THIS project
│   └── sessions (research tasks), conclusions
├── writer-for-alpha/                       ← writer's work on THIS project
│   └── sessions (writing tasks), conclusions
├── reviewer-for-alpha/                     ← reviewer's work on THIS project
│   └── sessions (reviews), conclusions
├── sessions                                ← project-level (planning, handoffs)
├── conclusions                             ← project-level decisions
└── files/
    ├── brief.md                            ← project brief (reference)
    └── dreams/
        └── progress-report.md              ← materialized: current status
  • Coordinator queries project-alpha → sees all agents’ work + project context
  • Researcher queries its own sub-peer → only its own research
  • Materialized dream: “Progress report across all sub-agents”

Important pattern: Agents that work across multiple projects need project-scoped sub-peers (researcher-for-alpha, researcher-for-beta), not a single researcher peer added to multiple projects. Otherwise the researcher’s project-alpha knowledge would leak to project-beta through parent aggregation.

If the researcher also needs persistent cross-project self-knowledge (tool preferences, learned strategies), it has its own independent peer:

researcher/                     ← the agent's own identity
├── sessions, conclusions       ← cross-project self-knowledge
└── files/
    └── skills.md

project-alpha/
├── researcher-for-alpha/       ← project-scoped work (separate peer)

project-beta/
├── researcher-for-beta/        ← project-scoped work (separate peer)

The researcher agent queries both its own peer and its project-scoped sub-peer when working on a task. The project owner only sees the project-scoped sub-peer.