Agent Cookbook
After reading: you'll know which docs to fetch first, what the typed Rust SDK gives an agent over an untyped boundary, how to drive vesl-test watch for closed-loop feedback, and which failure modes are recoverable in-loop vs. need human review.
This page is the working companion to Orientation, which names what's published. Orientation tells you the artifacts exist; this page tells you how to use them.
Ingestion Order
Three fetches cover most agent tasks:
/llms.txtfirst. The index lists every page with a one-line description. Fetching it once tells the agent the shape of the guide.- Per-page
.mdmirrors as needed./setup/quickstart.md,/build/hull.md, etc. — fetch only what the task requires. One page costs one page of context. /llms-full.txtfor bulk ingestion. The whole guide concatenated in sidebar order. Use when the task spans the docs surface; prefer per-page fetches otherwise.
For source-level questions, the canonical repos are linked from every page that names a primitive. SHA-pinned cross-references in the docs (e.g. vesl-core at 11d110d, vesl-nockup at 6e2127c) point at the exact snapshot the docs were written against. When the agent's checkout is newer, the source is authoritative.
What the Typed Surface Gets You
The Rust SDK at the kernel boundary is typed at every seam. An agent driving it gets feedback shapes that an untyped boundary would have to discover at runtime:
PokeOutcomeenum. Everyapp.poke(...)returns one ofAccepted { effects } | Rejected { reason } | Crashed { error }. The agent matches on the variant; an unhandled variant is a compile error, not a silent miss.assert_kernel_cause_tag!at compile time. With drift-detection codegen wired (see Hull → Hull/Kernel Drift Detection), a typo in a cause tag failscargo build, not at runtime as a silentOk(vec![]). Wirenockup graft codegen kernel-cause-tagsfrombuild.rsto opt in.- Codegen-driven harness methods.
nockup graft codegen harness-methodsgenerates typedGraftTestHarness::<verb>(...)methods fromharness-bindings.toml. A rename in either the manifest or the binding surfaces as a codegen-time error. build_*_pokebuilders. One per cause; the canonical 14-graft surface is on Grafts — Per-Graft Rust Snippets. Each takes typed Rust primitives and returns aNounSlab. The agent doesn't construct nouns by hand.
The typed surface compresses the agent's feedback loop. Where an untyped poke surfaces a problem as Ok(vec![]) with no effects (silent), the typed shape fails cargo build or returns a concrete PokeOutcome::Rejected variant the agent can branch on.
Closed-Loop Development
vesl-test watch streams effects from a running kernel, which makes for a tight read-eval-print loop:
- Start the loop. Boot the kernel via
cargo run, then in a second terminal:vesl-test watch. The watch stream emits one line per effect. - Poke and observe. Drive a poke through the hull (or via the Serve arm's HTTP routes). The watch stream prints each emitted effect as it lands.
- Branch on the effect. Success effects (e.g.
%settle-noted) confirm the path. Error effects (e.g.%settle-error msg=@t) carry the rejection reason as a cord. - Iterate. Edit Hoon, recompile, restart. State survives via PMA-resume. Boot drops from ~15s cold to ~1s warm.
For a one-shot inspection without watch, vesl-test inspect peek <path> returns the current value at a peek path. Full surface: Testing / CLI.
Recommended File Reads Per Task
Different tasks lean on different pages. A short map:
- "Scaffold a new nockapp." Start at Setup / Quickstart. The three-command flow there scaffolds, composes, and boots a kernel.
- "Add a new poke verb." Kernel / Adding a Domain Cause walks state field + cause variant + arm body for a single domain cause. The denial-shape paragraph at the end is load-bearing — bare
?>crashes the kernel where an explicit branch returns a typed rejection. - "Read state without a poke." Kernel / Adding a Domain Peek walks the
(unit (unit *))return convention and the peek chain. - "Swap the verification gate." Kernel / Replacing a Verification Gate covers the five named gates in
vesl-gates.hoonand the[graft.gates]manifest line. - "Wire two grafts in one arm." Kernel / Coordinating Multiple Grafts in One Arm walks the
apply-<graft>wet-gate pattern fromdomain-patterns. - "Run a server in production." Build & Run / Serve Subcommand for flags, auth, and
/statusshape; Build & Run / Production Checklist for the pre-ship walk. - "Investigate a runtime issue." Troubleshooting / Common Pitfalls names every footgun in the symptom-first format: what you see, what's happening, the fix.
Graft Selection
The 14 shipped grafts cluster by family. A short selection guide:
- Commitment (
settle,mint,guard,forge) — pick by lifecycle.settlefor the full register/verify/note cycle with replay protection.mintfor one-shot root binding without verification.guardfor hash-leaf inclusion checks.forgefor STARK proofs over committed data. - State (
kv,counter,queue,rbac,registry) — pick by access shape.kvfor key-value,counterfor atomic increments,queuefor FIFO,rbacfor permission grants,registryfor structured records. - Behavior (
validate,log,clock,batch) — pick by wrap point.validatefor pre-?--switch input rules.logfor append-only audit.clockfor deterministic timestamps.batchfor settlement-flush bundling. - Intent (
intent-graft) — placeholder, no builder. Causes crash on invocation until upstream lands.
The full taxonomy with priority bands lives on Grafts. Per-graft Rust snippets — one realistic poke per graft — live on Grafts — Per-Graft Rust Snippets.
Common Failure Modes
A short catalog of failure shapes an agent will see, with the recovery path:
Ok(vec![])fromapp.poke(...). No effects came back. Likely causes: an unknown cause tag (drift detection opt-out), a kernel crash via?>(bare assertion on user input — see Kernel / Causes — Denying a Cause Without Crashing), or amule-trapped panic in a graft body. Wire drift detection, refactor?>to?:/?.branching, and grepvesl-test watchoutput formote=Exittraces.- Compile error
cause tag <X> not in KERNEL_CAUSE_TAGS. Drift detection caught a rename. Either update the hull's poke builder call site to match the kernel's renamed tag, or rerunnockup graft codegen kernel-cause-tagsafter a manifest edit. Full surface: Hull → Hull/Kernel Drift Detection. Rejected::RbacDeniedfrom a peek-then-poke gate. The caller's pubkey lacks the requested permission. The peek-then-poke pattern returns a typed rejection without sending the downstream poke. Full surface: Hull → Peek-Then-Poke Gating.verify-jamreports stale.out.jampredates the last Hoon source edit. Re-run./compile.sh. The fingerprint covers both manifest TOMLs and library.hoonfiles; either surface changing triggers staleness./healthreturns 503 with"stage":"booting". The hull hasn't finished kernel boot. Cold boot is ~15s; PMA-resume is ~1s. Wait or wirereadinessProbeto the 200.
Failure modes with error: prefix from nockup graft inject --apply are gating lints — they refuse the write. Each one names a silent-fail surface in the composer or hoonc. See Inject Lints for the per-lint shape.
Stuck?
Something broken? The breakage is probably already in Common Pitfalls.
See Also
- Orientation — what's published in machine-readable form.
- Grafts — Per-Graft Rust Snippets — one canonical poke per graft.
- Hull — typed Rust surface, drift detection, peek-then-poke gating.
- Testing / CLI —
vesl-test watchfor closed-loop feedback. - Common Pitfalls — symptom-first failure mode catalog.