Append-only journals as the coordination medium for AI agents that never run at the same time.
Multiple agents need to collaborate on one piece of work, but they don't run concurrently — one finishes and shuts down before the next is spun up, and work can stretch across hours or days. There is no shared live memory. djournal makes the coordination medium a durable, append-only journal file per task: an agent reads the record, does its part, appends its results, and hands off. The work survives agent shutdown, crashes, and the passage of time.
The journal is the state machine and the program counter — not an external engine. The orchestrator is a small, stateless interpreter; coordination patterns live in journal entries as conventions, not in scheduler code.
- One journal per task. Each task is one append-only file (
<task-id>.djl) that only ever grows. Parallelism is expressed as many journals, never many writers in one. - Public-read, private-append (single-writer). Any agent may read any
journal; only the current baton-holder appends, and only to its own. So
there is never a contended write anywhere in the system. The sole exception is
the orchestrator's one privileged
done-abandoned. - One entry primitive, distinguished by addressee. A note (to no one —
history/heartbeat), a handoff (to an agent role — passes the baton), or a
terminal (
done-ok/done-failed/done-abandoned— closes the journal). The final terminal block is the journal's public return value. - Inline markers as the index. Markers live in the file itself, so the CLI locates any slice (an entry, the trail, the live handoff, the outcome) without scanning the whole file — reads stay bounded by slice size, not journal size.
- Lifecycle.
open → closed. A closed journal is frozen and immutable, and may be referenced read-only by successor journals.
Cross-journal coordination: fan-out by spawning child journals, join by
declaring blocked-on and letting the scheduler observe closure, supervision
by a parent handling each child's terminal, and retry-by-reference (a fresh
journal whose brief references the frozen failed one). Failure propagates up the
supervision tree; blocked-on is constrained to descendants, so it cannot cycle.
Requires Zig 0.16.
zig build # build the djournal CLI → zig-out/bin/djournal
zig build test # run the test suite
zig build run -- … # build and run with args
djournal triage --to <role> [request] open a new root journal (entry point)
djournal append <id> --as <role> <kind> [body] append an entry; prints its number
djournal head <id> the live handoff (or terminal, if closed)
djournal show <id> <n> one entry by number
djournal trail <id> the full trail, task-start → tail
djournal outcome <id> a closed journal's terminal block
append kinds (exactly one): --note · --to <role> · --done-ok ·
--done-failed · --done-abandoned. A body may be given inline or piped on
stdin (captured verbatim), so append composes with pipes and
here-documents. The journal directory defaults to ./journals, overridable with
$DJOURNAL_DIR.
$ export DJOURNAL_DIR=./journals
$ djournal triage --to planner "write a haiku about append-only logs"
t-0001
$ djournal append t-0001 --as planner --to poet "3 lines, 5-7-5, theme: durability"
2
$ djournal append t-0001 --as poet --done-ok "logs never forget / each line a kept promise / the past stays the past"
3
$ djournal outcome t-0001
#3 [■ done-ok]
logs never forget / each line a kept promise / the past stays the pastThere is no bespoke process-spawning engine: the "runtime" is a basic agent in a
harness using djournal as its coordination tool. The harness loop is mechanical
(scan → read each head → evaluate blocked-on → create children from spawn
directives → route → abandon the silent-and-dead). See
docs/agent-protocol.md for the worker-agent and
harness protocols, and docs/format.md for the on-disk format
and marker/convention syntax.
src/
journal.zig entry model, addressee→kind, marker (de)serialization, lifecycle
store.zig append-only files, single-writer + closed enforcement,
marker-indexed retrieval, the injectable Clock
orchestrator.zig stateless scan/route/evaluate/abandon + triage
coordination.zig fan-out / join / supervision / retry conventions + helpers
main.zig the djournal CLI
e2e.zig end-to-end lifecycle tests
docs/ on-disk format + agent protocol
openspec/ capability specs and change history
Greenfield and self-contained: the journal format, CLI, orchestrator logic, and
coordination semantics are implemented and tested (zig build test). The
agent/harness runtime is specified by docs/agent-protocol.md; wiring it to a
concrete agent framework is left to the harness author.
Licensed under the Mozilla Public License 2.0. See LICENSE.