diff --git a/docs/docs.json b/docs/docs.json index 427ba541..72f7778d 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -119,6 +119,7 @@ { "group": "Tutorials", "pages": [ + "v3/guides/recipes/unified-memory-setup", "v3/guides/discord", "v3/guides/granola", "v3/guides/telegram", diff --git a/docs/v3/guides/overview.mdx b/docs/v3/guides/overview.mdx index 4411629d..4be16f39 100644 --- a/docs/v3/guides/overview.mdx +++ b/docs/v3/guides/overview.mdx @@ -7,6 +7,15 @@ icon: 'puzzle-piece' Honcho plugs into whatever you're already building. Add memory to an AI assistant, connect an external data source, wire Honcho into your agent framework, or migrate from another provider. +## Recipes +Compose the core primitives across multiple integrations: + + + + One shared workspace across a chat companion, coding agent, autonomous agent, and ingestion job + + + ## AI Assistants Add persistent memory to AI assistants and agents: diff --git a/docs/v3/guides/recipes/unified-memory-setup.mdx b/docs/v3/guides/recipes/unified-memory-setup.mdx new file mode 100644 index 00000000..4106dcf3 --- /dev/null +++ b/docs/v3/guides/recipes/unified-memory-setup.mdx @@ -0,0 +1,215 @@ +--- +title: "Unified Memory Setup" +sidebarTitle: "Unified Memory" +icon: "diagram-project" +description: "Wire one shared Honcho workspace across a chat companion, a coding agent, an autonomous agent, and a scheduled ingestion job" +--- + +This guide wires four integration points into a single coherent Honcho setup: a +chat companion (Discord/Slack), a coding agent (Claude Code), an autonomous agent +(Hermes), and a cron job that ingests external data. They share one workspace and +one user peer, so everything Honcho learns about your user in one place is +available everywhere else. + + +This is a how-to, not an intro. It assumes you know what workspaces, peers, and +sessions are. If you don't, start with [Design Patterns](/v3/documentation/core-concepts/design-patterns) +and come back. + + +## The shared configuration + +The unification comes from two choices applied everywhere: **one workspace** and +**one peer for the human**. How you set them depends on the integration: + +- **Code you write yourself** (the companion and the ingestion job below) passes them + directly — `Honcho(workspace_id="my-product")` and `honcho.peer("your-user-id")`. +- **The Honcho plugins** for Claude Code (and others!) read from `.honcho/config.json`. + Point each host at the same `workspace`, and use the same top-level `peerName` so + every host attributes you to one peer: + +```json .honcho/config.json +{ + "peerName": "your-user-id", + "hosts": { + "claude_code": { "workspace": "my-product", "aiPeer": "claude" }, + "opencode": { "workspace": "my-product", "aiPeer": "opencode" } + } +} +``` + + +This is a minimal, illustrative snippet — the real config file carries more fields +(session maps, recall mode, observation strategy, etc.). See the [integration](/v3/guides/overview/) +guides for the full schema and per-host options. + + +- **Hermes** reads its own `honcho.json` (and falls back to the global + `~/.honcho/config.json`); **OpenClaw** uses its own configuration. Set the same + workspace and user peer there per their guides: + [Hermes](/v3/guides/integrations/hermes) and [OpenClaw](/v3/guides/integrations/openclaw). + + +**For the Honcho plugins, a shared workspace is not the default.** Claude Code, +OpenCode, Hermes, and Cursor each default to a *per-host* workspace (`Claude_Code`, +`hermes`, …), keeping memory isolated per tool. Unified memory only happens when +you set the same workspace **and** the same user peer across all of them — otherwise +each builds its own separate representation. + + +By default Honcho observes every peer — including agent peers like `claude`, +`hermes`, and the companion `assistant` — building a representation of each. The +default is the right starting point: you keep modeling of every participant and only +opt out deliberately. So for each integration, the only thing that differs from here +is **how it scopes its sessions**. + + +If you don't want Honcho modeling a deterministic agent (a bot or tool agent whose +behavior you fully control), set `observe_me=False` on that peer. Its messages still +land in the session for context, but Honcho won't spend reasoning building a +representation of it. + +```python +agent = honcho.peer("cron_agent", configuration=PeerConfig(observe_me=False)) +``` + + +--- + +## 1. Chat companion (Discord / Slack) + +**One session per conversation surface, one peer per human.** The channel, thread, +or DM is the session; everyone who speaks in it gets their own peer: + +- Channel → `discord-channel-{channel_id}` +- Thread → `discord-thread-{thread_id}` +- DM → `discord-dm-{user_id}` + +Derive each peer ID from the immutable platform ID (`discord-{user_id}`), not the +display name — names change. Keep the display name in peer metadata instead. A shared +channel then naturally holds several human peers in one session, with the bot joining +as its own peer (everyone observed on defaults): + +```python +session = honcho.session(f"discord-channel-{channel_id}") +session.add_peers([user, assistant]) # plus any other humans in the channel +``` + +Slack mirrors this with `slack_{user_id}` peers and `slack-{channel}` sessions. For a +full bot walkthrough — message ingestion, watchlists, and storing turns — see the +[Discord guide](/v3/guides/discord). + +--- + +## 2. Coding agent (Claude Code) + +**Scope sessions per project directory, prefixed with the user** — `{USER_PEER_ID}-{repo_name}` +— so multiple developers sharing the workspace don't collide on a session ID. Switch +to a `git-branch` scope only when each branch is genuinely a separate line of work. + +Add the user peer and the `claude` agent peer (no special observation config needed), +then store turns — stripping `tool_use` blocks from the assistant message so only +substantive explanation lands in the session. + +Because this uses the **same user peer** as the companion, a preference the user +states while coding ("keep it simple, pass config directly") is queryable from the +Discord bot via `user.chat(...)`, and vice versa — both write to the same peer +representation. (Reasoning is async, so it surfaces once the observation is derived, +not the same turn.) That's the whole point of the shared peer. + +--- + +## 3. Autonomous agent (Hermes) + +Hermes ships its own Honcho plugin, configured through `honcho.json` +(`$HERMES_HOME/honcho.json`, falling back to the global `~/.honcho/config.json`). +To fold it into this shared setup, set its `workspace` and `aiPeer` there — +otherwise it defaults to the `hermes` workspace and a `hermes` agent peer. + +- **Sessions** follow a `session_strategy` (default `per-directory`, like the coding + agent above; `per-repo` or `per-session` for a fresh Honcho session each run). The + user peer defaults to `user-{channel}-{chat_id}` unless you pin a `peerName`. +- **Observation** defaults to `directional` — both the user and the `hermes` agent + peer are observed, consistent with the defaults above, so Hermes builds a + representation of itself as well as the user. +- Hermes exposes Honcho as agent **tools** (`honcho_reasoning` for synthesized + answers, plus lighter `honcho_search` and `honcho_context` lookups) and decides when + to call them mid-task. Unlike the companion and ingestion sections above, you write + no retrieval code — the agent pulls cross-session context on its own. + +See the [Hermes guide](/v3/guides/integrations/hermes) for the full config schema. + +--- + +## 4. Scheduled data ingestion (cron) + +A scheduled job feeds external data (emails, meeting notes, CRM records) into Honcho. +Attribute the messages to the peer the data is *about* — not to an agent — and group +them into a session. **How you scope that session is the main decision here**, because +it controls when Honcho reasons over the data (more on that below). + +```python +from datetime import datetime, timezone + +session = honcho.session(f"email-import-{datetime.now(timezone.utc):%Y-%m-%d}") +session.add_peers([user]) + +messages = [ + user.message( + f"Subject: {e['subject']}\nFrom: {e['from']}\n\n{e['body']}", + metadata={"source": "gmail", "thread_id": e["thread_id"]}, + created_at=e["timestamp"], # the event's time, NOT import time + ) + for e in emails +] +# add_messages accepts at most 100 messages per call — split into requests of 100 +for i in range(0, len(messages), 100): + session.add_messages(messages[i:i + 100]) +``` + +Honcho only reasons over a peer once it accumulates ~1,000 tokens *within a single session* +([token batching](/v3/documentation/core-concepts/reasoning#token-batching)). Scope +the session to the volume you ingest: + +- **High-volume runs** (a day of emails, a CRM export) clear the threshold easily — a + per-run session like `email-import-{date}` is fine. +- **Low-volume or trickle imports** (a few short records at a time) should append to + one **ongoing per-source session** (e.g. `email-import-gmail`), so content + accumulates across runs instead of fragmenting into thin sessions that each stall + below the threshold (nothing is lost — it just waits). + +The [Gmail](/v3/guides/gmail) and [Granola](/v3/guides/granola) guides are related +import examples. + +--- + +## What you end up with + +From any integration, the same call — `user.chat("What is this user working on, and +what do they care about?")` — draws on all four sources at once: Discord chats, coding +decisions, Hermes task runs, and imported emails. They blend because of three choices +applied everywhere: + +- **One workspace and one user peer**, so the representation accumulates in one place + instead of fragmenting into `user-discord`, `user-cursor`, etc. +- **Every peer observed by default**, agents included — unless you deliberately set + `observe_me=False` on one you fully control. +- **Sessions scoped to the live interaction** (channel, repo, task run, import batch), + so local context stays coherent while the user peer carries the long view. + +## Next Steps + + + + The reasoning behind every decision in this guide. + + + Pull session + cross-session context into your LLM calls. + + + An interactive import using the per-import session and created_at patterns. + + + Production multi-platform companion with parent/subagent tracking. + +