Nodes and builtins
The nodes a template is made of, with node kinds and fields, ports and cords, every builtin and its config keys, the ticket-completion node ids in order, and the model profiles.
A template's patch document is nodes joined by cords. This page says what the code does; file:line citations are in parentheses. The file format around it is on templates.
01node kinds and fields#
A document has version, nodes and cords. A node has these fields:
id: the node's name in the document.kind:runtime,builtinorsubpatch. A template may not use a subpatch (see templates).runtime: for a model node, theruntime, themodeland theprofile.builtin: for a builtin, itstype.subpatch: apath.config: a map of keys that the node reads.inletsandoutlets: the node's ports.layout: where the board draws the node. It is not part of the topology revision.stage: optionally marks the node as a stage on the run's progress bar, with alabel.
A model node runs an agent process. A builtin is deterministic code that smith runs itself.
02ports and cords#
A port has an id, a kind, and optionally a JSON schema and an initial value. The kind is bang or message. A message carries a JSON payload that is checked against the port's schema. A bang carries no payload: it only says that something happened.
A cord joins an outlet to an inlet. Its delivery.mode is enqueue or latest and nothing else.
enqueueadds the envelope to the inlet's queue.latestreplaces an envelope still queued from the same cord, and journalsenvelope.replaced. The shipped ticket templates use it for the cords that send work back.
A queue holds 64 envelopes by default and rejects the one that does not fit. Harness launches use capacity 32 and one invocation at a time. The run's events are on runs.
A cord that sends a baton back to an earlier node makes a loop. Each envelope counts its hops, and the hop cap ends a loop that does not converge. See runs.
03profiles#
A model node declares a profile, and a template without one is refused. The profiles are reason, inspect, work and research.
workis the profile that gets a writable workspace in the run's own tree. The shipped templates use it for the worker.inspectis used for planners and reviewers, which read the workspace.researchis the only profile that takesmax_searches,max_fetchesandmax_tokens.reasonis used for intake, close and challenge nodes in the shipped templates. What it permits beyond that is not checked.
checks is not a model profile. env_profile: checks on deps and command_check names the environment that commands run in; see checks.
04model node config#
The keys that the shipped templates set on model nodes are prompt, merge_input, input_fields, output_fields, capabilities, context_sources, workspace_mode, ticket_field, read_ticket_fields, attempts, resume_cords, resume_input_fields, resume_prompt, record_decision and skip_on_failure. The full list of keys a model node reads is not checked.
05builtins#
Every builtin is in KnownBuiltins, and its runner and description are in internal/service/patch_builtin_registry.go. command_check and check_router are on checks. A builtin with a single outlet infers it when outlet is not set.
passthrough
passthrough: forwards the envelope unchanged. Config: optional outlet (registry line 26).
switch
switch: routes the envelope to a named outlet. Config: route.
router
router: routes an object by equality of one field. Config: field and equals pick true_outlet or false_outlet. max_false with exhausted_outlet diverts the false route once it has been taken max_false times since the last human gate decision, and adds a loop_exhausted line to the baton.
iter
iter: walks a list on the baton, one item per pass. It keeps no state: the cursor rides on the baton, so n items take n+1 passes. Config: list_field (required), cursor_field (default iter_cursor), item_field (default item), item_outlet and done_outlet.
rework
rework: sends back only the tickets of a sorted batch that a failure points to; a failure that maps to no claim sends the whole batch. Config: list_field (default work_list), cursor_field (default iter_cursor), item_field (default item) and optional outlet.
capability_assert
capability_assert: requires evidence of capability calls before it forwards a baton. Config: source_node, tools, and optionally package, ticket_field, ticket_list_field, exactly_once and conditional_tools. The shipped templates also set required_if, repair_tool, repair_outlet, repair_field, decision_sources, landed_node, blocked and outlet. The full list of keys is not checked.
workspace_handoff
workspace_handoff: seals the released workspace evidence into an immutable handoff. Config: source_node, optional baton field mappings, and an optional format list of formatter commands (id, executable, args, match, timeout) that run on the changed files before sealing.
workspace_land
workspace_land: commits the approved handoff, exactly as sealed, in its workspace. Config: source_node, optional field (default landed) and outlet. What it does with main, and when the rebase conflicts: land.
deps
deps: adds the exact Go dependencies listed in the tickets' deps blocks (go get, then go mod tidy) before work. Config: env_profile must be checks, with optional workspace and execution limits. The blocks are read from the baton's ticket_source only.
human_gate
human_gate: holds the run until an explicit human decision. Config: prompt, optional approved_outlet and rejected_outlet, show (baton paths the card prints), title (baton paths joined with " — " to make the card title), step (a short phrase above the title), and mock_asset (when true, an approved baton's mock html is written under the run's write grant and mock_ref is set). The shipped templates also set approve_label and decision_field.
gather
gather: joins fanned-out branches, and forwards once every configured inlet has received the same number of envelopes. Config: inlets, field (default gathered), outlet and optional exhausted_outlet.
citation_check
citation_check: keeps only the findings sources whose url a researcher's runtime recorded fetching, and splits what is left of the research budget. Config: field (default findings), researchers, budget, budget_field and research_field (default research).
output
output: makes a new snapshot asset from files copied in when the node runs, and reports it in the journal. Config: field (default output) names the baton record, and name, about, name_field, about_field, tags_field, tags, files and announce are defaults or options. See assets.
tool
tool: runs an operator-declared command from harness.json by id. Config: tool (required) and optional outlet. The command, args, env, secrets, timeout, output schema, retries and workspace come from harness.json only, and a template that carries any of them is refused. It shares smith's network. Stdout over 1 MiB is invalid. See harness-json.
command_check
command_check runs the project's checks. It is described on checks.
check_router
check_router routes check results. It is described on checks.
06ticket-completion nodes#
These are the node ids of ticket-completion, in file order (internal/harness/ticket-completion.yaml). quick-fix, mock-first and batch build on the same contract.
ticket_intake
ticket_intake (model, reason): reads the project, phase, ticket and comments, and searches learnings. Returns the ticket context, memory context, constraints and open questions.
intake_proof
intake_proof (capability_assert): requires that intake made its reads, and sends intake back once if it missed rating its search results.
research_route
research_route (switch): sends the baton direct to the plan, or to challenge. It is set to direct.
challenge
challenge (model, reason): challenges the ticket context from first principles. It is reached only when research_route is set to challenge; the shipped file sets direct.
plan
plan (model, inspect): writes the approach and the acceptance list.
deps
deps (builtin): adds the Go dependencies the ticket lists.
work
work (model, work): implements the ticket in the run's workspace.
seal_handoff
seal_handoff (workspace_handoff): seals what work left.
tests_route
tests_route (check_router): routes check results to passed, revise or failed. See checks.
deterministic_checks
deterministic_checks (command_check): runs the project's checks on the sealed handoff. See checks.
review_route
review_route (switch): picks the first reviewer.
review
review (model, inspect): reviews the handoff against the acceptance list.
review2_route
review2_route (switch): sends the baton to a second review, or past it. It is set to off.
review2
review2 (model, inspect): a second review by another model.
review2_decision
review2_decision (router): accepted goes to the gate, otherwise to revise_route.
review_decision
review_decision (router): accepted goes on, otherwise to revise_route.
revise_route
revise_route (router): sends a rejected baton back to work, or to the gate when the reviewer needs a human. After max_false 2 passes it goes to the gate.
human_gate
human_gate: the operator approves and lands it, or sends it back.
land
land (workspace_land): commits the approved handoff.
ticket_close
ticket_close (model, reason): moves the ticket to testing and completes it with the real evidence.
completion_proof
completion_proof (capability_assert): requires exactly one complete_ticket call.
Cords named tests-revise, revise-work and human-revise send work back to work, and are its resume_cords: work resumes its session on them. See tickets.