# hank.json A `hank.json` file is the program a Hankweave run executes. It declares an immutable workflow: a sequence of codons (sealed agent tasks) and loops (repeated branches of codons) that the runner executes in order once the file loads. The root fields around that sequence set up the shared context – editor schema support, environment requirements, global prompt layers, and hank-level overrides – while the `hank` array itself is where the work happens. This page is the field-level reference for that file. It explains what each key accepts, what the loader enforces beyond what an editor can check, and where the surrounding contracts (budgets, loops, sentinels, model routing) are documented. ## How to read this page Use this page to look up the fields accepted in `hank.json`. The tables show the published JSON Schema, including types, required fields, constraints, and schema defaults. The text below each table adds loader behavior that an editor cannot check, such as file existence and model availability. Code blocks come from shipped fixtures and validation captures, so the spellings and diagnostics they show are the ones the runtime actually produces. A `[changed]` or `[since]` marker appears only where the release history identifies a version. Model names in examples come from shipped fixtures. For configuration precedence, see [Hanks](/0.10.0/files/concepts/hanks); for file discovery and `--validate`, see the [CLI reference](/0.10.0/files/reference/cli). The schema's root description still points to the stale URL `https://hankweave.dev/reference/configuration`; use this page instead. ## Choose the hank's root fields A hank is a JSON workflow object. Only `hank` is required, and no fields outside the seven listed below are accepted. The root fields divide into three jobs: editor support (`$schema`), human-facing bookkeeping (`meta`), and run-wide behavior (`requirements`, `overrides`, and the global system prompt fields). | field | type | default | required | constraints | description | | ------------------------ | ------------------------- | ------- | -------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `$schema` | `string` | | no | | JSON Schema URL for editor support | | `meta` | `object` | | no | | Metadata for sharing/indexing (optional) | | `overrides` | `object` | | no | | Architect's overrides (optional) | | `requirements` | `object` | | no | | Requirements that must be met for this hank to run (optional) | | `globalSystemPromptFile` | `string \| array` | | no | | Global system prompt file(s) applied to all codons. Must be relative path(s) inside the hank directory using '/' separators; absolute paths, '..' escapes, and symlinks are rejected. | | `globalSystemPromptText` | `string` | | no | | Global system prompt text applied to all codons | | `hank` | `array` | | yes | minItems 1 | The immutable logic sequence (required) | `$schema` is an optional string for editor support. If it is absent, the runtime writes it back on every startup and during `--validate`, then prints `+ Added $schema to for editor support`. The value is `https://unpkg.com/hankweave@latest/schemas/hank.schema.json`. The schemas are also available from the npm package, so you can wire them into an editor once and get autocomplete and inline validation for every configuration file Hankweave reads. In VS Code, map each file pattern to its schema: ```json { "json.schemas": [ { "fileMatch": ["**/hank.json"], "url": "https://unpkg.com/hankweave@latest/schemas/hank.schema.json" }, { "fileMatch": ["**/hankweave.json"], "url": "https://unpkg.com/hankweave@latest/schemas/hankweave.schema.json" }, { "fileMatch": ["**/*.sentinel.json"], "url": "https://unpkg.com/hankweave@latest/schemas/sentinel.schema.json" } ] } ``` `meta` contains required `name` and `version`, plus optional `description` and `author`. Metadata is for humans: it helps remember what was built six months from now. `requirements` contains `env: string[]`; each declared name is checked fail-fast at startup and during `--validate` by either the direct environment-variable name or its `HANKWEAVE_`-prefixed form. `overrides` contains hank-level settings; precedence is owned by [Hanks](/0.10.0/files/concepts/hanks). `globalSystemPromptFile` is a string or string array of file references. `globalSystemPromptText` is inline text. Supplying both global-system fields is a load error. The global system prompt is prepended before codon `appendSystemPromptFile` or `appendSystemPromptText` content; the parts are joined with a blank line, then receive template replacement and HTML-comment stripping. Global prompts apply the same instruction to every codon, which keeps workflow-wide conventions in one place instead of repeating them in each task prompt. Typical content includes workspace layout, coding standards, domain constraints, and project requirements: | Use Case | Example Content | | ------------------- | ------------------------------------------------------------------------------------------------ | | Workspace layout | "The codebase is a TypeScript monorepo with packages/ for libraries and apps/ for applications." | | Coding standards | "Use functional components. All functions need JSDoc. No console.log in production." | | Domain context | "This is a fintech app. PII must never be logged. All amounts are in cents." | | Project constraints | "The project targets Node 22+. Don't use APIs removed in newer releases." | `overrides` may contain `model`, `dataHashTimeLimit`, `sentinel`, `shimIdleTimeout`, and `budget`. The `sentinel` override carries `enablePersistence`, `healthCheckGracePeriodMs`, and `waitForAllHealthChecks`. `dataHashTimeLimit` is accepted as a positive hank override but is not consumed by the 0.10.0 hashing calls; normal startup omits it when calling the execution setup, and `--validate` uses the built-in 5000-millisecond value directly. Budget allocation belongs to [budgets](/0.10.0/files/concepts/budgets), and config precedence belongs to [Hanks](/0.10.0/files/concepts/hanks); this page does not restate either contract. `hank` is an array with at least one item: the immutable logic sequence whose codon order is fixed when the hank **loads**. Its items are codons – sealed agent tasks – or loops – repeated branches containing codons. An unknown root key is a load error. `strand` is not an alternate root key: only `hank` is legal. A file named `strand.json` is usable only when passed explicitly as a config path, because implicit discovery finds `hank.json` only. \[changed 0.10.0] The published root schema fields were fixed so editors no longer flag `requirements` and `globalSystemPrompt*` as unknown keys. The shipped init fixture shows how these pieces fit together in a real file: the `$schema` and `meta` block at the root, then the first codon of the `hank` array with its prompt file, checkpointed files, and output copy step. ```json { "$schema": "https://unpkg.com/hankweave@latest/schemas/hank.schema.json", "meta": { "name": "My Workflow", "version": "1.0.0", "description": "Generated by hankweave init" }, "hank": [ { "id": "analyze-haiku", "name": "Analyze Project (Haiku)", "model": "haiku", "continuationMode": "fresh", "promptFile": "./prompts/analyze-haiku.md", "checkpointedFiles": ["analysis-haiku.md"], "outputFiles": [ { "copy": ["analysis-haiku.md"] } ] }, … ] } ``` [Hanks](/0.10.0/files/concepts/hanks), [hankweave.json](/0.10.0/files/reference/hankweave-json), and [environment variables](/0.10.0/files/reference/environment-variables). ## Configure one codon A codon describes one sealed agent task. `id`, `name`, `model`, and `continuationMode` are required. You can omit `type`; its schema default is `"codon"`. The full field list follows; the subsections after it group the fields by the three things a codon definition controls: what the model is asked to do, how failures and resource limits are handled, and how files move into, through, and out of the workspace. | field | type | default | required | constraints | description | | ------------------------ | ------------------------- | ------- | -------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `type` | `string` | `codon` | no | = `codon` | Type discriminator - optional, defaults to 'codon' | | `id` | `string` | | yes | minLength 1 | Unique identifier for this codon (e.g., 'codon-1', 'data-analysis') | | `name` | `string` | | yes | minLength 1 | Human-readable name displayed in UI and logs | | `promptFile` | `string \| array` | | no | | Path to a file containing the prompt (mutually exclusive with promptText). Must be a relative path inside the hank directory using '/' separators; absolute paths, '..' escapes, and symlinks are rejected. | | `promptText` | `string` | | no | | Inline prompt text (mutually exclusive with promptFile) | | `appendSystemPromptFile` | `string \| array` | | no | | Path to a file containing system prompt to append (mutually exclusive with appendSystemPromptText). Must be a relative path inside the hank directory using '/' separators; absolute paths, '..' escapes, and symlinks are… | | `appendSystemPromptText` | `string` | | no | | Inline system prompt text to append (mutually exclusive with appendSystemPromptFile) | | `model` | `string` | | yes | minLength 1 | Model to use for this codon. Can be a Claude model ('sonnet', 'opus'), Gemini model ('gemini-2.0-flash-exp', 'flash'), or any other model supported by the configured shim. | | `continuationMode` | `enum` | | yes | `fresh` \| `continue-previous` | How this codon should handle continuation from previous codons. 'fresh': Start a new session (default for most cases). 'continue-previous': Continue from the previous codon's session, maintaining context and conversatio… | | `rigSetup` | `array` | | no | | Rig setup operations to run before codon starts. Each operation must complete successfully for codon to start. | | `description` | `string` | | no | | Optional description shown to users about what this codon does | | `checkpointedFiles` | `array` | | no | | Glob patterns for files to checkpoint during codon execution. These files will be: watched for changes and streamed to the client, tracked in the git-based checkpoint system, and resolved using gitignore rules for consi… | | `env` | `object` | | no | | Optional environment variables to set for the Claude process | | `outputFiles` | `array` | | no | | Optional output copy steps to run after codon completion: files to copy out from a completed codon, with optional pre-copy commands. | | `sentinels` | `array` | | no | | Sentinels to run during this codon. Sentinels are parallel observation agents that process the event stream. Each entry is a wrapper object with sentinelConfig (portable sentinel configuration, file or inline) and setti… | | `archiveOnSuccess` | `array` | | no | | Paths to archive after successful completion. These files/directories are moved to rigArchive/ after the codon completes successfully. Paths are relative to the agent workspace (agentRoot/). Archived files can be restor… | | `onFailure` | `enum` | | no | `abort` \| `retry` \| `ignore` | How to handle codon failure. 'abort' (default): Use existing failure behavior (server stays active for retriable errors, shuts down for non-retriable). 'retry': Automatically retry up to maxAttempts times if the error i… | | `retryConfig` | `object` | | no | | Configuration for retry behavior. Only used when onFailure is 'retry'. Delays grow exponentially from delayMs and are capped at maxDelayMs; when the provider supplies a Retry-After hint, that value is used instead of th… | | `exhaustWithPrompt` | `string` | | no | | Prompt to send when extending codon until context exhaustion. When set, the codon will automatically continue with this prompt after each successful completion until context is exhausted. | | `maxExtensions` | `integer` | `100` | no | > 0 | Maximum number of extensions before forcing completion. Default: 100. Safety valve to prevent infinite extension loops. | | `autoCompact` | `boolean` | | no | | Whether the harness may auto-compact (summarize/trim) the session when the context window fills. Default: false — compaction is disabled, the provider's context-overflow error surfaces instead, plain codons fail at the… | | `shimIdleTimeout` | `integer` | | no | > 0; max 1800 | Max seconds between agent events before the session aborts (idle timeout). Overrides hank-level and runtime defaults. If unset, falls back to hank override, runtime config, or the built-in default (180s for Anthropic mo… | | `budget` | `object` | | no | | | ### Choose prompt and model inputs The published descriptions call `promptFile` and `promptText` mutually exclusive, but the loader behaves differently: at least one is required, both are accepted, and `promptFile` wins when both are present. By contrast, `appendSystemPromptFile` and `appendSystemPromptText` cannot be used together. The loader resolves `model` against the provider registry. An unrecognized name fails at load. See [model resolution](/0.10.0/files/reference/model-resolution) for shortcuts, routing, and `harnessOverride`. The schema's older phrase “configured shim” means the runtime adapter selected for the provider. `continuationMode` accepts `"fresh"` or `"continue-previous"`. See [codons](/0.10.0/files/concepts/codons) for handoff requirements, model matching, and context-exhaustion behavior. ### Control failure and resource limits `onFailure` is the string enum `abort | retry | ignore` and defaults to `abort`. `retryConfig` is accepted only with `onFailure: "retry"`. \[since 0.6.1] A codon `budget` can set `maxDollars`, `maxTimeSeconds`, `maxOutputTokens`, `maxContextTokens`, and `onExceeded: complete | fail`. A codon-level `onExceeded` overrides the hank-level policy. When a measured limit is reached, the budget tracker emits an exceeded event and the runner requests `SIGTERM`. `onExceeded: "complete"` marks that interrupted codon as completed; it does not let the model finish its current reasoning. `onExceeded: "fail"` marks it failed. See [budgets](/0.10.0/files/concepts/budgets) for metering and allocation. \[changed 0.8.0] `autoCompact` defaults to `false`, so the provider's context-overflow error surfaces instead of silent compaction. `shimIdleTimeout` must be a positive integer no greater than 1800. Its fallback is 180 seconds for Anthropic models through the Claude SDK and 120 seconds for other providers through the embedded Pi SDK. An idle-timeout abort is retriable. `exhaustWithPrompt` asks a successfully completed codon to continue until context exhaustion. `maxExtensions`, which defaults to 100, prevents an infinite extension loop. See [codons](/0.10.0/files/concepts/codons) for the complete extension behavior. ### Move files into, through, and out of the workspace `rigSetup` runs before the codon. In a loop, `rigSetup` without `allowFailure: true` produces a warning; `allowFailure` controls whether a failed setup operation fails the codon. `checkpointedFiles` contains glob patterns over the agent workspace and follows gitignore rules. Configuration file references such as `promptFile` are different: they do not use globs or gitignore rules. \[changed 0.9.0] A failure in `outputFiles` copying or `beforeCopy` fails the run. `outputFiles[].copy` is a non-empty list of globs selected from `agentRoot` and copied to the configured output directory. `beforeCopy` commands run in `agentRoot`, including commands whose schema uses `workingDirectory: project`. The published descriptions retain the older `execution directory` and `executionPath` terms. There is no default output directory; see [the runbook](/0.10.0/files/operate/runbook). `archiveOnSuccess` contains file globs relative to `agentRoot`. Matching files move to `rigArchive/` after success and can be restored during rollback. See [execution directory](/0.10.0/files/reference/execution-directory) for the archive layout. `sentinels` attaches event observers to the codon without changing how the codon itself executes. Each entry is a wrapper object containing `sentinelConfig`, either a file reference or inline object, plus optional codon-scoped `settings`: `failCodonIfNotLoaded`, `outputPaths.logFile`, `outputPaths.lastValueFile`, and the `lifecycle`, `errors`, `outputs`, and `triggers` switches under `reportToWebsocket`. See [sentinel configuration](/0.10.0/files/reference/sentinel-config) for the full contract. The `env` object sets variables for the agent process. Its generated schema description retains the older phrase “Claude process.” The anchor fixture demonstrates a three-step `rigSetup`: create `pipeline`, copy `rigs/preflight.ts` to `pipeline/preflight.ts`, and run `bun pipeline/preflight.ts`. The init fixture provides the codon spelling and model examples used here; its visible excerpt is in the root-key entry above. The anchor fixture shows the sentinel wrapper shape – a single `sentinelConfig` file reference – without retyping the sentinel's own configuration: ```json "sentinels": [ { "sentinelConfig": "sentinels/quality-observer.json" } ], … ``` [Codons](/0.10.0/files/concepts/codons), [model resolution](/0.10.0/files/reference/model-resolution), [sentinel configuration](/0.10.0/files/reference/sentinel-config), and the [runbook](/0.10.0/files/operate/runbook). ## Repeat codons with a loop A loop repeats one or more codons until its termination condition is met. `type`, `id`, `name`, `terminateOn`, and `codons` are required, and `type` must be `"loop"`. | field | type | default | required | constraints | description | | ------------------ | ----------------------------------- | ------- | -------- | ----------- | ------------------------------------------------------------------------------------- | | `type` | `string` | | yes | = `loop` | Type discriminator - required for loops | | `id` | `string` | | yes | minLength 1 | Unique identifier for this loop | | `name` | `string` | | yes | minLength 1 | Human-readable name displayed in UI and logs | | `description` | `string` | | no | | Optional description shown to users | | `terminateOn` | `iterationLimit \| contextExceeded` | | yes | | Termination condition for the loop | | `codons` | `array` | | yes | minItems 1 | Array of codons to execute in each iteration | | `budget` | `object` | | no | | Budget scope for this loop. | | `archiveOnSuccess` | `array` | | no | | Paths to archive when the loop terminates. Paths are relative to the agent workspace. | `terminateOn` is an object variant: it accepts either `iterationLimit` with an integer `limit` of at least 1, or `contextExceeded`. Termination semantics belong to [loops](/0.10.0/files/concepts/loops). `codons` contains plain codons only, with at least one item; nested loops are not supported in v1. Loop and hank `overrides` budgets share `{maxDollars, maxTimeSeconds, allocation: shared | proportional | proportional-strict, shares: Record, onExceeded}`. `allocation` defaults to `shared`; codon budgets additionally carry token caps. A loop-level `archiveOnSuccess` archives its paths once, when the loop **terminates**, relative to the agent workspace. A `contextExceeded` loop containing any `continuationMode: "fresh"` codon is a fatal load error. Inside a loop, a `continue-previous` codon whose model differs from the preceding codon is a fatal load error. Duplicate codon IDs are fatal globally and within a loop; duplicate codon names produce a warning. The checked loop fixture below shows the structure in full: one loop wrapping two codons (`append-a` and `append-b`), bounded by `iterationLimit: 2`. Both codons checkpoint `log.txt` so its state carries across iterations, and the second codon copies it out through `outputFiles`. The terminal capture under the fixture shows how `--validate` reports the result: the workflow summary counts the codons and the loop separately ("2 codons • 1 loop"). ```json { "$schema": "https://unpkg.com/hankweave@0.10.0/schemas/hank.schema.json", "meta": { "name": "Minimal loop", "version": "1.0.0", "description": "Two haiku codons inside one loop bounded by iterationLimit 2." }, "hank": [ { "type": "loop", "id": "append-loop", "name": "Append loop", "terminateOn": { "type": "iterationLimit", "limit": 2 }, "codons": [ { "id": "append-a", "name": "Codon A appends", "model": "haiku", "continuationMode": "fresh", "promptFile": "./prompts/append-a.md", "checkpointedFiles": [ "log.txt" ] }, { "id": "append-b", "name": "Codon B appends", "model": "haiku", "continuationMode": "fresh", "promptFile": "./prompts/append-b.md", "checkpointedFiles": [ "log.txt" ], "outputFiles": [ { "copy": [ "log.txt" ] } ] } ] } ] } ``` ```text ✓ Configuration is valid! ╭──────────────────────────────────────────────────────────────────────────────╮ │ Minimal loop v1.0.0 │ │ 2 codons • 1 loop │ ╰──────────────────────────────────────────────────────────────────────────────╯ ``` [Loops](/0.10.0/files/concepts/loops) and [budgets](/0.10.0/files/concepts/budgets). ## Keep file references inside the hank directory Configuration file references must be relative to the directory containing `hank.json`, use `/` as the separator, remain inside that directory, and avoid symlinks. For example, `"prompts/summarize.md"` is portable. `"/etc/hosts"`, `"..\prompts\summarize.md"`, and `"../../shared/summarize.md"` fail validation. Not every path in a hank follows that rule, because fields anchor to two different roots. Authoring-time references (`promptFile`, global prompt files, rig sources) resolve against the hank directory, which is fixed when the file loads. Execution-time references (`checkpointedFiles`, `outputFiles`, `archiveOnSuccess`, rig targets) resolve against the agent workspace (`agentRoot`), which exists only at runtime. Use this table to choose the correct base for each field: | Field | Base | Extra rules | | ---------------------------------------------------------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- | | `promptFile`, `appendSystemPromptFile`, `globalSystemPromptFile` | hank directory | Relative `/` spelling; contained and symlink-free | | String `sentinelConfig` | hank directory | Its internal file refs use the config file's directory \[changed 0.10.0] | | Sentinel-config internal refs | config file's directory | Hank directory remains the containment anchor \[changed 0.10.0] | | `rigSetup.copy.from` | hank directory | Copy-tree scan; cannot name the hank directory itself | | `rigSetup.copy.to` | agent workspace (`agentRoot`) at runtime | Published schema/validator use `projectPath` / `executionPath`; full target path, including its final name | | `checkpointedFiles` | agent workspace | Glob patterns use gitignore rules | | `outputFiles[].copy` | agent workspace (`agentRoot`) → output directory | Non-empty glob list; the published schema says “execution directory”; destination behavior belongs to the runbook | | `archiveOnSuccess` | agent workspace | Paths move to `rigArchive/` after success | | Template variables | `agentRoot` | `<%DATA_DIR%>` resolves below the read-only data mount | Absolute paths, drive-qualified paths such as `C:`, backslashes, NUL characters, and paths that leave the hank directory are rejected. A spelling that leaves and then re-enters the directory is also rejected. The loader rejects the first symlink below the hank directory. A symlink in the path leading to the hank itself does not count, but a symlinked directory inside the hank does. \[changed 0.10.0] These rules apply to `promptFile`, `appendSystemPromptFile`, `globalSystemPromptFile`, `rigSetup.copy.from`, and string `sentinelConfig` values. Within a file-based sentinel configuration, `systemPromptFile`, `userPromptFile`, and `structuredOutput.schemaFile` resolve from that configuration file's directory while still remaining inside the hank directory. For `rigSetup.copy.from`, validation scans the whole source tree before the codon starts. It rejects symlinks, including dangling ones, and non-regular files such as FIFOs, sockets, and devices. It reports entries in a consistent sort order. `copy.from` also cannot name the hank directory itself, including through `.` or `sub/..`. These checks are \[changed 0.10.0]. At runtime, `rigSetup.copy.to` is joined to `agentRoot`. The published schema and validator use the older `projectPath` and `executionPath` terms. Supply the full target path, including the final file or directory name; that target can rename a copied file or directory. Validation checks spelling and containment before probing whether a path exists, so it never touches a forbidden path. It collects all reference violations before reporting them. Referenced files must be regular files, so a FIFO is rejected before any read could block. The exact path-violation messages use these forms: | Problem | Diagnostic | | -------------------------------------- | ------------------------------------------------------------------------------------------------------------- | | Absolute or drive-qualified | `"" is an absolute or drive-qualified path; hank refs must be relative paths inside the hank directory` | | Backslash | `"" contains a backslash; hank refs use "/" as the only path separator` | | NUL character | `"" contains an invalid character (NUL)` | | Leaves the hank directory | `"" resolves outside the hank directory (); move the file into the hank directory` | | Path crosses a symlink | `"" passes through a symlink at ""; symlinks are not allowed in hank refs` | | Copied tree contains a symlink | `"" contains a symlink at ""; symlinks are not allowed anywhere in a copied tree` | | Copied tree contains another file type | `"" contains a non-regular file at ""; only regular files and directories can be copied` | The captures below show those messages as `--validate` emits them. Each one pinpoints a different failure: a path that climbs out of the hank directory, a reference to a file that does not exist, an absolute path, and a backslash separator. All four exit with code 1. The absolute path in the missing-file diagnostic is fixture output, not a path to copy into a hank. ```text Validation failed: … • - Codon "Write one line" (write-line) - promptFile: "../../minimal-single-provider/prompts/summarize.md" resolves outside the hank directory; move the file into the hank directory exit=1 ``` ```text Validation failed: … • Codon 1 (write-line): promptFile "/fixtures/scenarios/ref-violations/prompts/does-not-exist.md" does not exist exit=1 ``` ```text Validation failed: … • - Codon "Write one line" (write-line) - promptFile: "/etc/hosts" is an absolute or drive-qualified path; hank refs must be relative paths inside the hank directory exit=1 ``` ```text Validation failed: … • - Codon "Write one line" (write-line) - promptFile: "prompts\write-one-line.md" contains a backslash; hank refs use "/" as the only path separator exit=1 ``` The anchor fixture's `normalize-aster` codon shows the `command` and `copy` operation shapes that these rules apply to: ```json "rigSetup": [ { "type": "command", "command": { "run": "mkdir -p pipeline" } }, { "type": "copy", "copy": { "from": "rigs/preflight.ts", "to": "pipeline/preflight.ts" } }, { "type": "command", "command": { "run": "bun pipeline/preflight.ts" } } ], … ``` > **VersionNote:** Version 0.10.0 hardened hank references: paths use portable POSIX spellings, cannot climb above the hank root, cannot pass through symlinks, and include copy-tree checks; file-based sentinel references now resolve from each config file's directory. Hanks from 0.9.x that use absolute or climbing paths must move those files inside the hank directory. [Rigs](/0.10.0/files/concepts/rigs), [execution directory](/0.10.0/files/reference/execution-directory), and [first-run failures](/0.10.0/files/start/first-run). ## Refer to workspace paths in prompts Prompt text cannot know the absolute workspace path in advance. Use one of these variables; Hankweave replaces it when the codon loads the prompt: | Variable | Resolution | | ------------------- | -------------------------------------------------------------------------------------------------------- | | `<%AGENT_ROOT%>` | The canonical, recommended agent workspace | | `<%PROJECT_DIR%>` | Silent alias of `AGENT_ROOT` | | `<%EXECUTION_DIR%>` | Silent alias of `AGENT_ROOT` | | `<%DATA_DIR%>` | `/read_only_data_source`, the linked or copied input data, treated as read-only by convention | Replacement applies to user prompts, `exhaustWithPrompt`, and system prompts. It does not apply to configuration path fields such as `archiveOnSuccess`. Hankweave also strips HTML comments from prompt content in this pass. See [authoring prompts](/0.10.0/files/author/prompts) for prompt-writing guidance. [Authoring prompts](/0.10.0/files/author/prompts) and [execution directory](/0.10.0/files/reference/execution-directory). ## Fix unknown field names When the loader recognizes a likely typo, it reports `Unknown field "x". Did you mean "y"?`. The table below maps the misremembered or deprecated names it recognizes to the fields you should use instead: | If you wrote | Use | | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | | `systemPromptFile`, `systemPromptText`, or `systemPrompt` | `appendSystemPromptFile`, `appendSystemPromptText`, or one of those two fields | | `prompt`, `prompts`, or `promptFiles` | `promptFile` or `promptText` as suggested by the diagnostic | | `trackedFiles`, `tracking`, `tracked`, `watchedFiles`, or `fileTracking` | `checkpointedFiles` | | `rig`, `setup`, or `preSetup` | `rigSetup` | | `archiveRigs`, `rigTeardown`, `teardown`, `archive`, `cleanup`, `archiveRig`, `archiving`, or `archives` | `archiveOnSuccess` | | `environment` or `envVars` | `env` | | `outputs` or `output` | `outputFiles` | | `continuation` or `mode` | `continuationMode` | | `costLimit`, `maxBudget`, `maxCost`, or unnested `maxDollars` | `budget.maxDollars` | | `maxDuration`, `maxDurationSeconds`, unnested `maxTimeSeconds`, or `timeLimit` | `budget.maxTimeSeconds` | | `maxTokens`, unnested `maxOutputTokens`, or `tokenLimit` | `budget.maxOutputTokens` | An unknown field outside the map lists valid fields for its position: root, codon, or loop. A root-level codon field also receives a hint to move it inside a codon in the `hank` array. Loop bodies are checked as nested positions. The capture shows the diagnostic as `--validate` reports it: a codon using the old `trackedFiles` name fails with exit code 1 and a pointer to `checkpointedFiles`. ```text Validation failed: … • - Codon "Write one line" (write-line) - trackedFiles: Unknown field "trackedFiles". Did you mean "checkpointedFiles"? exit=1 ``` [CLI `--validate`](/0.10.0/files/reference/cli) and [errors and exit codes](/0.10.0/files/reference/errors-and-exit-codes). ## Decide whether a load message blocks the run Load errors stop the hank. Warnings do not: startup prints them under `! Configuration warnings:` after the hank structure and budget table. `--validate` presents them under `Warnings:` and still exits with code 0, so a validated file can carry actionable advice without failing. Errors include a missing prompt source, an invalid `retryConfig`, incompatible continuation settings, duplicate IDs, a forbidden `copy.from`, missing or unreadable files, invalid sentinel configurations, and failed self-tests. After a hank loads, model-based extraction can still fail like any other model task; its `onFailure` value controls what happens next. Configuration warnings cover valid but suspicious choices in four areas: | Area | Warning conditions | | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | Names and loops | Duplicate codon names; loop codons with `rigSetup` but without `allowFailure: true`; loop codons relying on the `onFailure: abort` default | | Prompt files | Empty files or files larger than 1 MB | | Rigs | Existing copy targets and dangerous command patterns, including root or home deletion, raw disk writes, formatting, and Windows recursive deletion | | Continuation | A first codon using `continue-previous`; continuation from a codon with no checkpointed files; `onFailure: ignore` followed by `continue-previous` | Budget preflight adds its own warnings when a limit cannot work as configured or may produce a surprising result: | Area | Warning conditions | | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Proportional allocation | A hank- or loop-scoped child cap exceeds its allocation; shares leave money unallocated with no unshared codon to receive it; a codon starts with zero effective budget | | Interruption and retries | `exhaustWithPrompt` is subject to a time budget; `onExceeded: "fail"` is combined with `onFailure: "retry"` | | Shared pools | A later codon uses `onExceeded: "fail"` but an earlier codon may exhaust the pool | | Model and time limits | A dollar-limited model has no pricing data; a codon time cap exceeds its loop's cap | Self-tests run on every startup, not only during `--validate`, once for each unique `harness:provider/model` identity. Here, `harness` is the selected runtime adapter. Self-test notices can appear with configuration warnings, but a failed self-test aborts configuration loading with category-specific guidance. See [authentication and models](/0.10.0/files/operate/authentication-and-models) for the two model-selection planes. The capture below demonstrates the distinction: the hank validates successfully and exits with code 0, yet the validator still warns that codon 2 continues from a previous codon that checkpoints no files – a handoff that will run but may not carry the state the author expected. ```text ✓ Configuration is valid! … Warnings: - Codon 2 (write-second): Continues from previous codon "write-line" doesn't checkpoint any files exit=0 ``` [CLI `--validate`](/0.10.0/files/reference/cli), [errors and exit codes](/0.10.0/files/reference/errors-and-exit-codes), and [authentication and models](/0.10.0/files/operate/authentication-and-models). ## Why an editor-valid file can still fail at load A hank file can pass the editor's JSON Schema check and still fail when the loader loads it because the published schema is deliberately looser than runtime validation. The editor verifies shape; the loader verifies that the workflow can actually run. The loader adds three layers of checks that the published schema does not cover: 1. Its runtime schema validator checks prompt presence, system-prompt exclusivity, `retryConfig`, model resolution, path spelling, and whether a path remains inside the hank directory. 2. Filesystem-aware checks reject missing files, symlinks, special files, unsafe copied trees, and invalid field combinations. 3. Startup checks enforce `requirements.env`, run model self-tests, and verify catalog availability. An editor cannot establish whether a path exists or crosses a symlink. It also cannot know the directory of a referenced sentinel configuration. For that reason, spelling and containment checks begin in the runtime schema validator, while filesystem checks happen in the loader. References inside a file-based sentinel configuration receive only the portable-spelling check until the loader knows that file's location. At config load, Pi – Hankweave's embedded runtime SDK – runs the `model_catalog` preflight to check whether a registry-known model is servable by that runtime. A miss fails before earlier codons spend money and lists models available for that provider. Run [CLI `--validate`](/0.10.0/files/reference/cli) to apply these checks before execution. See [errors and exit codes](/0.10.0/files/reference/errors-and-exit-codes) for outcomes and [model resolution](/0.10.0/files/reference/model-resolution) for catalog behavior. ## Find related configuration This page defines `hank.json` fields. The surrounding configuration is documented here: * [CLI](/0.10.0/files/reference/cli): `--validate` and configuration discovery * [hankweave.json](/0.10.0/files/reference/hankweave-json): runtime configuration * [sentinel configuration](/0.10.0/files/reference/sentinel-config): sentinel fields * [model resolution](/0.10.0/files/reference/model-resolution): model routing * [environment variables](/0.10.0/files/reference/environment-variables): variable names * [execution directory](/0.10.0/files/reference/execution-directory): archive layout * [Hanks](/0.10.0/files/concepts/hanks): configuration precedence * [Runbook](/0.10.0/files/operate/runbook): output destinations For the concepts behind the fields, see [codons](/0.10.0/files/concepts/codons), [loops](/0.10.0/files/concepts/loops), [rigs](/0.10.0/files/concepts/rigs), [sentinels](/0.10.0/files/concepts/sentinels), and [budgets](/0.10.0/files/concepts/budgets).