The Harness — Implementation Plan
Three nouns, five verbs: plan and milestone gates for the Seed Agents harness rebuild

The Harness — implementation plan

Status: in progress (started 2026-08-11). Architecture source: the "Three nouns, five verbs" deck (claude.ai
artifact 7ec78c32), superseding the five-collapses deck; grounded in workflows v1 as built on feat/agent-workflows
(PR #920) and agents/docs/research/ (branch agents-planning).

Breaking changes are allowed and preferred over aliases or dual paths. What must not regress is the v1 spine: the
runs queue (leases, boot sweep, park/resume, persisted usage), the QuickJS journaled script engine with content-keyed
replay, verbatim-markdown briefings, and the one-card UX law (steer from one place, interrogate one click deep, never
lose work).

Architecture in one paragraph

Three nouns: the Space (one document tree per agent account — ~/tools, ~/memory, ~/plans, ~/triggers,
agent.md; every tool is a document with a summary line, an Onyx contract, a description, and source or a builtin
binding), the Log (per-thread append-only events, each stamped with an actor), and the Runs (the v1
tree-queue, kept verbatim). Five verbs — read, write, call, delegate, plan — replace the 25-tool registry;
everything else is a document under ~/tools/, collapsed to its summary until touched. The user holds the same five
verbs through the same log (symmetry). Two engines: QuickJS scripts orchestrate (journaled), microVM lambdas compute (TS
first-class, Python kept). Long-running work is parked runs plus wake sources; triggers are documents that bind event
sources to continuations and serve as the event bus.

Branch & review protocol ("checkmark branches")

Base: feat/agent-workflows (rebased onto main 2026-08-11). Milestones land as a stacked series:

feat/agent-workflows ← base (PR #920) └─ harness/01-verbs └─ harness/02-tools-as-docs └─ harness/03-symmetric-log └─ harness/04-exec └─ harness/05-time └─ harness/06-event-bus

Per-milestone protocol, in order:


    Build on the milestone branch; commits stay small and story-shaped.

    Gate (self-verification, all must pass before anything is pushed):


    bun x tsc --noEmit in agents/ (and desktop typecheck when frontend is touched)

    bun test in agents/ — full suite, no skips added

    desktop vitest for touched UI packages

    the prompt-budget test (M2+): system-prompt bytes for a default agent stay under target

    the simulated-model gate: a blind subagent, given only the live tool schemas, completes a scripted task

(delegation fan-out, tool discovery, plan maintenance). This replaces the gpt-5-mini cassettes wherever the tool
surface changed, because cassette fingerprints include tool names; re-recording live gates is deferred until
credits exist and is tracked in the review doc.


    Self-review: an adversarial review pass over the milestone diff (correctness, crash/replay safety,

prompt-injection surface, UX-contract regressions against the settled v1 decisions). Findings fixed or explicitly
recorded as accepted gaps.


    Checkmark: push the branch, write agents/docs/harness/reviews/NN-<name>.md containing: what changed and why,

how it was verified (gate output summaries), known gaps, and a manual test script for Eric — concrete desktop
steps with expected outcomes.


    Prompt Eric to review the checkmark. Work continues onto the next milestone without blocking; his feedback is

folded in as fixup commits on the open milestone and propagated up the stack with rebases.

Milestones

M1 — The five verbs (harness/01-verbs)

The registry monolith (agents/protocol/src/tool-registry.ts, ~1,400 lines, 25 tools) is replaced by five verb
definitions plus internal address dispatch. No aliases: the old tool names stop existing; stored transcripts keep their
historical events (rendered generically) and replay fine — provider messages carry names verbatim and never re-dispatch
old calls.


    read {address, …opts} — one dispatcher keyed by address shape:

    ~/memory/** → agent-memory read/list (dir address ⇒ listing with summary lines)

    ~/tools/** → tool contract (M1: from the builtin table; M2: from documents)

    hm://… → existing hypermedia read path; ipfs://… → ipfs read

    https://… → web read; activity: (or ~/activity) → activity feed with existing filters

    ~/threads/<id> → transcript; run:<id> → run journal

    write {address, content, …opts} — memory writes/deletes, plan documents, hm:// document operations (absorbing

the 22-command write envelope into address+content+intent), ipfs://, attachment moves (an attachment is just a
readable source address).


    call {tool, input} — dispatch by tools/… path over one seam (registerBuiltin), which M1 introduces

internally: search, web_search, navigate, execute land here as bound builtins. Calling an unexpanded tool returns its
contract as the result (touch-expands); the retry runs.


    delegate {brief, script?, output?, await?, title?, step?} — merges sub_session (default), run_workflow

(script present ⇒ script child), start_session (await: false ⇒ detached but still in the run tree).
Verbatim-markdown briefs, typed output with bounded retries, plan-step attachment — all preserved from v1.


    plan {steps | update} — absorbs update_plan; set_session_title is deleted (titling is already automatic and

agent-authored).

Files: protocol/src/tool-registry.ts (rewrite), protocol/src/index.ts (event/type updates), api-service.ts
(createAgentServicePiTools region, the three name-filter chains, delegation paths), shared UI tool renderers
(@shm/ui/agents), desktop run-card step labels, affected tests across agents/src/*.test.ts and desktop.

Success is measurable: default-agent system prompt shrinks by roughly the difference between 25 schemas and 5; model
tool-choice in the simulated gate has no wrong-tool retries.

M2 — Tools as documents (harness/02-tools-as-docs)


    Tool documents in the Space: frontmatter-style metadata (name, summary, tags, grants required), Onyx input/output

contracts, model-facing description, and source (lambda) or builtin binding id. Storage rides the agent-memory tree
(~/tools/**) so read/write/versioning come free; each save produces a CID (content-address the canonical CBOR
encoding).


    Boot upsert: builtins materialize/refresh their documents at service start; a forked builtin doc keeps the binding id

but its contract diff is visible.


    The index: generated summary of the Space (one line per tool/group, memory dirs with counts, live plans, active

triggers), injected into every run's system prompt; a CI test asserts the byte budget (~1.5 KB default agent).


    Touch-expand + pins: read on a tool document (or contract-returning call) appends a durable

expanded {path, cid} log event and activates the tool via Pi setActiveToolsByName; replay/compaction/park-resume
reconstruct the active set from pins. Unpin is explicit.


    The five verbs' own docs deepen on first use (full help returned beside the first result).

M3 — The symmetric log (harness/03-symmetric-log)


    actor: 'user' | 'agent' | 'system' | 'trigger' on session events (schema migration; existing rows backfill by event

type).


    Protocol: user-invoked read/write/call against a thread — appended to the log as actor: user

tool_call/tool_result pairs and executed as runs on the interactive queue; the agent sees them in transcript replay on
its next turn, no side channel.


    Desktop: composer / palette over the Space (tools, saved plans, triggers); Onyx-schema-generated forms for tool

input; results render with the existing card grammar; user edits to plan steps and per-child cancels emit log events
the agent can read.


    Web parity via the shared @shm/ui/agents package where the platform adapters allow.

M4 — Execution cleanup + TS (harness/04-exec)


    execute {runtime: 'ts' | 'python', code, files?} — the whole compute surface; option sprawl (image/cpu/memory per

call) collapses to service config.


    Bun-based TS runner image beside the Python image; one file-framed runner protocol for both; runner-protocol suite

runs against the injected fake sandbox, real-microVM smoke stays gated.


    Lambda tool documents become callable: call tools/<lambda> = validate input (Onyx, outside VM) → execute stored

source → validate output. Author→test→save flows through write + call.

M5 — Time (harness/05-time)


    runs.wait gains event and budget-pause beside children/timer.

    ctx.sleep(until) persists wake-at; the dispatch loop's timer sweep wakes due runs (days-scale, restart-proof —

kill/restart tests across sleeps).


    ctx.waitForEvent(match, {timeout}) registers an ephemeral trigger scoped to the run; firing appends the payload

to the journal and requeues the run; timeout is a timer wait racing it.


    ctx.continueAsNew(state) finalizes the run and enqueues a successor carrying declared state only — journal growth

over week-scale loops stays bounded.


    Card/thread copy for every parked state: "sleeping until 08:00", "waiting for approval", "paused: daily budget", with

user wake/cancel affordances.

M6 — The event bus (harness/06-event-bus)


    Trigger documents in ~/triggers/** replace the trigger CRUD protocol surface; monitors read documents.

status: draft | active; activation is the consented step (minimal consent card — the card grammar's question state).


    Sources: the shipped four (schedule, document-comment, user-mention, site-update) plus document-change (watch any

hm:// path or Space dir) and run-completed (chain automations). Webhook stays out of scope unless trivial.


    Continuations: newThread {brief} (today's behavior), appendTo {thread}, wake {run, signal} (delivers to a

waiting ctx.waitForEvent), runPlan {plan} (saved plan → fresh run).


    Per-trigger budgets with auto-pause; firing history browsable as run records beside the document.

Test strategy summary


    Unit/integration: the existing agents suite is the backbone; every milestone leaves it green and grows it

(address-dispatch table tests, pin-replay tests, actor-backfill tests, runner protocol, timer-sweep kill/restart,
trigger-continuation matrix).


    Determinism: golden replay tests for the script engine remain untouched proof that journaled semantics survived

each milestone.


    Model-facing: simulated-model gates (blind subagent over the real schemas) per milestone; live gpt-5-mini cassette

re-record is a single deferred task once credits exist.


    Manual (Eric): each review doc ends with a five-minute desktop script — the checkmark is not done until that

script passed for me first.

Do you like what you are reading? Subscribe to receive updates.

Unsubscribe anytime

Connections0

Connections show where other documents or comments link to this document.

Related documents

Loading connections…