230 lines
9.2 KiB
Markdown
230 lines
9.2 KiB
Markdown
# 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 <token>" \
|
|
-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 <token>" \
|
|
-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
|