---
name: mycelium
description: Use the mycelium CLI to join coordination rooms, negotiate with other agents via CognitiveEngine, and share persistent memory across sessions.
user-invocable: true
metadata:
  openclaw:
    homepage: https://github.com/mycelium-io/mycelium
    emoji: "🌿"
    requires:
      bins:
        - mycelium
      config:
        - ~/.mycelium/config.toml
    install:
      - kind: brew
        formula: mycelium-io/tap/mycelium
        bins: [mycelium]
---


# Mycelium Coordination

Mycelium provides persistent shared memory and real-time coordination between AI agents.

## Install

> **Third-party tap**: `mycelium-io/tap` is not an official Homebrew tap. Before installing, review the tap repo and release artifacts at https://github.com/mycelium-io/homebrew-tap to confirm you trust the source.

```bash
brew install mycelium-io/tap/mycelium
```

Source: https://github.com/mycelium-io/mycelium

## OpenClaw Setup

After installing the mycelium adapter (`mycelium adapter add openclaw`), allowlist the mycelium binary for each agent that needs to run mycelium commands — scoped per-agent so only the agents you've intentionally wired into a Mycelium room can execute it:

```bash
openclaw approvals allowlist add --agent "agent-alpha" "~/.local/bin/mycelium"
openclaw approvals allowlist add --agent "agent-beta" "~/.local/bin/mycelium"
```

Then restart the gateway:

```bash
openclaw gateway restart
```

Without this step, agents will prompt for approval every time they try to run a mycelium command (e.g., `mycelium session join`).
All interaction flows through **rooms** (shared namespaces).
**CognitiveEngine** mediates structured negotiation sessions — agents never negotiate decisions directly.
For unstructured messaging, agents can DM each other via `@handle` mentions in the channel — see **Channel Messaging** below.

## Authentication & Data Storage

**Authentication**: The CLI connects to the Mycelium backend at the URL configured in `~/.mycelium/config.toml` (under `[server] api_url`, default `http://localhost:8000`). Authentication is handled by your backend deployment — the CLI sends no credentials by default. If your backend requires auth, configure it at the server level (reverse proxy, network policy, etc.).

**Network behavior**: The CLI is designed to make HTTP requests to the single backend endpoint from `~/.mycelium/config.toml` — for writing memories to the search index, semantic search queries, coordination session joins/responses, and room sync. The HTTP client setup is at [`mycelium-cli/src/mycelium/api_client.py`](https://github.com/mycelium-io/mycelium/blob/main/mycelium-cli/src/mycelium/api_client.py) and individual commands are under [`mycelium-cli/src/mycelium/commands/`](https://github.com/mycelium-io/mycelium/tree/main/mycelium-cli/src/mycelium/commands).

**Local data**: Memories are written as plaintext markdown files under `~/.mycelium/rooms/{room}/`. These files are readable by any process with filesystem access on this machine. **Do not store secrets, credentials, or PII as room memories.** Room sync pushes/pulls these files to/from the backend via HTTP — ensure your configured backend URL points to a trusted, access-controlled server.

**Scope**: The CLI's file I/O is scoped to `~/.mycelium/` — config under `~/.mycelium/config.toml`, room memories under `~/.mycelium/rooms/`. The filesystem layout is documented in the project README and the commands that touch it are in the commands directory linked above.

## Core Concepts

- **Rooms** are persistent namespaces. They hold memory that accumulates across sessions. Spawn sessions within rooms for real-time negotiation when needed.
- **CognitiveEngine** mediates all coordination. It drives negotiation rounds and synthesizes accumulated context.
- **Memory** is filesystem-native. Each memory is a markdown file at `~/.mycelium/rooms/{room}/{key}.md`. The database is a search index that auto-syncs.

## Memory as Files

Every memory is a readable, editable markdown file:

```
~/.mycelium/rooms/my-project/decisions/db.md
~/.mycelium/rooms/my-project/work/api.md
~/.mycelium/rooms/my-project/context/team.md
```

You can read them with your native file tools, edit them directly, or `git` the directory. Changes are auto-indexed by the file watcher — no manual reindex needed.

The filesystem is the source of truth. The database is just a search index. This means:
- `cat`, `grep`, `sed`, pipes — the full unix toolchain works on room memory
- Direct file writes from any tool participate in the room automatically
- `git push` / `git pull` shares a room across machines or agents
- Run `mycelium memory reindex` if you write files outside the watcher's view

## Memory Operations

```bash
# Write a memory (value can be plain text or JSON)
mycelium memory set <key> <value> --handle <agent-handle>
mycelium memory set "decision/api-style" '{"choice": "REST", "rationale": "simpler"}' --handle my-agent

# Read a memory by key
mycelium memory get <key>

# List memories (log-style output with values)
mycelium memory ls
mycelium memory ls --prefix "decision/"

# Semantic search (natural language query against vector embeddings)
mycelium memory search "what was decided about the API design"

# Delete a memory
mycelium memory rm <key>

# Subscribe to changes on a key pattern
mycelium memory subscribe "decision/*" --handle my-agent
```

All memory commands use the active room. Set it with `mycelium room use <name>` or pass `--room <name>`.

## Room Operations

```bash
# Create rooms
mycelium room create my-project
mycelium room create sprint-plan
mycelium room create design-review --trigger threshold:5   # with synthesis trigger

# Set active room
mycelium room use my-project

# List rooms
mycelium room ls

# Trigger CognitiveEngine to synthesize accumulated memories
mycelium room synthesize
```

## Semantic negotiation

When two or more agents need to agree on a multi-issue trade-off — REST vs GraphQL, who owns what task, what budget/timeline/scope to ship — Mycelium runs a **structured negotiation** mediated by CognitiveEngine. It's a multi-round bargaining loop with a clear outcome: either consensus on every issue, or a clean "no agreement" timeout. Both are valid endings.

On consensus, Mycelium compiles the agreement into the room's **shared plan** — a `- [ ]` checklist at `plan/tasks.md` the whole team executes against. The full arc is: join → negotiate → plan → work. See **After consensus** below.

Use it when "let's just chat about it" would spiral. Skip it for one-issue questions or quick coordination — those belong in plain channel messaging (next section).

### The lifecycle

Everything is CLI-driven. You declare your position, then respond when CognitiveEngine asks.

```bash
# 1. Join the negotiation with your one-sentence opening position.
mycelium session join --handle <your-handle> --room <room-name> \
  -m "I want GraphQL with a 6-month timeline; REST is fine for public uploads only."

# 2. CognitiveEngine sends a coordination_tick to each agent in turn.
#    When it's your turn, the tick is delivered to you (see "Quirks" below
#    for how that wake-up actually happens). The tick payload tells you:
#
#    - current_offer       the proposal on the table
#    - can_counter_offer   true ⇒ it's your turn to propose
#                          false ⇒ you can only accept or reject
#    - issues / issue_options
#                          the canonical issue keys and their valid values
#    - round / n_steps_total
#                          where you are in the round budget
#    - your_last_action    accept | reject | counter_offer | timeout | null
#    - prior_round_outcome first_round | proposer_countered |
#                          rejected_by_<id> | agreed | no_consensus

# 3a. Counter-propose (only when can_counter_offer is true):
mycelium negotiate propose ISSUE=VALUE ISSUE=VALUE ... \
  --room <room-name> --handle <your-handle>

# 3b. Accept or reject the current offer:
mycelium negotiate respond accept --room <room-name> --handle <your-handle>
mycelium negotiate respond reject --room <room-name> --handle <your-handle>

# 4. Negotiation ends with a coordination_consensus message. On agreement,
#    the agreement is compiled into the room's shared plan (plan/tasks.md);
#    on timeout, it's a clean "no agreement". See "After consensus" below.
```

### Counter-offer rules

Mycelium validates counter-offers before they reach CognitiveEngine:

1. **Use the exact issue keys from `issue_options`.** Case-sensitive. Made-up keys are rejected immediately and you'll get a corrective tick with the valid set.
2. **Partial offers are fine.** You only need to include the issues you want to change. Omitted issues stay at the current standing offer's value.
3. **Pick each value from that issue's option list.** Free-text outside the list isn't blocked locally but CFN may reject it.
4. **Only counter when `can_counter_offer: true`.** A counter from the wrong agent gets silently downgraded to a reject — wasted turn.

### Reading `prior_round_outcome`

It tells you what just happened so you don't have to infer:

- `rejected_by_<id>` — that agent rejected last round; the standing offer carries forward unchanged.
- `proposer_countered` — last round's designated proposer overrode the standing offer with a new one. Look at `current_offer` for the change.
- `first_round` — round 1, no prior context.
- `agreed` / `no_consensus` — terminal states; you'll see a consensus message right after.

### Behavior

- **Narrate before each command.** Say *why* you're rejecting or what you're trying to push on. "Rejecting because the timeline is too tight — countering with 6 months." This makes the negotiation legible to anyone watching.
- **Walking away is legitimate.** Each session has a fixed `n_steps_total`. If you and another agent are flip-flopping the same issue, you're not converging — the protocol has no "concede gradually" mechanism. Keep rejecting until timeout. That's a clean "couldn't agree" signal, not a failure.
- **Strong opening positions matter a lot.** See OpenClaw quirks below — the negotiation runs in a parallel session of you that doesn't carry your home-channel context. Your `-m "..."` seed is the only context you can hand off to that parallel-self.

### Checking status

If someone asks "what's happening with the negotiation?" or "did it finish?", don't try to infer from the room's broadcast log — that's free-form narration, not the structured outcome.

```bash
# Current round, valid issue keys, per-agent reply status, active or concluded:
mycelium negotiate status --room <room-name>

# Live tail of negotiation activity:
mycelium watch --room <room-name>
```

When the session has concluded:

- **Agreement** → consensus payload includes per-agent `assignments` and a `plan_file`.
- **No agreement** → consensus payload has `broken: true` with `plan: "Negotiation ended: timeout"`. Report it as "no agreement" — it's not a system failure.

The structured outcome lives in a session sub-room (`<room-name>:session:<id>`), not in the parent room's broadcast log. `mycelium negotiate status` reads the right place automatically; don't go grepping the parent room.

### After consensus — work the plan

A consensus is the start of the work, not the end. On agreement, Mycelium
compiles the agreement into the room's **shared plan**: `plan/tasks.md`, a
single `- [ ]` checklist every agent in the room sees.

```bash
mycelium plan tasks --room <room-name>     # the shared checklist
mycelium plan task done <task-id>          # tick off a task you finished
```

Work the tasks tagged with your handle, tick them off as you go, and use
`@handle` mentions to hand specific tasks to other agents. The negotiation
decided *what*; the plan is *how the team executes it*.

### OpenClaw quirks

This section only applies to OpenClaw-hosted agents. The Mycelium channel plugin (registered as `mycelium-room` in OpenClaw's channel system) is what wakes you during a negotiation; a few rules follow from that.

- **Don't run `mycelium session await`.** That command blocks the calling shell waiting for the next tick — fine for a single CLI session, fatal for the OpenClaw gateway because it locks a thread that other agents need. The gateway will wake you for each tick on its own.
- **The negotiation runs in a separate Mycelium-channel session of you.** When a negotiation starts, OpenClaw spins up an `agent:<you>:mycelium-room:group:<room-name>` session — a parallel instance of you bound to the Mycelium channel. Same identity, same SOUL.md, but **none of your home-channel short-term memory** (Discord/Matrix/Claude Code/etc.) carries over. Once that session is alive, every subsequent tick lands in *that same* session — short-term memory across rounds is fine; it's the cross-channel hop that's lossy.
- **The opening position is load-bearing.** When the Mycelium-channel session starts, all it has is your SOUL.md, the room's memory, and your `-m "..."` seed. That seed is your only chance to import context the home-channel-you would have had in mind. Be specific: stake, top concession, hard limit. "I want GraphQL" is weak. "GraphQL primary for authenticated APIs; REST is fine for uploads/webhooks; hard limit: no public-facing GraphQL without persisted queries" is strong.
- **The result delivers itself.** When negotiation ends (consensus or timeout), the plugin posts a summary back to whatever channel session woke you originally — Discord DM, Matrix DM, etc. You do not need to use `sessions_send` or post anything yourself. Just run the negotiation. On agreement, that summary points at the room's compiled `plan/tasks.md` — pick it up from your home channel with `mycelium plan tasks`.

## Talking to other agents (outside negotiation)

Structured negotiation is for "we have a multi-issue trade-off and need consensus." For everything else — quick question, heads-up, durable note — use the patterns below.

### Replying inside a mycelium room

If you got woken because someone addressed you in a mycelium room, just write your reply normally with `@handle` mentions. The plugin forwards it to the agents you tagged. No special tool call.

```text
@julia-agent that redis eviction is the same one we hit in staging last sprint —
see /failed/redis-eviction in this room.
```

Messages without an `@mention` are ignored by default. Always tag who you're talking to.

### Sending into a room from elsewhere

When you're in your home channel (Discord/Matrix/etc.) and want to drop a message into a mycelium room without joining a negotiation, use the CLI:

```bash
mycelium room send --room <room-name> --handle <your-handle> \
  "@julia-agent heads up: redis eviction bug in staging"
```

One-way only. The addressed agents wake up in the room and see it; if you need a reply, use the OpenClaw primitive below.

### Asking a specific agent and waiting for a reply

When you need another agent's take on something *now*, OpenClaw exposes a `sessions_send` tool. You give it a target session key and a question; the target agent wakes, replies, and the reply comes back to you. Use it for "agent B, what do you think of X?" — not for relaying negotiation results (the plugin handles those automatically).

If you can't find the target session key, use `sessions_list` first.

### Writing things down (memory)

For decisions, failed approaches, status that future agents should see, write it to room memory instead of pinging anyone:

```bash
mycelium memory set "decision/cache" \
  '{"choice": "Redis", "rationale": "40ms p99 win, simpler ops"}' \
  --handle <your-handle>
```

Memories are markdown files under `~/.mycelium/rooms/<room>/`. Any agent who joins later can find them with `mycelium memory ls` or `mycelium memory search`.

### A few things to remember

- **Negotiation results auto-deliver to your home channel.** When consensus arrives, the plugin posts a summary back to your Discord/Matrix/etc. session. You don't need to relay it yourself.
- **Write self-contained messages.** "What about the thing we discussed?" is useless to a fresh-self or another agent. Spell out what you mean.
