# How the Hive and Event Plane Enable Multi-Agent Coordination in Munder Difflin

> Discover how Munder Difflin's Hive and Event Plane layers enable auditable, reactive multi-agent workflows through on-disk Git persistence and real-time IPC.

- Repository: [Chaitanya Giri/munder-difflin](https://github.com/chaitanyagiri/munder-difflin)
- Tags: deep-dive
- Published: 2026-08-28

---

**Munder Difflin splits autonomous Claude agent runtime state into two orthogonal layers: the Hive (on-disk Git persistence) and the Event Plane (real-time hook-driven IPC), enabling auditable, reactive multi-agent workflows.**

The **hive/event plane** architecture in [Munder Difflin](https://github.com/chaitanyagiri/munder-difflin) solves a critical challenge in multi-agent systems: how to give autonomous Claude agents both durable, version-controlled memory and real-time reactive behavior. This design separates persistence from communication, letting agents remember indefinitely, coordinate asynchronously, and respond to live events without losing state.

## The Two-Layer Architecture

| Layer | Responsibility | Key Mechanism |
|-------|---------------|-------------|
| **Hive** | Durable, auditable state | Git-tracked folder with atomic file writes |
| **Event Plane** | Real-time event streaming | Claude Code hooks over Unix-domain socket |

These layers operate independently but coordinate through the Electron main process, which is the sole Git committer and the consumer of all IPC events.

## Understanding the Hive: On-Disk Persistence

The Hive lives at `<harnessHome>/hive/` as a regular Git repository. Only the Electron main process commits, enforcing a strict single-writer policy that prevents merge conflicts and index lock contention.

### Directory Layout

```

hive/
  PROTOCOL.md            # Agent contract: how to remember and message

  registry.json          # Roster of all agents with capabilities

  board.md               # Shared blackboard (god agent only)

  tasks.json             # Task ledger with assignee and status

  log.jsonl              # Append-only global event feed

  agents/<agentId>/
    identity.md          # Static agent description

    memory.md            # Long-term per-agent memory

    inbox/               # Incoming messages

    inbox/.done/         # Processed messages (audit trail)

    outbox/              # Outgoing messages (router drains)

    cursor.json          # Last processed message ID

```

### Core Design Rules

- **One-writer-per-file**: Each agent writes only inside `agents/<id>/`.
- **Atomic writes**: Messages use temp-file + rename ([`hive.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/hive.ts) implements this).
- **Append-only logs**: Consumers track their own cursor; history never rewrites.
- **Global files restricted**: Only `log.jsonl` (append) and [`board.md`](https://github.com/chaitanyagiri/munder-difflin/blob/main/board.md) (god-mediated) permit cross-agent writes.

The message schema follows a trimmed FIPA-lite "speech-act" format defined in [`HIVE.md`](https://github.com/chaitanyagiri/munder-difflin/blob/main/HIVE.md):

```json
{
  "id": "2026-05-30T14-03-11-123Z-a1b2",
  "conversation": "conv-7f3",
  "in_reply_to": null,
  "from": "agent.researcher",
  "to": "agent.coder | god | broadcast",
  "act": "request | inform | propose | query | agree | refuse | done",
  "subject": "short human-readable summary",
  "body": "free text / markdown / structured payload",
  "hops": 3,
  "requires_reply": true,
  "needs_human": false,
  "created_at": "ISO-8601"
}

```

### Writing Messages to the Hive

Agents output messages to their `outbox/`; the [`router.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/router.ts) implementation handles delivery:

```typescript
import { writeFileSync, renameSync } from 'fs';
import { v4 as uuid } from 'uuid';
import * as path from 'path';

const msg = {
  id: `${new Date().toISOString()}-${uuid()}`,
  conversation: 'conv-123',
  in_reply_to: null,
  from: 'agent.researcher',
  to: 'agent.coder',
  act: 'request',
  subject: 'fetch latest spec',
  body: 'Please read SPEC.md and summarize the key points.',
  hops: 0,
  requires_reply: true,
  needs_human: false,
  created_at: new Date().toISOString(),
};

const outDir = '/path/to/hive/agents/researcher/outbox';
const tmp = path.join(outDir, `${msg.id}.tmp`);
const final = path.join(outDir, `${msg.id}.json`);

writeFileSync(tmp, JSON.stringify(msg, null, 2));
renameSync(tmp, final);   // atomic: router polls for .json files only

```

### Consuming Messages from the Hive

```typescript
import { readdirSync, readFileSync, renameSync } from 'fs';
import * as path from 'path';

const inbox = '/path/to/hive/agents/coder/inbox';
const done = path.join(inbox, '.done');

for (const file of readdirSync(inbox)) {
  if (!file.endsWith('.json')) continue;
  const msg = JSON.parse(readFileSync(path.join(inbox, file), 'utf8'));
  // Process message...
  renameSync(path.join(inbox, file), path.join(done, file));
}

```

## Understanding the Event Plane: Real-Time IPC

While the Hive handles durability, the **Event Plane** enables reactivity. Claude Code processes emit structured events through hooks, which a shim (`tools/cth-hook`) forwards over a Unix-domain socket to the Electron main process.

### Hook Types and Flow

| Hook | When Fired | Use in Munder Difflin |
|------|-----------|----------------------|
| `UserPromptSubmit` | New user input | Trigger agent activation |
| `PreToolUse` | Before tool execution | Audit or block operations |
| `PostToolUse` | After tool completion | Update state, route results |
| `Notification` | Claude emits alert | Surface to UI or escalate |
| `Stop` | Turn ends | Poll inbox, decide block/resume |

Each hook:

1. Receives JSON payload from Claude Code
2. Tags with `session_id` via environment variable
3. POSTs to `~/.cth/events.sock`

The main process consumes these events to:

- Update the Pixi canvas avatar state machine
- Refresh the xterm view
- Trigger Hive operations (routing, logging, committing)
- Decide whether to block an agent (keep active for pending messages)

### Hook Shim Implementation

```bash

# Conceptual cth-hook shim

cat | jq '. + {session_id: "$CLAUDE_SESSION_ID"}' |
  while read -r line; do
    printf '%s\n' "$line" >> ~/.cth/events.sock
  done

```

## How Hive and Event Plane Coordinate

The true power of Munder Difflin's **hive/event plane** design emerges in their integration. Consider this request-response flow:

1. **Agent B** needs data from **Agent C** → writes to `agents/B/outbox/`.
2. **Router** ([`src/main/router.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/router.ts)) detects the file, moves it to `agents/C/inbox/`, appends to `log.jsonl`, and commits.
3. **Agent C** finishes its turn; the `Stop` hook fires via Event Plane.
4. **Main process** polls C's inbox, finds the pending request, returns "block" decision.
5. **C** stays active, reads request, performs work, replies through its outbox.

This hybrid approach gives **synchronous coordination semantics** built on **asynchronous, durable storage**.

## The God Orchestrator

A privileged *god* agent (the "CEO" desk) centralizes sensitive operations per [`src/main/godAgent.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/godAgent.ts):

- **Routing resolution**: Handles routine outbound requests without waking target agents.
- **Human escalation**: Surfaces critical requests (destructive actions, budget overruns) through native Claude Code sessions.
- **Blackboard ownership**: Sole writer of [`board.md`](https://github.com/chaitanyagiri/munder-difflin/blob/main/board.md), ensuring conflict-free shared planning.

The god agent is itself a consumer of both planes: it receives events via IPC and persists decisions to the Hive.

## Key Implementation Files

| File | Purpose |
|------|---------|
| [`HIVE.md`](https://github.com/chaitanyagiri/munder-difflin/blob/main/HIVE.md) | Design document specifying layout, schema, routing, and god orchestrator |
| [`SPEC.md`](https://github.com/chaitanyagiri/munder-difflin/blob/main/SPEC.md) | Two-plane architecture specification (Event Plane vs Terminal Plane) |
| [`src/main/hive.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/hive.ts) | Runtime Hive API: load agents, persist messages, Git commits |
| [`src/main/router.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/router.ts) | Outbox watcher, message mover, `log.jsonl` appender |
| [`src/main/godAgent.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/godAgent.ts) | Privileged orchestrator logic |
| `tools/cth-hook` | Hook-to-socket shim for Claude Code integration |

## Summary

- **Hive** provides **Git-backed durability** with atomic file writes, single-writer rules, and append-only logs.
- **Event Plane** delivers **real-time reactivity** through Claude Code hooks over Unix-domain sockets.
- **Router** ([`router.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/router.ts)) bridges them: watching outboxes, moving messages, committing history.
- **God agent** centralizes escalation and shared state to prevent merge conflicts.
- Together they enable **auditable, recoverable, reactive multi-agent coordination** without sacrificing either persistence or responsiveness.

## Frequently Asked Questions

### What is the difference between the Hive and the Event Plane?

The **Hive** is the on-disk, Git-tracked persistence layer where all agent state, messages, and history live permanently. The **Event Plane** is the real-time IPC mechanism that streams hook events from Claude Code processes to the main process. The Hive ensures you can replay and audit everything; the Event Plane ensures the UI and agents react immediately to state changes.

### Why does only the main process commit to Git?

Munder Difflin enforces a **single-writer-per-file** rule to eliminate Git index lock contention. If multiple agents or processes tried to commit simultaneously, Git's locking would create race conditions and failures. By centralizing all commits in the main process, the system guarantees atomic, conflict-free history.

### How do agents communicate without direct connections?

Agents communicate through **asynchronous mailbox files**. When Agent A sends to Agent B, A writes to its own `outbox/`. The router (main process) detects this, moves the file to B's `inbox/`, logs it, and commits. B discovers the message on its next activation via the Event Plane's `Stop` hook, which triggers a poll of its inbox.

### What happens when an agent needs human approval?

The **god agent** adjudicates such requests. When a message has `needs_human: true` or involves critical operations, the god agent escalates through a native Claude Code session rather than auto-resolving. This privileged agent is also the sole writer of [`board.md`](https://github.com/chaitanyagiri/munder-difflin/blob/main/board.md), maintaining a clean audit trail for all human-involved decisions.