Appearance
A Conversation Log is a shared append-only JSONL of every message, tool call, and mutation across agents in a multi-agent session — tailed (not fully read) at task start so agents stay coordinated without duplicating each other's work.
Primitive
Conversation Log
The artifact
JSONL. One event per line. No multi-line entries.
.pi/multi-team/sessions/abc/conversation.jsonl
JSONL
10:00:00{agent:orchestrator, type:message, body: "Classifying to engineering-lead"}
10:00:02{agent:orchestrator, type:tool_call, tool: delegate, args: {...}}
10:00:05{agent:engineering-lead, type:message, body: "backend-dev will handle"}
10:00:20{agent:backend-dev, type:mutation, kind: tilldone-done, task_id: "jwt"}
Chosen so tail -n 20 conversation.jsonl | jq . works from the shell. Humans and agents read the same format.
Fixed vocabulary
Four event types. Extending them requires updating every reader.
message
Agent said something. The body field is the text. What the orchestrator speaks, what a lead replies, what a worker reports.
tool_call
Agent invoked a tool. Tool name + args. Captures delegation, read, write, bash — every non-text action.
tool_result
Tool returned. Paired with a tool_call. The return value (truncated if large); enables tail-readers to see outcomes.
mutation
Session state changed. Task marked done, skill activated, agent spawned. The log becomes authoritative for state — not just transcript.
Why agents don't read the whole log
Tail N entries. Not N × session_length.
ignored — old historyLAST 20 ✓
turn 1turn 500now
Full-log reads grow unboundedly with session length. Tail reads are O(N) regardless of total size. The active-listener skill enforces this: every agent tails the last N before responding, getting awareness without blowing the context budget.
The single-source-of-truth rule
If UI and log disagree, the log wins.
invariant
Mutations outside the log → divergence.
anything that changes session state
MUST write a mutation event
If a worker marks a task done by updating some internal field without emitting a {type: mutation}, the UI says pending, the log says nothing — and nobody knows the truth. The log is where state events go, not just where messages go. Make this rule early; breaking it is expensive to fix later.
What breaks
Four failure modes. All predictable.
Multi-line entries
Tail reading becomes stateful — must find entry boundaries. Fragile. Pretty-printed JSON breaks the whole contract.
Agents reading the full log
Context budget blown on history that doesn't matter for the current turn. The whole design assumes bounded reads.
Mutations outside the log
State divergence. UI shows X, log says Y. Nobody knows which is authoritative.
Shared logs without session scoping
Concurrent sessions' lines interleave. Tail reads surface irrelevant context from other sessions.
The discipline
One log. Tail-read, mutation-aware, session-scoped.
JSONL so tail + jq is the whole reader. Fixed vocab so extending the log is a deliberate act, not accidental drift. Mutations go through the log so the log is authoritative, not decorative. The log is how five agents in a room stay coordinated without each of them reading the other four's minds.