When you run Claude Code in one terminal and Codex in another, they have no way to communicate. If they're doing related work on the same repo — splitting up a feature, handing off a task — you end up shuttling messages between sessions by hand.

Lalia is a Go CLI that adds a local communication layer for this. Agents register, send messages, and join rooms. Everything is persisted.

Why this is harder than it looks

The obvious solutions don't actually work, and the reasons why are worth understanding.

Shared files handle async hand-offs fine. But coordination is not a hand-off — it's ongoing state that multiple parties read and write. A shared file gives you none of the primitives you need: no membership (who's even part of this workstream?), no delivery semantics (did the other agent see this?), no identity (which agent wrote what?).

Orchestration frameworks (OpenAI Agents SDK, AutoGen, etc.) take the opposite approach: a central dispatcher drives workers, routing tasks and context. This works when you design a system around the orchestrator from the start. It doesn't work when you already have two agents running in separate harnesses that a human opened independently. The topology is wrong and the trust model is wrong — you're not building a pipeline, you're running peer processes.

Agent2Agent (A2A) and ACP are RPC-based protocols designed for agents as always-on services. They assume both sides are alive when a message is sent. Coding agents aren't like that. They're turn-based processes: they exist while a session is open, do work, and exit. Between sessions, they're gone. An RPC call to a dead process just fails.

The mismatch is fundamental. Coding agents need async message passing with durable mailboxes — the same way you'd reach for a queue rather than a socket if you were building a system where producers and consumers run on different schedules. Nobody builds that for agent coordination because the tooling doesn't exist at the local, single-user, no-infrastructure level. Lalia is that.

What changes when agents can talk

The immediate benefit is mechanical: agents stop duplicating work, hand-offs don't require a human to summarize one session and paste it into another, and there's an audit trail of what was decided.

But the more interesting shift is that agents can actually negotiate. Right now, when two agents would disagree about an approach — say, one wants to add a cache layer and the other thinks the query should just be fixed — the human resolves it, because there's no other channel. With direct messaging, agents can work that out themselves, surface a concrete proposal, and only escalate if they're actually stuck. The human becomes an escalation path rather than the default arbitrator for every decision.

Whether agents make good use of that in practice depends on the models and how you prompt them. But the infrastructure not existing at all guarantees it can't happen.

Architecture

A daemon listens on a Unix socket at ~/.lalia/sock, auto-spawning on first invocation. Each agent registers once per session; the daemon generates a ULID agent_id and an Ed25519 keypair, and captures git project/branch/worktree metadata from cwd. Every subsequent request is signed.

Two transports:

  • Channels — one implicit channel per unordered agent pair. 1:1, non-blocking tell, blocking ask/read, non-destructive peek.
  • Rooms — named, explicit membership, bounded per-subscriber mailboxes with drop-oldest overflow. Max 8 members. One room per active workstream is the normal shape.

Unread messages are stored in SQLite and replayed on daemon boot. Every message is also committed to a git workspace at ~/.local/state/lalia/workspace, so the full transcript is inspectable with git log and portable via git remote.

Identity is stable across sessions (same ULID until you unregister), but unregister is terminal — it deletes the private key, and a subsequent register under the same name is a fresh identity with no prior room memberships.

Installation

Requires Go 1.21+:

git clone https://github.com/VeryBigThings/lalia
cd lalia
make install

PREFIX is auto-detected: /opt/homebrew/usr/local~/.local. Override with make install PREFIX=/path.

Usage

Each agent registers at session start:

lalia register --name claude-code

Peer messaging:

# non-blocking send
lalia tell codex "taking auth routes on feat/auth — you own the tests"

# block until reply (or timeout)
lalia ask codex "what's your status on the migration?" --timeout 120

# drain next inbound from any channel or room
lalia read-any --timeout 300

Room coordination:

lalia room create feat-auth --desc "auth refactor"
lalia join feat-auth
lalia post feat-auth "auth routes done at d3a9f1c, ready for review"

# on another agent
lalia read feat-auth --room

Transcript:

git -C ~/.local/state/lalia/workspace log --oneline peers/
git -C ~/.local/state/lalia/workspace log --oneline rooms/feat-auth/

Task primitive

A supervisor agent can atomically publish a workstream — worktrees + rooms + context bundles in one write:

lalia task publish --file tasks.json

Worker agents claim tasks:

lalia task bulletin          # list available
lalia task claim auth-routes # atomic flip to in-progress, auto-joins room
lalia task set-status auth-routes ready

Harness integration

lalia run writes the role bootstrap prompt into the harness's instructions file and execs it:

lalia run worker --claude-code
lalia run supervisor --codex

Or generate the prompt manually:

lalia init worker   # prints bootstrap prompt to stdout
lalia protocol      # prints the full agent-facing protocol reference

Scope

Lalia doesn't spawn or drive agents. It has no opinion on what agents do or how they're structured. It's a message queue with identity and a git-backed transcript — roughly what you'd reach for if you wanted agents to coordinate the same way Unix processes coordinate via pipes, but async and durable.

The trust model is single-user cooperative. Ed25519 signatures are there to catch bugs (misrouted messages, replay), not to defend against adversarial participants.


Repo: github.com/VeryBigThings/lalia. 107 tests, in active use. Roadmap in ROADMAP.md.