Phase 01 · Linear intake
The simplest slice of The Archivist: wire a dispatcher, register its nodes and DAGs in dependency order, execute one visitor query, and read the lifecycle result. The full runner is below — this is the real code.
Flow
Code
The #linear-run region covers the dispatcher construction, molecular deep-DAG registration, and the execute call that drives the full flow:
ts
// ── Dispatcher ───────────────────────────────────────────────────────────
const dispatcher = new Dagonizer<ArchivistState, ArchivistServices>({ services });
// ── Deep-DAG node registration (molecular pattern) ───────────────────────
// Each deep-DAG module exports a registerXxxNodes helper that registers
// the nodes it needs. Call it before registerDAG so the validator can
// resolve all node references when the DAG is registered.
registerBookSearchFanoutNodes(dispatcher);
dispatcher.registerDAG(BookSearchFanoutDAG);
registerComposeRetryLoopNodes(dispatcher);
dispatcher.registerDAG(ComposeRetryLoopDAG);
// ── Parent-DAG-only nodes (not used by deep-DAGs) ────────────────────────
for (const node of [
recallContext,
classifyIntent,
// Inlined branch nodes (reviews + describe) — not in the deep-DAGs
extractQuery,
decideTools,
webSearchScout,
openLibraryScout,
googleBooksScout,
subjectScout,
wikipediaScout,
rankByRating,
pickBestMatch,
mergeCandidates,
recordFindings,
hasCitationsGate,
groupByYear,
recallPastVisits,
recommendSimilar,
// recall-memories branch
recallMemories,
composeMemoryResponse,
respondToVisitor,
declineOffTopic,
declineEmpty,
// empty-result LLM response branch
composeEmptyResponse,
]) {
dispatcher.registerNode(node);
}
dispatcher.registerDAG(archivistDAG);
// ── Demo run ─────────────────────────────────────────────────────────────
const visitor = new ArchivistState();
visitor.query = "I'm looking for a book about a strange house and a library";
const result = await dispatcher.execute('the-archivist', visitor);
logger.result(`intent=${result.state.intent}`);
logger.result(`shortlist=${String(result.state.shortlist.length)}`);
logger.result(`draft=${result.state.draft}`);
logger.result(`lifecycle=${result.state.lifecycle.kind}`);
logger.result(`triples=${String(services.memory.size)} written`);What it demonstrates
- Molecular registration order — deep-DAG nodes must be registered before their DAG is registered (
registerBookSearchFanoutNodes→dispatcher.registerDAG(BookSearchFanoutDAG)), and both deep-DAGs before the parentarchivistDAG. The dispatcher validates all node references at registration time. - Single execute call —
dispatcher.execute('the-archivist', visitor)drives the entire multi-branch flow. The caller sees oneExecutionResult<ArchivistState>containing the final state and lifecycle. - Lifecycle result —
result.state.lifecycle.kindis'completed','cancelled', or'timed_out'. Nodes never throw; the dispatcher always returns. - Services bag — every node receives
context.services(LLM, search tools, memory, logger). Nodes never construct their own clients.
See this in action in the Archivist live demo.