# Sentinel configuration reference
A sentinel observes a running codon from the outside. While a codon (a sealed unit of agent work) executes, the sentinel watches the event stream, batches matching events into language-model calls, and writes a report. This page is the lookup reference for the JSON configuration that controls all of that: which events to match, when to call the model, what the prompt sees, and where the output goes.
The configuration lives in a hank directory, the folder containing the hank's JSON configuration, `hank.json`, including its `meta`, `overrides`, and `hank` array. Sentinel configurations are attached to individual codons from that file, either as file references or inline objects; the attachment mechanics are at the end of this page, after the field reference.
The sections follow the order you will usually need them: the top-level fields first, then triggers and execution strategies, then prompts, output, error handling, and finally the codon wrapper and the list of events that can actually reach a sentinel. Each table is generated from the published schema; the prose around it records the runtime behavior that a schema cannot express, including several checks that happen at load time or first call rather than at validation.
## Schema fields and runtime checks
Use the tables to look up types, required fields, and bounds from the published `sentinel.schema.json` (docs.lock hash `63b4609a…`). The text below them covers runtime checks that JSON Schema cannot express. Version markers identify when a field changed.
Two publication details are worth knowing before you rely on the schema in an editor. The published schema description still links to `https://hankweave.dev/reference/sentinel-config`; use [Sentinel configuration](/0.10.0/files/reference/sentinel-config) instead. And the runtime sentinel parser is strict and does not declare a `$schema` property. The published `$schema` row is editor metadata, so associate the schema in the editor rather than placing `$schema` inside a sentinel configuration.
## Define top-level fields
A sentinel configuration is a strict object with 18 published properties. `id`, `name`, `trigger`, `execution`, and `model` are required; other keys are rejected.
| field | type | default | required | constraints | description |
| ------------------- | ---------------------------------------------- | ------- | -------- | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id` | `string` | | yes | minLength 1; pattern `^[a-z0-9-]+$` | |
| `name` | `string` | | yes | minLength 1 | |
| `description` | `string` | | no | | |
| `trigger` | `event \| sequence` | | yes | | |
| `execution` | `immediate \| debounce \| count \| timeWindow` | | yes | | |
| `systemPromptFile` | `string \| array` | | no | | System prompt file(s), relative to this config file's directory (or the hank directory for inline configs), using '/' separators. Must stay inside the hank directory; absolute paths and symlinks are rejected. |
| `systemPromptText` | `string` | | no | | |
| `userPromptFile` | `string \| array` | | no | | User prompt file(s), relative to this config file's directory (or the hank directory for inline configs), using '/' separators. Must stay inside the hank directory; absolute paths and symlinks are rejected. |
| `userPromptText` | `string` | | no | | |
| `conversational` | `object` | | no | | |
| `errorHandling` | `object` | | no | | |
| `llmParams` | `object` | | no | | |
| `model` | `string` | | yes | | The full model ID to use (e.g., "anthropic/claude-3-5-sonnet-20241022", "openai/gpt-4-turbo"). |
| `structuredOutput` | `object` | | no | | |
| `joinString` | `string` | | no | | String to join entries in text-based log file. Only valid for text output. Supports escape sequences: \n (newline), \t (tab), \r (carriage return), \ (backslash). Defaults to '\n---\n' for visual separation. |
| `reportToWebsocket` | `object` | | no | | |
| `output` | `object` | | no | | |
| `$schema` | `string` | | no | | JSON Schema URL for editor support |
Most of these fields behave as the table suggests; `id` and `model` carry extra runtime rules. `id` uses lowercase letters, numbers, and hyphens, and duplicate IDs in one codon are rejected at load.
The `model` field decides whether the sentinel can run at all, and the check depends on the form of the ID. The schema describes `model` as a full model ID. For a slash-containing model, a missing registry entry, an unconfigured provider, or a failed or pending provider health check causes the sentinel to be skipped with an info-level `Skipping sentinel : …` message; the codon proceeds. A slash-less short name such as `haiku` skips that load-time gate: the sentinel loads and fires, then always fails its first LLM call with `llm-call-failed: No LLM provider available`, because only slash-containing full model IDs receive a provider call.
A captured quality-observer run used `anthropic/claude-haiku-4-5` and produced a report. That report is an event-observer result: it can summarize the completion event it received, but it cannot verify artifact existence, row coverage, or artifact correctness without corresponding event data. Model shortcuts and model-selection planes are documented in [model resolution](/0.10.0/files/reference/model-resolution) and [authentication and models](/0.10.0/files/operate/authentication-and-models). [AWS Bedrock](/0.10.0/files/reference/aws-bedrock) covers sentinel credentials. The general path/ref contract belongs to [hank.json](/0.10.0/files/reference/hank-json); this page only states sentinel-specific reference bases.
## Match events with triggers
The required `trigger` field decides which events the sentinel cares about. It is a discriminated union with an `event` form (match individual events, optionally filtered by conditions) and a `sequence` form (match an ordered pattern across the event history).
| field | type | default | required | constraints | description |
| ------------------ | ---------------------------------------------------------- | ------- | -------- | ------------------- | ----------- |
| `event` | `object` | | | `type` = `event` | |
| ↳ `on` | `array` | | yes | minItems 1 | |
| ↳ `conditions` | `array` | | no | | |
| `sequence` | `object` | | | `type` = `sequence` | |
| ↳ `interestFilter` | `object` | | yes | | |
| ↳ ↳ `on` | `array` | | yes | minItems 1 | |
| ↳ `pattern` | `array` | | yes | minItems 1 | |
| ↳ `options` | `object` | | no | | |
| ↳ ↳ `consecutive` | `boolean` | | no | | |
Both forms are validated against the live runtime, not just the schema. Every named event type in `on` is checked against the live `serverEventTypes` list at load. Condition paths use dot notation into `event.data`, such as `exitStatus.type`, and are checked against the named event type's data shape; that path check is skipped when `on` contains `*`. Conditions in one array are AND-ed, and a missing path evaluates to `undefined` and does not match. The eight operators are `equals`, `notEquals`, `in`, `notIn`, `contains`, `matches`, `greaterThan`, and `lessThan`; `equals` and `notEquals` take a string, number, boolean, or `null`; `in` and `notIn` take a non-empty array of strings or numbers; `contains` and `matches` take strings; and `greaterThan` and `lessThan` take numbers.
The sequence form adds state. A sequence keeps an in-memory history of interest-filtered events capped at 1000 per sentinel and tracks the last trigger position to avoid duplicate matches. `options.consecutive` defaults to `true`: consecutive matching must reach the exact history tail, while `false` matches pattern steps greedily with gaps allowed. Wildcards are accepted in the interest filter and pattern-step types. This history cap is separate from the template and queue caps below.
## Batch events with execution strategies
Matching an event does not call the model directly. The required `execution` field controls when matched events become LLM calls, so a sentinel can react to every match or accumulate matches into batches.
| field | type | default | required | constraints | description |
| ---------------- | --------- | ------- | -------- | ------------------------- | ----------- |
| `immediate` | `object` | | | `strategy` = `immediate` | |
| `debounce` | `object` | | | `strategy` = `debounce` | |
| ↳ `milliseconds` | `integer` | | yes | > 0; max 300000 | |
| `count` | `object` | | | `strategy` = `count` | |
| ↳ `threshold` | `integer` | | yes | > 0; max 1000 | |
| `timeWindow` | `object` | | | `strategy` = `timeWindow` | |
| ↳ `milliseconds` | `integer` | | yes | > 0; max 3600000 | |
`immediate` queues one batch per match. `debounce` accumulates matches until a quiet-period timer fires. `count` queues at its threshold. `timeWindow` queues on a periodic schedule.
Batching interacts with a bounded queue. Each sentinel processes its trigger queue serially, so new matches wait while an item is processed. The queue is capped at 100 triggers and 10000 total events. When either cap is reached, the oldest trigger is dropped with an info-level log; once the queue passes 70% of the trigger cap, it logs `[Sentinel:] Queue backpressure: /100 triggers queued` at info level. At codon completion, pending accumulated events are flushed and the queue drains before the codon is considered done. [Sentinel concepts](/0.10.0/files/concepts/sentinels) covers the observer lifecycle and drain semantics.
## Prompts and template context
Once a batch fires, the prompts decide what the model actually sees. A sentinel must define at least one of `userPromptFile` and `userPromptText`. Supplying both is accepted: file content is assembled first and text is appended, so these fields are not an XOR pair. Prompt-file fields accept a string or an array of strings; array entries concatenate in order. File-based references resolve from the directory containing that sentinel configuration, while inline configurations resolve from the hank directory. In 0.10.0, `systemPromptFile`, `userPromptFile`, and `structuredOutput.schemaFile` use each file configuration's own directory instead of the first configuration's directory. Escape and symlink (filesystem-link) checks run when the codon starts and again on cache hits.
Prompts are Eta templates with caching enabled and `autoEscape: false`, so rendered text is raw. The available context is:
| Context property | Meaning |
| ---------------------- | --------------------------------------------------- |
| `it.events` | Triggering events, capped at the first 1000 events |
| `it.codon.id` | Current codon ID |
| `it.codon.name` | The sentinel configuration's `name` |
| `it.codon.description` | The sentinel configuration's optional `description` |
| `it.codon.startTime` | Time the sentinel run started |
| `it.world.currentTime` | Trigger queue time |
Three properties of this context trip people up. `it.world.currentTime` is `trigger.queuedAt`, not template-execution time. Templates execute synchronously and cannot be interrupted, so keep them lightweight and avoid complex computation or infinite loops. And `it.timestamp` and `it.context` are not part of the context.
Most importantly, event data reaches the model only when the template interpolates it; a prompt without `<%= it.events %>` receives no event data. The sweep capture demonstrates both cases: an untemplated prompt produced a no-events response, while the Eta-templated prompt reported the received `codon.completed` event. The captured report is shown first; the event stream follows.
*Templated sweep report.*
```
---
# Sweep Report
1. Received 1 event of type `codon.completed`.
2. Codon `step-two` completed successfully with a cost of $ and duration of ms.
3. Sweep: clean
```
The captured event stream is available here. Note the `sentinel.output` entry from the untemplated run: the model explicitly reports that no event data was provided, which is what a missing `<%= it.events %>` interpolation looks like from the outside.
*Captured sentinel event stream.*
```
{"id":"","timestamp":"","type":"codon.completed","data":{"codonId":"step-one","success":true,"cost":"","duration":"","exitStatus":{"type":"success"}}}
{"id":"","timestamp":"","type":"codon.completed","data":{"codonId":"step-two","success":true,"cost":"","duration":"","exitStatus":{"type":"success"}}}
{"id":"","timestamp":"","type":"sentinel.triggered","data":{"sentinelId":"sweep-observer","codonId":"step-two","triggerNumber":1,"strategy":"immediate","eventCount":1,"queueSize":0}}
{"id":"","timestamp":"","type":"sentinel.output","data":{"sentinelId":"sweep-observer","codonId":"step-two","triggerNumber":1,"outputType":"text","content":"I don't see any events in your message. You've described a scenario involving codon completion events and asked me to write a sweep report, but no actual event data has been provided for me to analyze.\n\nTo write the three-line report you've requested, I would need to see the events themselves. Could you please share:\n\n- The event log or event stream from the two-codon run\n- Details about each `codon.completed` event (success/failure status, costs if applicable)\n\nOnce you provide the events, I can generate:\n1. Count of codon.completed events and their success status\n2. Total cost calculation\n3. Sweep status assessment\n\nPlease paste the events and I'll write your report.","cost":"","tokens":{"input":102,"output":158},"eventCount":1}}
```
The captured quality-observer report likewise cites completion-event data and explicitly says that artifact existence, row coverage, and correctness cannot be verified from that event data. Use a rig (an executable setup or checker) or an artifact-reading codon for filesystem assertions; a sentinel is an event observer, not a filesystem-tool session.
[Hank JSON](/0.10.0/files/reference/hank-json) owns the general reference-path contract. [Environment variables](/0.10.0/files/reference/environment-variables) lists sentinel-scoped provider keys.
## Bound conversational history
By default each trigger is an independent LLM call. Conversational mode instead retains history across triggers, and because that history grows, it requires a trimming strategy.
| field | type | default | required | constraints | description |
| ---------------- | -------- | ------- | -------- | ----------- | ----------- |
| `conversational` | `object` | | no | | |
`trimmingStrategy` is required: `maxTurns` is an integer greater than 0 and at most 100, while `maxTokens` is an integer greater than 0 and at most 100000. `continueOnError` defaults to `false`. A conversational sentinel also requires `systemPromptFile` or `systemPromptText`. `maxTurns` prunes the oldest complete user-and-assistant turns. `maxTokens` prunes the oldest messages using exact token counts when available and a `text.length / 4` estimate for older messages; that mode may break turn pairing.
History persists through atomic writes at `.hankweave/sentinels/history/{sentinel-id}-codon-{codon-id}.json`, so state resumes after a server restart. The consecutive-failure threshold does not apply to conversational sentinels; category-specific fatal policy still applies, so corruption unloads unless `continueOnError` is `true`.
## Constrain structured output
Structured output selects object, array, or enum output and constrains which schema material may accompany it.
| field | type | default | required | constraints | description |
| ------------------ | -------- | ------- | -------- | ----------- | ----------- |
| `structuredOutput` | `object` | | no | | |
The modes have complementary requirements. Enum mode requires a non-empty `enumValues` array and forbids schema fields. Object and array modes require exactly one of `schemaStr` and `schemaFile` and forbid `enumValues`. Schema code is evaluated with the Zod `z` object already in scope; neither inline code nor a schema file needs an import, and the result must be a Zod schema or loading fails.
Structured output also adds a model-capability requirement, checked late rather than at load. A structured-output sentinel with a full slash model whose registry entry lacks tool-call capability loads and fires, then fails its first structured-output call with a fatal configuration error when real providers exist. The capability check is invoked when a trigger fires, not as a load-only rejection. Slash-less short names follow the separate load-and-first-call behavior described under [top-level fields](#define-top-level-fields). With `structuredOutput`, `output.format` is rejected and `joinString` is invalid.
## Set LLM parameters
`llmParams` bounds response-generation settings and merges defaults when fields are absent.
| field | type | default | required | constraints | description |
| ----------- | -------- | ------- | -------- | ----------- | ----------- |
| `llmParams` | `object` | | no | | |
The runtime defaults are `temperature: 0`, `maxOutputTokens: 8192`, and `maxRetries: 2`. Temperature 0 is the deterministic default for consistent sentinel output. [Authentication and models](/0.10.0/files/operate/authentication-and-models) covers provider access and model-selection planes.
## Error handling and unloading
Error handling counts consecutive failures and applies category-specific unloading rules.
| field | type | default | required | constraints | description |
| --------------- | -------- | ------- | -------- | ----------- | ----------- |
| `errorHandling` | `object` | | no | | |
`maxConsecutiveFailures` defaults to 3. A non-conversational sentinel unloads when consecutive failures reach that threshold; one success resets the counter. Fatal policy is category-based: `template` and `configuration` errors always unload; `resource` errors never unload; an explicit unload request takes precedence. A `corruption` error unloads a conversational sentinel unless `continueOnError` is `true`; for a non-conversational sentinel it is retained and handled by the consecutive-failure threshold.
One schema field is misleading here. `unloadOnFatalError` is present in the schema with a stated default of `true`, but the runtime never reads it. It is metadata, not an effective switch. See [errors and exit codes](/0.10.0/files/reference/errors-and-exit-codes) for the failure taxonomy and exit behavior.
## Write output files
A sentinel writes text or JSONL output. Structured output is always NDJSON, one JSON object per line, regardless of `output.format`.
| field | type | default | required | constraints | description |
| ------------ | -------- | ------- | -------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `output` | `object` | | no | | |
| `joinString` | `string` | | no | | String to join entries in text-based log file. Only valid for text output. Supports escape sequences: \n (newline), \t (tab), \r (carriage return), \ (backslash). Defaults to '\n---\n' for visual separation. |
> **VersionNote:** `output.format: "json"` was removed in 0.5.5. The only values are `text` and `jsonl`; structured output rejects `output.format` entirely.
The two formats differ in how entries are stored. Text output appends `joinString + text` to an append-only log. Auto-named text logs use a `.md` extension; a configured `output.file` keeps its configured name. JSONL wraps each text output as one JSON line containing `text`, `timestamp`, and `sentinelId`, with a `.jsonl` extension. `joinString` defaults to `\n---\n` and supports `\n`, `\t`, `\r`, and `\\` escapes.
Where the file lands depends on a priority chain. The log-file priority chain is codon-level `settings.outputPaths.logFile`, then sentinel-level `output.file`, then the automatic path `.hankweave/sentinels/outputs/{id}/{id}-{codonId}-{timestamp}.{md|jsonl|ndjson}`. `lastValueFile` follows the same chain. A bare filename with no `/` resolves under the managed execution path `.hankweave/sentinels/outputs/{id}/`; a path containing `/`, including `./x.md`, resolves relative to `agentRoot`. A resolved path that escapes both the execution directory and `agentRoot` is rejected as a fatal configuration error.
`lastValueFile` is atomically replaced for every output; the log is append-only. Initialization failures while creating the directory or file, or checking writability, are fatal configuration errors. Write failures after initialization are logged and do not fail the sentinel. The sentinel-sweep capture uses the bare name `sweep-report.log`, so its managed location is `/.hankweave/sentinels/outputs//sweep-report.log`, not `agentRoot`.
## Control WebSocket reporting
`reportToWebsocket.errors` and `.outputs` gate `sentinel.error` and `sentinel.output` emission. `lifecycle` and `triggers` are declared client-visibility keys for events that are always emitted into the event stream.
| field | type | default | required | constraints | description |
| ------------------- | -------- | ------- | -------- | ----------- | ----------- |
| `reportToWebsocket` | `object` | | no | | |
`errors` and `outputs` emit unless their values are `false`, suppressing `sentinel.error` and `sentinel.output` respectively. `sentinel.loaded`, `sentinel.unloaded`, and `sentinel.triggered` are emitted into the event stream without corresponding server-side `lifecycle` or `triggers` suppression gates; those schema fields are client-visibility controls, and this page does not claim a server-side suppression read site.
> **Pitfall:** `settings.reportToWebsocket` in the codon wrapper is not a reliable override in 0.10.0. The loader does not extract it as a normal wrapper setting, and the remaining merge path is gated and can select the wrong string-reference entry. Configure reporting in the sentinel file itself.
[Events](/0.10.0/files/reference/events) owns event shapes; [WebSocket protocol](/0.10.0/files/integrate/protocol) covers client delivery.
## Attach sentinels to codons
With the configuration defined, the last step is attaching it. A codon attaches sentinels through a per-codon wrapper containing `sentinelConfig` and optional `settings`.
| field | type | default | required | constraints | description |
| ----------- | --------------- | ------- | -------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `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… |
`sentinelConfig` is either a hank-directory-anchored file path or an inline configuration object. Inline references receive escape checks at the wrapper level; file-based references receive them at the file's own directory. The wrapper's `settings` carries `failCodonIfNotLoaded` (default `false`), `outputPaths.logFile`, `outputPaths.lastValueFile`, and `reportToWebsocket`.
Sentinels are wired per codon as `"sentinels": [{"sentinelConfig": ""}]`; a root-level `sentinels` array fails validation with `Unrecognized field(s) at hank root: sentinels`. With `failCodonIfNotLoaded: true`, a sentinel load failure is fatal for the codon. With the default `false`, the failure is logged and the sentinel is skipped. On load, the runtime emits `sentinel.loaded` with `sentinelId`, `codonId`, `model`, `triggerType`, `executionStrategy`, `conversational`, `source`, and optional `sourcePath`.
## Which events reach sentinels
Trigger validation accepts any well-formed event name, but routing is narrower than validation. Only server-state and agentic-backbone event categories are routed to sentinels. Connection-state events are client-specific, and sentinel events are not routed, preventing self-observation loops. The table below is the authoritative list of what a trigger can actually match.
| id | category | journaled | sentinelRouted | payloadFields | receipts |
| ------------------------ | ---------------- | --------- | -------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| archive.completed | server-state | true | true | codonId, archivedPaths | schemas/event-schemas.ts:668, schemas/event-schemas.ts:977, schemas/event-schemas.ts:1257, hankweave-runtime.ts:5465 |
| archive.partial | server-state | true | true | codonId, archivedPaths, failedPaths | schemas/event-schemas.ts:673, schemas/event-schemas.ts:978, schemas/event-schemas.ts:1258, hankweave-runtime.ts:5450 |
| assistant.action | agentic-backbone | true | true | codonId, action, content, toolName?, toolInput? | schemas/event-schemas.ts:572, schemas/event-schemas.ts:986, schemas/event-schemas.ts:1237, hankweave-runtime.ts:2777, hankweave-runtime.ts:2789, hankweave-runtime.ts:2824 |
| budget.summary | server-state | true | true | ceiling, allocation, rows, totals | schemas/event-schemas.ts:724, schemas/event-schemas.ts:979, schemas/event-schemas.ts:1267, hankweave-runtime.ts:6478 |
| checkpoint.list | server-state | true | true | runId, checkpoints, currentBranch | schemas/event-schemas.ts:637, schemas/event-schemas.ts:968, schemas/event-schemas.ts:1250, hankweave-runtime.ts:4255 |
| codon.completed | server-state | true | true | codonId, success, cost, duration, exitStatus, failureReason?, failureIgnored?, budgetExceeded? | schemas/event-schemas.ts:560, schemas/event-schemas.ts:961, schemas/event-schemas.ts:1235, hankweave-runtime.ts:1886, hankweave-runtime.ts:2064, hankweave-runtime.ts:2253, hankweave-runtime.ts:3365 |
| codon.extended | server-state | true | true | codonId, codonName, extensionNumber, exhaustWithPrompt, cumulativeTokens, cumulativeCost | schemas/event-schemas.ts:565, schemas/event-schemas.ts:962, schemas/event-schemas.ts:1236, hankweave-runtime.ts:2946 |
| codon.started | server-state | true | true | codonId, codonName, codonDescription?, sessionId, previousSessionId?, startTime, promptMetadata? | schemas/event-schemas.ts:555, schemas/event-schemas.ts:960, schemas/event-schemas.ts:1234, hankweave-runtime.ts:316 |
| error | server-state | true | true | message, codon?, fatal, severity?, context?, code? | schemas/event-schemas.ts:617, schemas/event-schemas.ts:967, schemas/event-schemas.ts:1246, hankweave-runtime.ts:975, hankweave-runtime.ts:995, hankweave-runtime.ts:1019, hankweave-runtime.ts:1062, hankweave-runtime.ts:1090, hankweave-runtime.ts:1116, hankweave-runtime.ts:1814, hankweave-runtime.ts:1867, hankweave-runtime.ts:2045, hankweave-runtime.ts:2236, hankweave-runtime.ts:2609, hankweave-runtime.ts:3981, hankweave-runtime.ts:4177, hankweave-runtime.ts:4273, hankweave-runtime.ts:4349, hankweave-runtime.ts:4512, hankweave-runtime.ts:4536, hankweave-runtime.ts:4599, hankweave-runtime.ts:4769, hankweave-runtime.ts:4804, hankweave-runtime.ts:4896, hankweave-runtime.ts:4918, hankweave-runtime.ts:5016 |
| file.updated | agentic-backbone | true | true | path, filename, content, action | schemas/event-schemas.ts:587, schemas/event-schemas.ts:988, schemas/event-schemas.ts:1240, hankweave-runtime.ts:2357, hankweave-runtime.ts:3927 |
| filetree.updated | agentic-backbone | true | true | tree | schemas/event-schemas.ts:592, schemas/event-schemas.ts:989, schemas/event-schemas.ts:1241, hankweave-runtime.ts:3954 |
| info | server-state | true | true | message | schemas/event-schemas.ts:627, schemas/event-schemas.ts:966, schemas/event-schemas.ts:1248, hankweave-runtime.ts:1705, hankweave-runtime.ts:1728, hankweave-runtime.ts:1902, hankweave-runtime.ts:1933, hankweave-runtime.ts:1971, hankweave-runtime.ts:2080, hankweave-runtime.ts:2196, hankweave-runtime.ts:2269, hankweave-runtime.ts:2730, hankweave-runtime.ts:3082, hankweave-runtime.ts:3100, hankweave-runtime.ts:3181, hankweave-runtime.ts:3205, hankweave-runtime.ts:3474, hankweave-runtime.ts:3723, hankweave-runtime.ts:3755, hankweave-runtime.ts:4058, hankweave-runtime.ts:4328, hankweave-runtime.ts:6427 |
| loop.iteration.completed | server-state | true | true | loopId, iteration, durationMs, costUsd, tokensUsed, isFinal, terminationReason? | schemas/event-schemas.ts:612, schemas/event-schemas.ts:976, schemas/event-schemas.ts:1245, hankweave-runtime.ts:6035 |
| rig.output | agentic-backbone | true | true | codonId, stream, line, commandIndex | schemas/event-schemas.ts:607, schemas/event-schemas.ts:992, schemas/event-schemas.ts:1244, hankweave-runtime.ts:6109 |
| rig.setup.completed | agentic-backbone | true | true | codonId, rigType, commandCount, durationMs, createdCheckpoint | schemas/event-schemas.ts:597, schemas/event-schemas.ts:990, schemas/event-schemas.ts:1242, hankweave-runtime.ts:2160 |
| rig.setup.failed | agentic-backbone | true | true | codonId, failureType, exitCode?, commandIndex?, ignored | schemas/event-schemas.ts:602, schemas/event-schemas.ts:991, schemas/event-schemas.ts:1243, hankweave-runtime.ts:1791 |
| rollback.archiveRestore | server-state | true | true | codonId, restoredPaths, failedPaths?, status | schemas/event-schemas.ts:678, schemas/event-schemas.ts:974, schemas/event-schemas.ts:1256, hankweave-runtime.ts:5557 |
| rollback.codonCheckpoint | server-state | true | true | codonId, codonName, checkpoint, checkpointType, message | schemas/event-schemas.ts:647, schemas/event-schemas.ts:971, schemas/event-schemas.ts:1252, hankweave-runtime.ts:4684, hankweave-runtime.ts:5136, hankweave-runtime.ts:5191 |
| rollback.completed | server-state | true | true | fromRun, toRun, checkpoint, codonId, codonName, checkpointType, autoRestart | schemas/event-schemas.ts:662, schemas/event-schemas.ts:972, schemas/event-schemas.ts:1255, hankweave-runtime.ts:4722, hankweave-runtime.ts:5254 |
| rollback.progress | server-state | true | true | currentStep, totalSteps, message | schemas/event-schemas.ts:657, schemas/event-schemas.ts:970, schemas/event-schemas.ts:1254, hankweave-runtime.ts:5117, hankweave-runtime.ts:5156 |
| rollback.rigCleanup | server-state | true | true | codonId, codonName, directories, status, successfulCleanups?, failedCleanups?, error? | schemas/event-schemas.ts:652, schemas/event-schemas.ts:973, schemas/event-schemas.ts:1253, hankweave-runtime.ts:5624, hankweave-runtime.ts:5662, hankweave-runtime.ts:5678 |
| rollback.started | server-state | true | true | fromRun, fromCodon, toCodon, toCheckpoint, checkpointType, codonsToProcess | schemas/event-schemas.ts:642, schemas/event-schemas.ts:969, schemas/event-schemas.ts:1251, hankweave-runtime.ts:4645, hankweave-runtime.ts:5095 |
| sentinel.error | sentinel | true | false | sentinelId, codonId, errorType, message, retriable, consecutiveFailureCount | schemas/event-schemas.ts:709, schemas/event-schemas.ts:1001, schemas/event-schemas.ts:1264, sentinels/sentinel.ts:576, sentinels/sentinel.ts:663, sentinels/sentinel.ts:798, sentinels/sentinel.ts:905 |
| sentinel.loaded | sentinel | true | false | sentinelId, codonId, model, triggerType, executionStrategy, conversational, source, sourcePath? | schemas/event-schemas.ts:699, schemas/event-schemas.ts:999, schemas/event-schemas.ts:1262, hankweave-runtime.ts:5819 |
| sentinel.output | sentinel | true | false | sentinelId, codonId, triggerNumber, outputType, content, cost, tokens, eventCount | schemas/event-schemas.ts:714, schemas/event-schemas.ts:1002, schemas/event-schemas.ts:1265, sentinels/sentinel.ts:538, sentinels/sentinel.ts:635, sentinels/sentinel.ts:762, sentinels/sentinel.ts:877 |
| sentinel.triggered | sentinel | true | false | sentinelId, codonId, triggerNumber, strategy, eventCount, queueSize | schemas/event-schemas.ts:719, schemas/event-schemas.ts:1003, schemas/event-schemas.ts:1266, sentinels/sentinel.ts:392 |
| sentinel.unloaded | sentinel | true | false | sentinelId, codonId, reason, errorType?, finalCost, llmCallCount | schemas/event-schemas.ts:704, schemas/event-schemas.ts:1000, schemas/event-schemas.ts:1263, sentinels/sentinel-manager.ts:851 |
| server.idle | server-state | true | true | reason, message | schemas/event-schemas.ts:632, schemas/event-schemas.ts:964, schemas/event-schemas.ts:1249, hankweave-runtime.ts:941, hankweave-runtime.ts:3621, hankweave-runtime.ts:3791, hankweave-runtime.ts:3812, hankweave-runtime.ts:4072, hankweave-runtime.ts:4743, hankweave-runtime.ts:5279, hankweave-runtime.ts:5291 |
| state.snapshot | server-state | true | true | currentCodon?, completedCodons, fileTree, totalCost, totalTime, recentFileAccess?, isRollingBack | schemas/event-schemas.ts:550, schemas/event-schemas.ts:963, schemas/event-schemas.ts:1233, hankweave-runtime.ts:1422 |
| state.transition | server-state | true | true | transitionType, runId?, codonId?, transition, resultingState | schemas/event-schemas.ts:693, schemas/event-schemas.ts:975, schemas/event-schemas.ts:1261, hankweave-runtime.ts:394 |
| token.usage | server-state | true | true | codonId, inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens, totalCost, modelId?, modelUsage? | schemas/event-schemas.ts:577, schemas/event-schemas.ts:965, schemas/event-schemas.ts:1238, hankweave-runtime.ts:2646, hankweave-runtime.ts:2660 |
| tool.result | agentic-backbone | true | true | codonId, toolUseId, toolName, result, truncated, originalLength, executionTimeMs, isError | schemas/event-schemas.ts:582, schemas/event-schemas.ts:987, schemas/event-schemas.ts:1239, hankweave-runtime.ts:2906 |
The generated selection contains 27 routed event types, including `codon.extended`, `rig.setup.completed`, `rig.setup.failed`, `rig.output`, `loop.iteration.completed`, `archive.completed`, `archive.partial`, `rollback.archiveRestore`, and `budget.summary`. Sentinel event names can pass trigger schema validation but never reach a sentinel; a trigger on `sentinel.output` loads successfully and never fires. [Events](/0.10.0/files/reference/events) owns the complete catalog, while [Sentinel concepts](/0.10.0/files/concepts/sentinels) owns the observer semantics.