# vriōus — Multi-Agent Orchestration & Shared Memory Patterns Canonical patterns for orchestrating coding agents (pi, opencode, claude-code) from Hermes, with shared memory across a distributed, multi-container fleet. ## Architecture Model This is **multi-host, multi-container** — not single-host. Each agent runs in its own container or host: ``` ┌─────────────────────────────────────────────────────────────────┐ │ Hermes (hertz) — orchestrator │ │ fact_store / memory tool / MCP client │ │ Skills: codex, opencode, claude-code, hermes-agent │ └──────┬───────────────────────────┬────────────────────┬──────────┘ │ │ │ ▼ ▼ ▼ ┌──────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ pi agent │ │ opencode │ │ claude-code │ │ (pica) │ │ (orca.fritz.box) │ │ (noether.fritz │ │ Codex CLI │ │ OpenCode CLI │ │ .box) │ │ --print │ │ run / TUI │ │ Claude Code CLI │ │ NPU inference │ │ provider-agnostic│ │ Anthropic Claude │ └──────┬───────┘ └────────┬─────────┘ └────────┬─────────┘ │ │ │ └─────────────────────┼────────────────────────┘ │ ┌────────▼────────┐ │ Stash / MCP │ │ memory server │ │ (memory.fritz │ │ .box:8080/sse) │ │ (boltzmann) │ └─────────────────┘ ``` Each agent is independent — separate host, separate Incus container, separate config. Hermes invokes them via SSH or lmcp: ## Agents | Agent | CLI | Invocation | Transport | Location | MCP Client | MCP Server | |-------|-----|------------|-----------|----------|-----------|------------| | **Hermes** | `hermes` | n/a (orchestrator) | — | hertz | stash, boltzmann, pica | `hermes mcp serve` | | **pi** | `pi --print` | `pi_exec` MCP tool, SSH+nohup | MCP / SSH | pica (Incus) | stash, hertz, boltzmann | `codex mcp-server` (2 tools) | | **opencode** | `opencode run` | SSH / lmcp / direct terminal | SSH / MCP | orca.fritz.box (Incus) | stash (configurable) | `opencode serve` | | **claude-code** | `claude` | SSH / lmcp / direct terminal | SSH / MCP | noether.fritz.box (Incus) | stash (via claude.json) | — | ## Invocation Patterns ### One-Shot (pi) ``` # Via pi_exec MCP tool (preferred — configurable timeout) mcp__pica__pi_exec( prompt="Read /path/to/file and summarize it", model="qwen3.5-9b-npu", provider="hossenfelder" ) # Via SSH (fallback) ssh mfritsche@pica "pi --print --provider hossenfelder --model qwen3.5-9b-npu 'prompt'" ``` ### One-Shot (opencode) ``` # Via SSH on orca ssh mfritsche@orca "opencode run 'Implement retry logic for API calls' --model openrouter/anthropic/claude-sonnet-4" # Or via lmcp on orca curl -s http://orca.fritz.box:8080/mcp -H "Authorization: Bearer " \ -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"shell","arguments":{"command":"opencode run '...'","timeout":120}}}' ``` ### One-Shot (claude-code) ``` # Via SSH on noether ssh mfritsche@noether "claude execute -p 'Refactor the auth module and add tests'" # Or via lmcp on noether curl -s http://noether.fritz.box:8080/mcp -H "Authorization: Bearer " \ -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"shell","arguments":{"command":"claude execute -p '...'","timeout":120}}}' ``` ### Background / Long-Running Tasks ``` # pi: SSH + nohup with lock file, timeout per file # See references/batch-pi-processing.md for full pattern # opencode on orca: SSH background ssh -f mfritsche@orca "opencode run 'Long task' > /tmp/opencode.log 2>&1" # claude-code on noether: SSH background ssh -f mfritsche@noether "claude execute -p 'Long task' > /tmp/claude.log 2>&1" # Or via lmcp with shell_bg on either host curl -s http://orca.fritz.box:8080/mcp -H "Authorization: Bearer ***" \ -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"shell_bg","arguments":{"command":"opencode run '...'","log":"/tmp/opencode-task.log"}}}' ``` ## Codex as MCP Server The official `codex` CLI (v0.143+) can run as an stdio MCP server, exposing pi's coding capabilities as callable tools. Start it on pica: ``` codex mcp-server --config model="o4-mini" ``` Handshake exposes: - Server: `codex-mcp-server` v0.143.0 - Protocol: 2024-11-05 - Capabilities: `tools.listChanged` ### Exposed Tools **`codex`** — Start a session ``` Input: prompt (required), model?, cwd?, sandbox?, approval-policy?, base-instructions?, developer-instructions?, config? Output: { threadId, content } ``` **`codex-reply`** — Continue a conversation ``` Input: threadId (required), prompt (required) Output: { threadId, content } ``` ### Wiring into Hermes Add the stdio server to Hermes's `config.yaml`: ```yaml mcp_servers: codex-pica: command: ssh args: [mfritsche@pica, /home/mfritsche/.local/share/pi-node/current/bin/codex, mcp-server] ``` Then `mcp__codex_pica__codex` and `mcp__codex_pica__codex_reply` appear as native Hermes tools. ### Wiring into opencode In `~/.config/opencode/opencode.jsonc` on orca: ```jsonc "mcp": { "codex": { "type": "local", "command": ["ssh", "mfritsche@pica", "/home/mfritsche/.local/share/pi-node/current/bin/codex", "mcp-server"], "enabled": true } } ``` ### Current pi Setup on pica Two installations coexist: | Version | Binary | MCP Server? | Notes | |---------|--------|-------------|-------| | `@earendil-works/pi-coding-agent` v0.80.3 | `pi` | No (--mode rpc only) | Community fork, NPU inference, MCP *client* | | `@openai/codex` v0.143.0 | `codex` | Yes (`codex mcp-server`) | Official OpenAI CLI, needs API key | pi (community fork) is already configured as an MCP *client* connected to stash, hertz, and boltzmann: ```jsonc // ~/.pi/agent/mcp.json { "mcpServers": { "stash": { "url": "http://192.168.88.184:8080/sse" }, "hertz": { "url": "http://hertz.fritz.box:8080/mcp", "directTools": ["write_file","shell_bg","shell","fetch","web_search"] }, "boltzmann":{ "url": "http://boltzmann.fritz.box:8080/mcp" } } } ``` ## Shared Memory Patterns ### Tier 1: Hermes Holographic Memory (Hermes-only) ``` fact_store(action='add', content='...', category='general') ``` Accessed exclusively by Hermes via `fact_store` and `fact_feedback` tools. Agents report results, Hermes extracts facts and stores them. ### Tier 2: Stash MCP Server (Any MCP-capable agent) ``` Memory server at memory.fritz.box:8080/sse (boltzmann container) - Postgres + pgvector + Ollama - 28 MCP tools - Query via /stash recall --namespaces "/" -- "query" ``` If pi, opencode, or claude-code support MCP client configuration, they can read/write to the same stash namespace directly. Otherwise, all memory flows through Hermes. ### Tier 3: File-Based (Every agent) ``` Shared facts.md — agents append with >>, Hermes reads with read_file ``` Simple, universal. Used in the batch-pi-processing pattern. ## Multi-Host, Multi-Container Design YES — this is designed for separate hosts/containers. Each agent is independently deployed: || Host | IP / FQDN | Container? | Agent | Notes | ||------|-----------|-----------|-------|-------| || hertz | hertz.fritz.box | bare metal | Hermes | Orchestrator, MCP client | || pica | pica.fritz.box | Incus | pi agent | RPi5, RK3588 NPU, qwen3.5-9b-npu | || orca | orca.fritz.box | Incus | opencode | OpenCode CLI | || noether | noether.fritz.box | Incus | claude-code | Claude Code CLI | || boltzmann | boltzmann.fritz.box | Incus | Stash / memory | Postgres, pgvector | **No shared filesystem required.** Communication is via: - **SSH** — primary transport to orca, noether, and pica - **lmcp** — HTTP MCP bridge running on each container (where set up) - **MCP (SSE)** — stash memory server on boltzmann ## Recommendations 1. **New agents go in their own container** — keeps dependencies, configs, and sessions isolated 2. **Stash as shared memory** — structured, queryable, MCP-accessible. Best upgrade path from file-based 3. **Hermes as sole memory curator** — extracts durable facts from agent outputs, stores in fact_store with trust scoring 4. **One-shot for bounded tasks, background TUI for iterative** — match the invocation pattern to the task 5. **AGENTS.md per repo** — project-level context that all agents respect