stitchkit 0.122.1 → 0.122.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/agent-runtime/deferred-tool-search.d.ts.map +1 -1
- package/dist/agent-runtime/deferred-tool-types.d.ts.map +1 -1
- package/dist/entrypoints/agent-runtime.js +4 -3
- package/llms/agent-runtime.2.txt +632 -745
- package/llms/agent-runtime.3.txt +733 -492
- package/llms/agent-runtime.4.txt +521 -88
- package/llms/agent-runtime.5.txt +114 -0
- package/llms/agent-runtime.txt +4 -655
- package/llms-full.txt +5 -1
- package/llms.txt +1 -1
- package/package.json +1 -1
package/llms/agent-runtime.4.txt
CHANGED
|
@@ -1,113 +1,546 @@
|
|
|
1
|
-
# stitchkit/agent-runtime — stitchkit docs slice, part 4 of
|
|
1
|
+
# stitchkit/agent-runtime — stitchkit docs slice, part 4 of 5
|
|
2
2
|
|
|
3
3
|
> Generated from the `docs/` tree by `bun run gen:llms`. The index of all slices is
|
|
4
4
|
> `llms.txt` in this package.
|
|
5
|
+
> Continues in `llms/agent-runtime.5.txt`.
|
|
5
6
|
|
|
6
7
|
Parts of this slice:
|
|
7
8
|
- `llms/agent-runtime.txt`: Guide: Agent application runtime (docs/guide/agent-runtime.md)
|
|
8
9
|
- `llms/agent-runtime.2.txt`: Guide: Agent application runtime (docs/guide/agent-runtime.md)
|
|
9
|
-
- `llms/agent-runtime.3.txt`: Guide: Agent application runtime (docs/guide/agent-runtime.md)
|
|
10
|
-
- `llms/agent-runtime.4.txt`: API reference: `stitchkit-
|
|
10
|
+
- `llms/agent-runtime.3.txt`: Guide: Agent application runtime (docs/guide/agent-runtime.md)
|
|
11
|
+
- `llms/agent-runtime.4.txt`: Guide: Agent application runtime (docs/guide/agent-runtime.md) · API reference: `stitchkit/agent-runtime` (docs/api/reference.md)
|
|
12
|
+
- `llms/agent-runtime.5.txt`: API reference: `stitchkit-tui` (docs/api/reference.md)
|
|
11
13
|
|
|
12
14
|
==============================================================================
|
|
13
|
-
#
|
|
15
|
+
# Guide: Agent application runtime (docs/guide/agent-runtime.md) (continued)
|
|
14
16
|
==============================================================================
|
|
15
17
|
|
|
16
|
-
##
|
|
18
|
+
## Observability
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
`createAgentObservability` emits a separate operator-only `AgentRunEvent`. It
|
|
21
|
+
reuses the same bounded sink lifecycle as request/tool observability without
|
|
22
|
+
sending new event kinds to existing request sinks. Product events omit provider
|
|
23
|
+
causes. Operator `internalCause` is also redacted by default; an operator-only sink must explicitly
|
|
24
|
+
set `includeInternalCause` and own its retention policy.
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
|--------|------|---------|
|
|
22
|
-
| `defineAgentTui` | function | typed config for title, `theme` (a `TerminalPalette` override) and `themeMode`, status rows, model catalog, context, commands, runtime bundle and optional host-evidenced recovery policy; the default never requeues acquired effects |
|
|
23
|
-
| `runAgentTui` | function | start one fresh durable conversation and terminal controller, recover durable work and publish its authenticated local session; `initialConversationId` is an explicit resume override; it closes the session and exits the process on Ctrl-C and every signal OpenTUI catches unless `exitSignals: []` |
|
|
24
|
-
| `defineTuiCommand` / `resolveTuiCommand` | function | typed composable slash-command registry; unknown slash input remains an ordinary model prompt |
|
|
25
|
-
| `createAgentTuiController` | function | single admission, selection, approval, interruption and conversation-switch owner over the harness |
|
|
26
|
-
| `startAgentTuiSessionHost` / `createAgentTuiClient` | function | authenticated mode-`0600` Unix-socket host/client for status, submit and interrupt through that controller |
|
|
27
|
-
| `listAgentTuiSessions` | function | discover live local terminal session IDs and their current conversation |
|
|
28
|
-
| `createAgentTuiComposer` / `navigateAgentTuiHistory` | function | multiline draft and reversible prompt-history state |
|
|
29
|
-
| `defaultAgentTuiStatusLine` / `AgentTuiStatusLineFormatter` | function / _type_ | terminal-native default rows and a host formatter over model capacity, durable snapshot, activity, workspace and local identities; `statusLine: false` hides the rows |
|
|
30
|
-
| `createAgentTuiDiagnosticRecorder` / `AgentTuiDiagnosticEventSchema` | function / schema | bounded per-session metadata journal that rejects prompt, reasoning, tool-input and provider-cause payloads before disk admission |
|
|
31
|
-
|
|
32
|
-
The `stitchkit-agent` binary runs React's production build unless `NODE_ENV` says otherwise and loads `stitchkit.agent.ts` by default and also exposes `sessions`,
|
|
33
|
-
`status`, `send` and `interrupt`. `--workspace` addresses a host outside the caller's cwd,
|
|
34
|
-
`send --idempotency-key` accepts caller-owned retry identity, and `interrupt` defaults to the
|
|
35
|
-
active run returned by `status`. Session descriptors and sockets are local control credentials,
|
|
36
|
-
not a remote API.
|
|
37
|
-
Interactive `/resume` and `/sessions` open the durable conversation picker. `/clear` creates a new
|
|
38
|
-
conversation and keeps the previous one available there; it is not a viewport-only operation.
|
|
39
|
-
The slash palette owns its highlighted selection: Up/Down move it, Tab completes it, Enter runs
|
|
40
|
-
the exact command and Escape dismisses it. Partial input is never submitted while the palette is
|
|
41
|
-
active; unknown slash text with no match remains an ordinary model prompt.
|
|
42
|
-
|
|
43
|
-
### `stitchkit-tui/core`
|
|
44
|
-
|
|
45
|
-
Renderer-neutral state only. This entrypoint imports neither React/OpenTUI nor the agent runtime.
|
|
26
|
+
### What a run says it spent
|
|
46
27
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
| `createTerminalFeedViewport` / `reduceTerminalFeedViewport` | function | generic follow-tail, history anchoring, unseen and bounded visible-range state |
|
|
51
|
-
| `createTerminalPaneState` / `reduceTerminalPaneState` | function | bounded split-pane focus, resize and single-pane collapse |
|
|
52
|
-
| `createTerminalCommandPalette` / `terminalCommandMatches` | function | bounded command filtering and keyboard selection over a collision-validated registry |
|
|
53
|
-
| `resolveExactTerminalCommand` / `validateTerminalCommands` | function | exact dispatch and fail-closed name/alias validation |
|
|
54
|
-
| `createTerminalOperationState` / `reduceTerminalOperationState` | function | confirmation and single-pending-operation lifecycle |
|
|
55
|
-
| `createTerminalTable` / `reduceTerminalTable` / `projectTerminalTable` | function | live table: typed columns, rows validated on entry, sort with key tie-break and missing values last, tree expansion pruned to present rows, filter on displayed text, selection kept across data; a row's `tone` and a column's `tone(value, row)` colour state |
|
|
56
|
-
| `layoutTerminalTableColumns` / `formatTerminalTableCell` / `visibleTerminalTableRows` / `terminalTableTreePrefix` | function | fixed and flexible column widths, `—` for missing values, the virtualized window, tree indentation |
|
|
57
|
-
| `createTerminalList` / `reduceTerminalList` / `visibleTerminalListLines` | function | picker with sections, fuzzy query with title highlight ranges, multi-select, disabled items and "more above/below" counts |
|
|
58
|
-
| `createTerminalForm` / `reduceTerminalForm` / `readTerminalForm` / `terminalFormFieldsFromJsonSchema` | function | typed fields (text, secret, number, integer, boolean, choice, JSON) from a JSON Schema, relative text edits, validation on leave and submit |
|
|
59
|
-
| `createTerminalTabs` / `reduceTerminalTabs` | function | tabs with badges, wrap-around movement, digit selection and reconcile that keeps the selected tab |
|
|
60
|
-
| `createTerminalNavigation` / `reduceTerminalNavigation` / `terminalBreadcrumbs` | function | screen stack keeping each level's state, root never popped |
|
|
61
|
-
| `createTerminalFocus` / `reduceTerminalFocus` | function | focus ring plus layers that take the keyboard and give it back |
|
|
62
|
-
| `createTerminalNotices` / `reduceTerminalNotices` / `nextTerminalNoticeExpiry` | function | bounded toasts on a caller clock, replaced by id |
|
|
63
|
-
| `createTerminalTimeSeries` / `appendTerminalSample` / `sampleTerminalTimeSeries` | function | time window bounded by duration and sample count, value-in-force sampling with explicit gaps |
|
|
64
|
-
| `terminalBrailleChart` / `terminalSparkline` / `terminalTimeAxis` / `terminalChartScale` | function | multi-series braille line or area chart as toned runs, sparkline, time axis |
|
|
65
|
-
| `terminalMeter` / `layoutTerminalMeterGrid` | function | eighth-block bar toned by thresholds, unmeasured as muted; column-major core grid |
|
|
66
|
-
| `terminalProgress` / `terminalSpinnerFrame` / `terminalIndeterminateBlock` / `formatTerminalDuration` | function | ratio, rate and ETA only when knowable; spinner frames; indeterminate bar; elapsed time |
|
|
67
|
-
| `defineTerminalKeymap` / `matchTerminalKey` / `fitTerminalKeyHints` | function | conflict-checked bindings that both answer keys and draw a footer fitted to the width |
|
|
68
|
-
| `terminalTableKeymap` / `terminalTableKey` / `terminalTabsKeymap` / `terminalTabsKey` | function | htop-style table bindings and tab bindings as keymaps |
|
|
69
|
-
| `matchTerminalSearch` / `searchTerminalItems` / `terminalHighlightRuns` | function | multi-word fuzzy match with ranges, stable ranking, highlight runs |
|
|
70
|
-
| `sanitizeTerminalText` / `terminalTextWidth` / `truncateTerminalText` / `fitTerminalText` / `wrapTerminalText` | function | strip escape and control sequences; measure, cut, pad and wrap by terminal cells |
|
|
71
|
-
| `terminalTextEdit` / `applyTerminalTextEdit` | function | one-line edits as relative actions, so fast input is never lost |
|
|
72
|
-
| `terminalJsonLines` / `layoutTerminalDetails` | function | toned, sanitized JSON lines; aligned key/value pairs |
|
|
73
|
-
| `terminalPalettes` / `resolveTerminalPalette` / `TerminalPalette` / `TerminalTone` | value / function / _type_ | one semantic palette (surfaces plus `primary`, `muted`, `accent`, `success`, `warning`, `danger`) for dark and light terminals |
|
|
74
|
-
| `terminalLabelsEn` / `terminalLabelsRu` / `TerminalLabels` | value / _type_ | every word the widgets draw |
|
|
75
|
-
|
|
76
|
-
### `stitchkit-tui/widgets`
|
|
77
|
-
|
|
78
|
-
OpenTUI React widgets over the core state. React, `@opentui/core` and `@opentui/react` are peers;
|
|
79
|
-
this entrypoint never loads `stitchkit`.
|
|
28
|
+
Usage values carry `provider-reported`, `computed`, `estimated` or `unavailable`
|
|
29
|
+
provenance, **per field**. Cost additionally carries an ISO currency code;
|
|
30
|
+
OpenRouter-reported cost is normalized as USD.
|
|
80
31
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
32
|
+
Read the provenance before the number (→ ADR 0109):
|
|
33
|
+
|
|
34
|
+
- **`provider-reported`** — the provider handed us exactly this. On
|
|
35
|
+
`step-finished`, that is what a step's figures are.
|
|
36
|
+
- **`computed`** — a total, added up over steps. **Every figure on a terminal
|
|
37
|
+
event is this**, tokens included: the AI SDK's `totalUsage` is a sum it
|
|
38
|
+
performed, not a number a provider reported for the run. It is not a figure to
|
|
39
|
+
bill against unchanged.
|
|
40
|
+
- **`unavailable`** — nobody reported it. Not zero.
|
|
41
|
+
|
|
42
|
+
Two rules follow from that last one, and they differ by field on purpose:
|
|
43
|
+
|
|
44
|
+
- **A token total with an unreported step is a floor**, labelled `computed`. A
|
|
45
|
+
token count is a diagnostic, and a floor is a useful one.
|
|
46
|
+
- **A cost with an unreported step is `unavailable`, not a floor.** Money is what
|
|
47
|
+
people bill against, and "at least $1.00" reported as `$1.00` is the same class
|
|
48
|
+
of lie this whole section exists to remove. One step that did not report its
|
|
49
|
+
cost makes the run's cost unknown — not smaller. It also stays unknown: later
|
|
50
|
+
steps reporting normally cannot revive it.
|
|
51
|
+
|
|
52
|
+
**A terminal event always carries `usage`.** A run that ended before the provider
|
|
53
|
+
reported anything — superseded, interrupted, timed out, shut down, failed —
|
|
54
|
+
carries every field `unavailable`. That is deliberately different from a run that
|
|
55
|
+
spent nothing, and an omitted object could not tell you which one you had.
|
|
56
|
+
|
|
57
|
+
Two costs in different currencies do not add: the sum reports `unavailable`
|
|
58
|
+
rather than picking a label. The core records a currency and never converts one.
|
|
59
|
+
|
|
60
|
+
`step-finished.response` identifies the provider response for that one step. The terminal event
|
|
61
|
+
does not copy the last response: response identity remains per-step, while every terminal usage
|
|
62
|
+
figure remains a `computed` aggregate.
|
|
63
|
+
|
|
64
|
+
**A run's figure is durable, and that is where to read it when a channel loses
|
|
65
|
+
it.** `AgentRun.usage` is written at every checkpoint and again with the terminal
|
|
66
|
+
record, so a crashed process leaves behind what it had already spent and a
|
|
67
|
+
dropped event is not a lost number:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
const snapshot = await store.loadSnapshot(conversationId)
|
|
71
|
+
const spent = snapshot.runs.find((run) => run.id === runId)?.usage
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Two gaps are open and are stated rather than left to be discovered:
|
|
75
|
+
|
|
76
|
+
- **Both event sinks are bounded and drop under load**, by arrival order — the
|
|
77
|
+
event carrying the money is exactly as droppable as the one carrying nothing.
|
|
78
|
+
The run record is the recovery, and this paragraph is the only place that says
|
|
79
|
+
so.
|
|
80
|
+
- **`AgentRuntimeResult.metrics` is `undefined` when this executor did not win
|
|
81
|
+
the terminal race.** Read `result.run.usage` — the durable figure — rather than
|
|
82
|
+
`result.metrics`, which is the channel that can go missing.
|
|
83
|
+
- **Compaction spend is invisible unless you report it.** `config.history.compact`
|
|
84
|
+
calls a model inside the turn and produces no step and no event of its own.
|
|
85
|
+
Return `usage` from `AgentCompactionResult` and it joins the run's figure;
|
|
86
|
+
omit it and the run under-reports by whatever summarising cost.
|
|
87
|
+
|
|
88
|
+
What stitchkit does **not** keep is a ledger: one figure, on the run that
|
|
89
|
+
produced it, never aggregated and never reconciled against a provider invoice
|
|
90
|
+
(→ ADR 0110).
|
|
91
|
+
|
|
92
|
+
### Reconciling with the provider's own accounting
|
|
93
|
+
|
|
94
|
+
Whether a provider bills for a call that was aborted mid-flight cannot be known
|
|
95
|
+
inside the process: the authoritative number arrives later, from the provider's
|
|
96
|
+
accounting. **stitchkit does not accept it back** (→ ADR 0110) — a terminal run
|
|
97
|
+
is an absorbing state, and a write that reached it through the conversation
|
|
98
|
+
aggregate could conflict a concurrent compaction into discarding a summary it had
|
|
99
|
+
just paid a model to produce.
|
|
100
|
+
|
|
101
|
+
The join is yours, and `runId` is the key:
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
// when the run terminates — write what the runtime observed
|
|
105
|
+
await ledger.record({
|
|
106
|
+
runId: terminal.run.id,
|
|
107
|
+
conversationId: terminal.run.conversationId,
|
|
108
|
+
// The durable figure, not `terminal.metrics` — that one is absent whenever
|
|
109
|
+
// this executor did not win the terminal race.
|
|
110
|
+
costUsd: terminal.run.usage?.cost?.value ?? null, // null when `unavailable`
|
|
111
|
+
provenance: terminal.run.usage?.cost?.provenance ?? 'unavailable',
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
// later — the provider's accounting names the same generation
|
|
115
|
+
await ledger.reconcile({ runId, costUsd: billed, provenance: 'provider-reported' })
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Record the row even when the figure is `unavailable`: that row is the evidence
|
|
119
|
+
that a run happened and cost something nobody has counted yet, and it is what the
|
|
120
|
+
provider's later figure attaches to. A run with no row is a run you cannot
|
|
121
|
+
reconcile.
|
|
122
|
+
|
|
123
|
+
The sink deduplicates stable event IDs by default. Cross-crash exactly-once still requires a durable
|
|
124
|
+
outbox.
|
|
125
|
+
|
|
126
|
+
## Deterministic race and adapter proof
|
|
127
|
+
|
|
128
|
+
`stitchkit/agent-runtime/testing` exports `createAgentRaceBarrier`, `createAgentRaceDriver`,
|
|
129
|
+
`createAgentRaceTrace` and `runAgentStoreConformance` — agent testing tools live beside the agent
|
|
130
|
+
runtime, and `stitchkit/testing` imports none of it. Barriers have bounded teardown, traces assert exact partial order, and the
|
|
131
|
+
helpers are exercised from packed Bun and Node consumers. `runAgentStoreConformance` runs duplicate,
|
|
132
|
+
coalescing, collision, stale checkpoint, replay safety, terminal race, absorption, bounded reads,
|
|
133
|
+
causal queued-history order, durable interrupt priority, compaction and recovery invariants against
|
|
134
|
+
any fresh durable adapter.
|
|
135
|
+
|
|
136
|
+
It picks its conversation identities itself and passes them to `createStore(context)` **before the
|
|
137
|
+
first mutation**, so an adapter whose runtime rows reference an application-owned conversation row
|
|
138
|
+
can provision those parents; the optional `cleanup(context)` removes them again, and runs once
|
|
139
|
+
whether the scenario passed or failed. A factory that owns no fixture state ignores the argument and
|
|
140
|
+
keeps working unchanged.
|
|
141
|
+
|
|
142
|
+
## Plain completions and shared invocation receipts
|
|
143
|
+
|
|
144
|
+
Use `createModelInvocationLedger` from `stitchkit/agent-runtime` when a direct text
|
|
145
|
+
completion and an agent must share causal provider evidence. It uses the existing
|
|
146
|
+
runtime store, not a second database. The completion path sends exactly one user
|
|
147
|
+
prompt, no framework instructions and no tools. It never starts an agent loop.
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
import { createModelInvocationLedger } from 'stitchkit/agent-runtime';
|
|
151
|
+
|
|
152
|
+
const invocations = createModelInvocationLedger({
|
|
153
|
+
store, // the same AgentRuntimeStore object passed to createAgentRuntime
|
|
154
|
+
models, // an existing defineModelRegistry result
|
|
155
|
+
payloadKey, // 32 bytes from the host's secret store; retain separately from archives
|
|
156
|
+
authorize: async ({ context, conversationId, action, trace }) => {
|
|
157
|
+
const session = await authenticate(context);
|
|
158
|
+
await authorizeConversation(session, conversationId, action, trace);
|
|
159
|
+
return { subject: session.subject }; // verified identity, never a body field
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
const completion = await invocations.complete({
|
|
164
|
+
conversationId: 'evaluation-42',
|
|
165
|
+
idempotencyKey: 'summary-case-3',
|
|
166
|
+
trace: {
|
|
167
|
+
operationId: 'summary-42', purpose: 'summarize', project: 'example',
|
|
168
|
+
parent: { traceId: 'trace-42' }, experiment: 'evaluation', case: 'case-3',
|
|
169
|
+
},
|
|
170
|
+
prompt: 'Summarize these supplied facts.',
|
|
171
|
+
models: ['primary', 'fallback'], // registry keys; repeat a key for an explicit retry
|
|
172
|
+
settings: { maxOutputTokens: 500 },
|
|
173
|
+
timeoutMs: 30_000,
|
|
174
|
+
}, authenticatedContext);
|
|
175
|
+
|
|
176
|
+
// Add to the existing createAgentRuntime configuration:
|
|
177
|
+
const receiptConfig = {
|
|
178
|
+
ledger: invocations,
|
|
179
|
+
trace: ({ run }) => ({
|
|
180
|
+
operationId: run.id, purpose: 'assistant-turn', project: 'example',
|
|
181
|
+
}),
|
|
182
|
+
};
|
|
183
|
+
// createAgentRuntime({ ...existingConfig, invocations: receiptConfig });
|
|
95
184
|
|
|
96
|
-
|
|
185
|
+
const page = await invocations.read({
|
|
186
|
+
conversationId: 'evaluation-42', limit: 100,
|
|
187
|
+
}, authenticatedContext);
|
|
188
|
+
// Continue with fromSeq: page.nextSeq while it is defined.
|
|
189
|
+
```
|
|
97
190
|
|
|
98
|
-
|
|
191
|
+
`complete` returns `invocationId`, `outcome` and, on success, `text`. `duplicate`
|
|
192
|
+
returns the existing ID without provider execution or replaying plaintext. Changed
|
|
193
|
+
input, trace or caller under the same key is a conflict. Model attempts are explicit
|
|
194
|
+
and bounded to eight; SDK retries are disabled. Only provider failures trigger the
|
|
195
|
+
next attempt. Abort, audit refusal and configuration errors do not. An admitted call
|
|
196
|
+
whose process died stays claimed: inspect the receipt before choosing a new key.
|
|
99
197
|
|
|
100
|
-
|
|
198
|
+
The agent retains its existing prompt, tools and loop. Both modes produce
|
|
199
|
+
`invocation/started`, `provider/request`, `provider/response` and
|
|
200
|
+
`invocation/finished` records through `read`. Each attempt has its own ID; response
|
|
201
|
+
usage is counted once and keeps `unavailable` distinct from measured zero. Requested
|
|
202
|
+
registry selection, sent adapter identity and effective provider identity are
|
|
203
|
+
separate. Effective identity is null when not reported. A gateway's hidden retries
|
|
204
|
+
are not visible as additional attempts.
|
|
205
|
+
|
|
206
|
+
`currentModelInvocationAttempt()` returns the causal context inside a provider's
|
|
207
|
+
`fetch` callback or streamed read. Use it to join a host transport audit to
|
|
208
|
+
`operationId`, `invocationId`, `attemptId`, optional `runId` and `step`.
|
|
209
|
+
`onAttempt` is an awaited admission hook; a rejected hook prevents the provider call.
|
|
210
|
+
SDK payload hashes are not represented as hashes of HTTP wire bytes.
|
|
211
|
+
|
|
212
|
+
Prompts and output are AES-256-GCM payload artifacts. `read` returns references and
|
|
213
|
+
hashes; `readPayload({ conversationId, artifactId }, context)` separately authorizes
|
|
214
|
+
`read-payload` and checks authentication tags and hashes. `payloadKey` must be 32
|
|
215
|
+
bytes and is copied at construction. Keep it outside the event store/backups; retain
|
|
216
|
+
the appropriate key when restoring an archive. `maxPayloadBytes` defaults to 4 MiB
|
|
217
|
+
(range 1 KiB–64 MiB). Streaming output evidence keeps parts up to half of it; past
|
|
218
|
+
that the evidence carries `truncated: { parts, sha256 }` over the whole stream, and
|
|
219
|
+
the answer itself is never cut. A receipt that cannot be written never changes an
|
|
220
|
+
outcome: `complete()` returns it with `receiptError` beside it, and a succeeded
|
|
221
|
+
answer keeps its `text`. Request headers
|
|
222
|
+
are excluded. Protect existing agent history independently: enabling receipts does
|
|
223
|
+
not encrypt its ordinary conversation records.
|
|
224
|
+
|
|
225
|
+
The built-in memory and SQLite stores implement `appendEventOnce`. Custom stores
|
|
226
|
+
must implement its once-only check and append atomically, returning the original
|
|
227
|
+
event on a duplicate key scoped by conversation and kind. A factory without this
|
|
228
|
+
capability refuses receipt setup. The driver-backed implementation finds the keyed
|
|
229
|
+
event by its identity through the driver's optional `events.find` — one index probe
|
|
230
|
+
in SQLite — so admission costs the same on a long conversation as on a new one; a
|
|
231
|
+
custom driver without `find` falls back to paging the log in one transaction.
|
|
232
|
+
`store.findEventOnce({ conversationId, kind, key })` reads the same event back.
|
|
233
|
+
Invocation payload artifacts are keyed by their artifact id the same way.
|
|
234
|
+
|
|
235
|
+
### Migration from direct SDK completions
|
|
236
|
+
|
|
237
|
+
**Who must act:** applications opting into shared completion/agent receipts.
|
|
238
|
+
Replace the direct `generateText` call with `invocations.complete`, configure host
|
|
239
|
+
authorization and a retained payload key, and pass the same ledger in the agent's
|
|
240
|
+
`invocations` option. Use the returned invocation ID and the paginated `read` method
|
|
241
|
+
for receipt queries; do not import runtime internals. Available since 0.100.0;
|
|
242
|
+
existing runtime configurations need no migration.
|
|
243
|
+
|
|
244
|
+
==============================================================================
|
|
245
|
+
# API reference: `stitchkit/agent-runtime` (docs/api/reference.md)
|
|
246
|
+
==============================================================================
|
|
247
|
+
|
|
248
|
+
## `stitchkit/agent-runtime`
|
|
249
|
+
|
|
250
|
+
Server-only optional application runtime. See the
|
|
251
|
+
[agent runtime guide](../guide/agent-runtime.md).
|
|
101
252
|
|
|
102
253
|
| Export | Kind | Summary |
|
|
103
254
|
|--------|------|---------|
|
|
104
|
-
| `
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
255
|
+
| `createAgentRuntime` | function | compose durable acceptance, stream loop, checkpoints, coordination, managed tools and winner-only terminal publication; reconciles same-owner terminal/interrupt/head CAS races before releasing the lane |
|
|
256
|
+
| `createDeferredAgentToolSurface` | function | bounded canonical catalog search plus durable same-run activation of direct `mountAgent` tools; supports one immutable surface or a finite identity-specific registry |
|
|
257
|
+
| `DeferredAgentToolSearchInputSchema` / `DeferredAgentToolMatchSchema` / `DeferredAgentToolReceiptSchema` | schema | bounded search input, public match and versioned durable selection receipt |
|
|
258
|
+
| `DeferredAgentToolSurfaceConfig` / `DeferredAgentToolCommonConfig` / `DeferredAgentToolSurfaceDefinition` / `DeferredAgentToolController` | _type_ | finite catalogs, selector, pin, budget and `mount`/`prepareStep` composition contracts |
|
|
259
|
+
| `DeferredAgentRuntimeToolDefinition` / `DeferredAgentToolMountConfig` | _type_ | peer-free Agent-only runtime definition and canonical mount configuration accepted by the controller |
|
|
260
|
+
| `DeferredAgentToolManifestEntry` / `DeferredAgentToolSearchContext` / `DeferredAgentToolReceipt` | _type_ | canonical selector input and inferred durable receipt records |
|
|
261
|
+
| `DeferredAgentToolEvent` | _type_ | PII-free search/step evidence with surface, provenance, counts, canonical schema bytes and ceilings |
|
|
262
|
+
| `defineAgentProtocol` | function | declare context, input metadata, canonical parts and optional pre-CAS terminal acceptance (`allow-empty`, `require-output` or callback) |
|
|
263
|
+
| `hasAgentTerminalOutput` | function | generic `require-output` predicate for non-blank text, generated files, structured provider parts and explicit tool-only policy stops |
|
|
264
|
+
| `AgentMessageSchema` / `AgentRunSchema` / `AgentSnapshotSchema` | schema | versioned canonical engine records |
|
|
265
|
+
| `AgentRunQueuePrioritySchema` | schema | durable opt-in priority for queued `interrupt-next` runs |
|
|
266
|
+
| `AgentRuntimeStore` | _type_ | aggregate CAS transaction boundary for message, run and compaction mutations |
|
|
267
|
+
| `BranchAgentConversationInputSchema` / `BranchAgentConversationInput` | schema / _type_ | strict branch request: stable request key, empty destination, settled conversation boundary or archive bytes, fresh artifact authorization |
|
|
268
|
+
| `AgentConversationBranchReceiptSchema` / `AgentConversationBranchReceipt` | schema / _type_ | durable lineage: request fingerprint, source/destination identities, source sequence/version/digest and creation time |
|
|
269
|
+
| `AgentConversationBranchResultSchema` / `AgentConversationBranchResult` | schema / _type_ | `created` or `duplicate` with the same durable receipt; `AgentRuntimeStore.branchConversation` is optional for hand-written stores |
|
|
270
|
+
| `createAgentRuntimeStore` | function | build the aggregate store from one coherent transaction driver; framework owns every state transition |
|
|
271
|
+
| `AgentRuntimeStoreDriver` | _type_ | ORM-neutral transaction over a bounded head, normalized runs/admissions, product history, a **required** `events: { append, list }` ledger table, an optional `archive: { export, import }` for driver-owned durable payloads, and indexed run recovery; optional `{ access: 'read' }` selects a coherent read transaction while absent options remain write-safe |
|
|
272
|
+
| `recordAgentRetryDecision` / `AgentRetryPolicy` | function / _type_ | `loop.retry` policy and the ledger record of a retry decision: explicit retryability and backoff at a durable provider-step boundary |
|
|
273
|
+
| `AgentRuntimeHeadSchema` | schema | constant-size conversation identity plus monotonic runtime version |
|
|
274
|
+
| `AgentStoredRunSchema` | schema | canonical normalized run with an optional retained terminal assistant |
|
|
275
|
+
| `AgentAdmissionReceiptSchema` | schema | durable idempotency receipt with canonical input and assigned run/assistant identities |
|
|
276
|
+
| `AgentHistoryMutationSchema` | schema | typed canonical message mutation applied inside the winning state transaction |
|
|
277
|
+
| `RecoverAgentRunSchema` | schema | explicit abandon/requeue recovery decision; acquired runs require replay-safe evidence |
|
|
278
|
+
| `createMemoryAgentRuntimeStore` | function | process-local reference adapter, not production durability |
|
|
279
|
+
| `purgeAgentConversation` | function | dispatch optional atomic deletion; returns `unsupported`, `active`, `conflict`, `purged` or `already_purged` |
|
|
280
|
+
| `AgentConversationPurgeInputSchema` / `AgentConversationPurgeInput` | schema / _type_ | conversation ID and optional expected snapshot version |
|
|
281
|
+
| `AgentConversationPurgeResultSchema` / `AgentConversationPurgeResult` | schema / _type_ | typed deletion/refusal outcomes; active refusal includes run IDs |
|
|
282
|
+
| `AgentConversationPurgedError` | class | runtime mutation rejected because its conversation ID is permanently purged |
|
|
283
|
+
| `AgentConversationPurgeDriver` | _type_ | optional `driver.conversations` capability: serialized tombstone read and atomic removal of all owned records |
|
|
284
|
+
| `projectAgentHistory` | function | asynchronously project canonical records and resolved multimodal files into provider-valid AI SDK messages |
|
|
285
|
+
| `defineModelRegistry` | function | typed language-model descriptors, capabilities and provider construction |
|
|
286
|
+
| `AgentModelCatalogSchema` / `AgentModelCatalog` | schema / _type_ | provider-neutral complete/partial model catalog with separately sourced popularity, metrics, prices and observation time |
|
|
287
|
+
| `AgentModelCatalogEntrySchema` / `AgentModelCatalogEntry` | schema / _type_ | one canonical provider model descriptor with optional price, popularity and metric evidence |
|
|
288
|
+
| `AgentModelPriceSchema` / `AgentModelPrice` | schema / _type_ | normalized per-token input/output pricing and source currency |
|
|
289
|
+
| `AgentModelPopularitySchema` / `AgentModelPopularity` | schema / _type_ | independently sourced ranked popularity observation with window and timestamp |
|
|
290
|
+
| `AgentModelMetricSchema` / `AgentModelMetric` | schema / _type_ | independently sourced benchmark measurement with provenance and observation time |
|
|
291
|
+
| `AgentModelCatalogProvider` | _type_ | abortable live catalog loader supplied by a provider adapter or application |
|
|
292
|
+
| `AgentModelSearchInputSchema` / `AgentModelSearchInput` | schema / _type_ | bounded catalog text query and result ceiling |
|
|
293
|
+
| `AgentModelSearchResultSchema` / `AgentModelSearchResult` | schema / _type_ | exact bounded catalog projection with total match count |
|
|
294
|
+
| `searchAgentModelCatalog` | function | deterministic bounded search over a loaded canonical catalog |
|
|
295
|
+
| `AgentModelSelectionSchema` / `AgentModelSelection` / `AgentModelSelectionStore` | schema / _type_ | durable per-conversation model choice; runtime resolvers receive run and snapshot to recover the model pinned to input metadata |
|
|
296
|
+
| `createMemoryAgentModelSelectionStore` | function | process-local selection reference adapter |
|
|
297
|
+
| `AgentConversationReader` | _type_ | optional bounded conversation-summary and message-history reader; `messages` takes `includeCompacted` and every page names its `compacted` ids; not part of the required runtime store contract |
|
|
298
|
+
| `AgentConversationSummarySchema` / `AgentConversationSummary` | schema / _type_ | bounded durable conversation list item with version, activity and preview |
|
|
299
|
+
| `AgentConversationPageSchema` / `AgentConversationPage` | schema / _type_ | cursor-paged conversation summaries |
|
|
300
|
+
| `AgentConversationMessagePageSchema` / `AgentConversationMessagePage` | schema / _type_ | cursor-paged durable message history |
|
|
301
|
+
| `composeAgentPrompt` | function | ordered prompt contributions and provenance-aware signed context budget; irreducible reservation deficits are `oversized`, not compactable history |
|
|
302
|
+
| `SeedConversationInputSchema` / `SeedConversationInput` | schema / _type_ | atomic once-seeding input; partial imported identity sets are refused |
|
|
303
|
+
| `AgentSeedReceiptSchema` / `AgentSeedReceipt` | schema / _type_ | durable seed receipt retained beyond compaction and implemented by custom store drivers |
|
|
304
|
+
| `StepRunOptions` | _type_ | per-step options of the durability engine (`stitchkit/tools`) as the runtime drives it |
|
|
305
|
+
| `DURABILITY_STEP_EVENT_KIND` | const | the ledger event kind a recorded step is written under |
|
|
306
|
+
| `StepResultDecodeError` / `StepResultNotSerializableError` / `StepAbortedError` / `ParkRecordDecodeError` / `ParkAbortedError` | class | fail-closed decode of a recorded step or park, a body whose result cannot be serialized, an aborted step, and a park collapsed around an aborted waiter |
|
|
307
|
+
| `structuredCompaction` | function | summarize a provider-valid snapshot range and replace it through CAS |
|
|
308
|
+
| `selectCompactableHistory` | function | which oldest whole complete turns may be summarised away — the half of compaction that needs no store (→ ADR 0142) |
|
|
309
|
+
| `SelectCompactableHistoryOptions` / `CompactableHistory` | _type_ | message list, retained-turn count and evidence policy in; `leadingSummary`, `compactable` and `retained` out |
|
|
310
|
+
| `createAgentSessionCoordinator` | function | strict process-local queue/interrupt/supersede lifecycle |
|
|
311
|
+
| `AgentRuntimeStopPolicy` | _type_ | named stop rule persisted and published on policy stop; `when` receives the AI SDK `steps` plus the run context `prepareStep` gets (`context`, `run`, `signal`, `toolFenceLifecycle`, `contextUsage`) |
|
|
312
|
+
| `AgentRuntimePrepareStep` | _type_ | per-run controlled step callback with typed domain context and managed run signal/fence |
|
|
313
|
+
| `AgentContextOverflowError` | class | deliberate application budget refusal thrown from `loop.prepareStep`; terminalizes as `context_overflow` without classifying arbitrary error text |
|
|
314
|
+
| `AgentRuntimeRecordIds` | _type_ | optional caller-provided input, run and assistant IDs for stable application records |
|
|
315
|
+
| `AgentRuntimeAdmission` | _type_ | canonical committed input, assigned run, pending assistant projection, compatibility IDs and snapshot version |
|
|
316
|
+
| `AgentAdmissionEventSchema` | schema | post-commit admission projection; removes store rereads but does not imply exactly-once delivery |
|
|
317
|
+
| `AgentRunMetricsSchema` | schema | optional provenance-aware usage and timings; `partial` says the provider never reported the run finished, so the figure beside it is not a confirmed total |
|
|
318
|
+
| `AgentRuntimeRecoverOptions` | _type_ | bounded paged startup recovery with causal per-conversation scheduling, context resolver and explicit evidence policy |
|
|
319
|
+
| `AgentRuntimeAbandonInput` | _type_ | one known orphan identity, expected revision and mandatory stale-owner evidence for `runtime.abandon()` |
|
|
320
|
+
| `AgentRuntimeConflictError` | class | thrown when a store mutation loses to a concurrent writer — catchable by type from `stitchkit/agent-runtime` |
|
|
321
|
+
| `AgentRunUnsettledError` | class | rejects `result` when the store never answered: `.run` is still active with no executor, close it with `runtime.abandon()` |
|
|
322
|
+
| `AgentSessionCloseOptions` | _type_ | `gracePeriodMs` for natural settlement, then abort, then `forceTimeoutMs` for bounded settlement after it |
|
|
323
|
+
| `AgentSessionCloseResult` | _type_ | what `close()` achieved: `settled`, or `timedOut` with `remaining` runs still in flight. Only omitting `forceTimeoutMs` guarantees nothing is in flight on return |
|
|
324
|
+
| `AgentHistoryProjectionOptions` | _type_ | storage-neutral file resolver, explicit unresolved-file behavior, and how an interrupted turn reaches the model (`interruptedAssistant`) |
|
|
325
|
+
| `createAgentToolFenceLifecycle` | function | pre-effect and post-effect run ownership fence for `mountAgent`; compose beside application idempotency for [durable operations](../guide/mcp-and-agents.md#durable-application-owned-execution) |
|
|
326
|
+
| `AgentRuntimeEventSchema` | schema | transient stream lifecycle plus post-commit admission/checkpoint/run-state/run-operation/terminal projections |
|
|
327
|
+
| `AgentRunOperationKindSchema` / `AgentRunOperationPhaseSchema` / `AgentRunOperationSchema` / `AgentRunOperation` | schemas / _type_ | latest durable model-request or compaction phase with operation/step identity and original timestamps; request admission is awaited before provider invocation |
|
|
328
|
+
| `RecordRunOperationSchema` / `RecordRunOperation` | schema / _type_ | owner/fencing/revision-checked mutation of `AgentRun.lastOperation` |
|
|
329
|
+
| `createAgentObservability` | function | separate agent-run sink over the shared bounded observability lifecycle |
|
|
330
|
+
| `AgentProviderResponseSchema` / `AgentProviderResponse` | schema / _type_ | provider-assigned response ID and the optional upstream provider the model's own adapter resolves, shared by `step-finished.response` and durable `provider/response` facts |
|
|
331
|
+
| `AgentStepFinishedEventSchema` / `AgentStepFinishedEvent` | schema / _type_ | one completed provider step with required usage and provider response identity |
|
|
107
332
|
|
|
108
|
-
###
|
|
333
|
+
### Durable capability layer
|
|
109
334
|
|
|
110
335
|
| Export | Kind | Summary |
|
|
111
336
|
|--------|------|---------|
|
|
112
|
-
| `
|
|
113
|
-
| `
|
|
337
|
+
| `AgentConversationArchiveSchema` / `AgentConversationArchive` / `encodeAgentConversationArchive` / `decodeAgentConversationArchive` / `canonicalAgentJson` | schema / _type_ / functions | canonical validated conversation archive (`canonicalAgentJson` is `canonicalJson` with the node and byte limits at their maximum, reading `-0` as `0` like `z.json()`) with exact ledger events, recovery projection and durable spill payloads |
|
|
338
|
+
| `AgentStoreEventEnvelopeSchema` / `AgentStoreEventEnvelope` / `AgentStoreEventKindSchema` / `AgentStoreEventKind` / `AgentStoreEventPageSchema` / `AgentStoreEventPage` | schema / _type_ | append-only event envelope, closed current vocabulary (including `provider/request` and `provider/response`) and bounded page |
|
|
339
|
+
| `AppendAgentStoreEventSchema` / `AppendAgentStoreEvent` / `ReadAgentStoreEventsSchema` / `ReadAgentStoreEvents` | schema / _type_ | required append and bounded-read store contracts |
|
|
340
|
+
| `AgentStoreTransitionSchema` / `AgentStoreTransition` / `AgentStoreEventDraft` / `AgentStoreEventDecodeAccepted` / `AgentStoreEventDecodeIgnored` / `AgentStoreEventDecodeResult` / `decodeAgentStoreEvent` | schema / _types_ / function | normalized runtime mutations, append drafts and strict current/ignorable future-event decoding outcomes |
|
|
341
|
+
| `AgentStoreTransitionRecordSchema` / `AgentStoreTransitionRecord` | schema / _type_ | persisted journal payloads: full runtime mutations or hash-only streaming checkpoint observations with numeric part/byte counts; inspection does not authorize replay |
|
|
342
|
+
| `defineAgentProjection` / `AgentProjectionDefinition` / `AgentProjectionValue` / `createAgentProjectionRegistry` / `createSqliteAgentProjectionStore` | functions / _type_ | deterministic folds with persisted version and honest `uptoSeq` checkpoints |
|
|
343
|
+
| `agentSummaryProjection` / `agentUsageProjection` / `agentOutlineProjection` | constants | built-in list summary, provenance-carrying usage and request outline projections |
|
|
344
|
+
| `agentConversationCardProjection` / `agentStateSlotsProjection` / `agentScheduleSummaryProjection` | constants | focused card, durable-state and schedule lifecycle projections |
|
|
345
|
+
| `defineStateSlot` / `AgentStateSlotDefinition` / `AgentStateSlotStore` / `AgentStateSlotValue` / `AnyAgentStateSlot` / `createAgentStateSlotStore` / `renderAgentStateSlots` | functions / _types_ | typed durable state written as ledger events and injected on every provider request |
|
|
346
|
+
| `agentGoalStateSlot` / `agentTodoStateSlot` / `createAgentStateTools` | constants / function | built-in goal/todo state and bound `goal_*` / `todo_write` Agent tools |
|
|
347
|
+
| `AgentSandboxGradeSchema` / `AgentSandboxGrade` / `AgentSandboxRestrictionSchema` / `AgentSandboxRestriction` / `AgentProcessSandbox` | schema / _type_ | host-provided process sandbox capability and explicit restriction vocabulary |
|
|
348
|
+
| `probeAgentProcessSandbox` / `missingSandboxRestrictions` / `recordAgentSandboxProbe` | functions | probe cached per sandbox object (keep the sandbox long-lived), fail-closed required-gap calculation and durable probe record; a probe that throws or returns no valid grade resolves to `unavailable` with a fixed reason, its cause emitted as a process warning (the coding tools instead carry it as the refusal's `cause` to the mount's `onToolError` hook) |
|
|
349
|
+
| `AgentSandboxProcess` / `AgentSandboxOutputStream` | _types_ | structural child/output interface for optional lifecycle-owned `AgentProcessSandbox.spawn`, without Node ambient type dependencies |
|
|
350
|
+
| `AgentEventSearchResultSchema` / `AgentEventSearchResult` / `createSqliteAgentEventSearch` / `createAgentEventSearchTools` | schema / _type_ / functions | authorized FTS5 search with exact event addresses and `session_*` tools |
|
|
351
|
+
| `createSqliteAgentSpillStore` | function | durable content-address-checked artifact storage, bounded read/search, retention facts and archive participation |
|
|
352
|
+
| `AgentScheduleSchema` / `AgentSchedule` / `AgentScheduleService` / `AgentScheduleDeliveryOutcomeSchema` / `AgentScheduleDeliveryOutcome` / `createAgentScheduleService` / `createAgentScheduleTools` | schemas / _types_ / functions | durable `at`/`after`/timezone-explicit `every`, indexed retry eligibility, typed retry/terminal failure (any other returned value delivers), `maxAttempts` (default 1000) per occurrence — a one-off ends `failed`, a recurring schedule skips to its next slot — bounded dispatch and fenced stable occurrence identity (ADR 0202) |
|
|
353
|
+
| `AgentChildBudgetSchema` / `AgentChildBudget` / `AgentChildStateSchema` / `AgentChildState` / `AgentChildRecordSchema` / `AgentChildRecord` | schema / _type_ | durable child graph, bounded seed and measured budget state |
|
|
354
|
+
| `AgentChildBlockingKindSchema` / `AgentChildBlockingKind` / `AgentChildBlockingSourceSchema` / `AgentChildBlockingSource` / `AgentChildBlockingEventSchema` / `AgentChildBlockingEvent` / `AgentChildBlockingDecision` | schemas / _types_ | parent-owned request identities; responses discriminate approval decisions from JSON input values |
|
|
355
|
+
| `AgentChildHandle` / `AgentChildManager` / `SqliteAgentChildManagerConfig` / `createSqliteAgentChildManager` / `createAgentChildTools` / `agentChildBudgetStopPolicy` | _type_ / functions | host execution port, child lifecycle, cascade (given to `createAgentRuntime` as `children`), messaging, Agent tools, and the child runtime's own budget stop policy — `recordStepUsage` at every step boundary, `policy_stop` as `child-budget` when spent |
|
|
356
|
+
| `AgentToolDefinition` | _type_ | peer-neutral shape returned by the bound agent-only state, search, schedule and child tool factories |
|
|
357
|
+
| `AgentProviderStreamCutError` | class | explicit retryable provider stream truncation evidence |
|
|
358
|
+
|
|
359
|
+
### Complete runtime inventory
|
|
360
|
+
|
|
361
|
+
The entrypoint deliberately exports the schemas beside their inferred types so persistence and
|
|
362
|
+
transport adapters validate the same records. Runtime composition types are `AgentRuntime`,
|
|
363
|
+
`AgentRuntimeConfig`, `AgentRuntimeInput`, `AgentRuntimeProtocolInput`, `AgentRuntimeRunContext`,
|
|
364
|
+
`AgentRuntimeResult`, `AgentRuntimeInterruptInput`, `AgentRuntimeAbandonInput`, `AgentRuntimeRecoveryInput`,
|
|
365
|
+
`AgentRuntimeRecoveryDecision`, `AgentRuntimeRecoveryOutcome`, `AgentRuntimePublisher`,
|
|
366
|
+
`AgentInputPolicy`, `AgentStopReason`, `AgentCoordinatedRun`, `AgentRunTicket`,
|
|
367
|
+
`AgentSessionCoordinator`, `AgentCompactionContext`, `AgentCompactionResult` and
|
|
368
|
+
`StructuredCompactionConfig`.
|
|
369
|
+
|
|
370
|
+
A provider refusal is classified rather than phrased. `classifyProviderFailure` returns an
|
|
371
|
+
`AgentProviderFailure` — an `AgentProviderFailureReason` (`insufficient-credits`, `rate-limited`,
|
|
372
|
+
`model-unavailable`, `context-overflow`, `timeout`, `cancelled`, `unknown`), the provider's `status`
|
|
373
|
+
when it supplied one, whether the same request is `retryable` unchanged, and the `evidence` the
|
|
374
|
+
answer rests on: `status` is the provider stating its own answer, `message` is us reading its prose,
|
|
375
|
+
and `none` is an honest refusal to guess. The sentence a user reads stays with the application —
|
|
376
|
+
its tone and its decision about what to admit are not the core's to make. `isToolResultFailure`
|
|
377
|
+
recognises a failure carried inside a *successful* tool result, in both the bare and the
|
|
378
|
+
`{ value: … }` envelope. Both are plain functions and need no runtime. → ADR 0141
|
|
379
|
+
|
|
380
|
+
`normalizeOpenRouterUsage` is the same normalisation `openRouterProvider`
|
|
381
|
+
applies, exported so an application calling the SDK directly gets provenance-correct numbers
|
|
382
|
+
without adopting the runtime. Pass each completed SDK step's usage, including `raw`.
|
|
383
|
+
Token provenance comes from the original OpenRouter fields: missing fields remain
|
|
384
|
+
`unavailable`, even when the SDK substitutes zero. Aggregate usage without `raw` cannot
|
|
385
|
+
establish reported token counts. Explicit zero remains `provider-reported`; cost is never
|
|
386
|
+
estimated from token prices.
|
|
387
|
+
|
|
388
|
+
`AgentContextUsage` reaches every step through `AgentRuntimeRunContext.contextUsage`: how full the
|
|
389
|
+
model's context is, as `usedTokens` (an `AgentUsageValue`, so it carries the provenance that says
|
|
390
|
+
where the number came from) beside the model's declared `contextWindow`. It is the **last completed
|
|
391
|
+
step's prompt size**, not the run's cumulative input tokens — cumulative counts every step's prompt
|
|
392
|
+
again and is a multiple of the real fill. Before the first step lands there is no provider-reported
|
|
393
|
+
number and the provenance is `unavailable`, which is a different fact from zero. No fraction is
|
|
394
|
+
exposed: dividing is one line where it is rendered, and the output reserve belongs to the
|
|
395
|
+
consumer's prompt budget rather than to this layer.
|
|
396
|
+
|
|
397
|
+
Canonical protocol exports are `AgentProtocol`, `AgentProtocolConfig`, `AgentTerminalAcceptance`,
|
|
398
|
+
`AgentTerminalAcceptanceInput`, `hasAgentTerminalOutput`, `AgentRecordIdSchema`, `AgentRecordVersionSchema`,
|
|
399
|
+
`AgentTimestampSchema`, `AgentJsonObjectSchema`, `AgentProviderEnvelopeSchema`,
|
|
400
|
+
`AgentProviderEnvelope`, `AgentMessagePartSchema`, `AgentMessagePart`, `AgentTextPartSchema`,
|
|
401
|
+
`AgentReasoningPartSchema`, `AgentFilePartSchema`, `AgentSourcePartSchema`,
|
|
402
|
+
`AgentToolCallPartSchema`, `AgentToolResultPartSchema`, `AgentOpaquePartSchema`,
|
|
403
|
+
`AgentControlPartSchema`, `AgentMessageRoleSchema`, `AgentMessageStatusSchema`, `AgentMessage`,
|
|
404
|
+
`AgentAssistantPlaceholderSchema`, `AgentAssistantPlaceholder`, `AgentRunStateSchema`,
|
|
405
|
+
`AgentTerminalReasonSchema`, `AgentTerminalReason`, `AgentRunQueuePrioritySchema`,
|
|
406
|
+
`AgentRunQueuePriority`, `AgentRun`, `AgentSnapshot`,
|
|
407
|
+
`AgentUsageValueSchema`, `AgentCostValueSchema`, `AgentUsageSchema`, `AgentUsage` and
|
|
408
|
+
`AgentRunMetrics`.
|
|
409
|
+
|
|
410
|
+
`AgentProvenanceSchema` / `AgentProvenance` is the entrypoint's single vocabulary for **how a
|
|
411
|
+
number came to be known**: `provider-reported` (the provider stated it about a request it served),
|
|
412
|
+
`measured` (this process counted it exactly, before any request was made), `computed` (arithmetic
|
|
413
|
+
over other values — a sum of exact numbers is still `computed`), `estimated` (a heuristic) and
|
|
414
|
+
`unavailable` (not known, so `value` is absent, which is a different fact from a reported zero).
|
|
415
|
+
Each surface declares the subset it can produce: `AgentUsageValueSchema` and `AgentCostValueSchema`
|
|
416
|
+
describe a request that has already happened and never say `measured`; `AgentTokenCountSchema`
|
|
417
|
+
describes a prompt being composed and never says `provider-reported`. Every token count is an
|
|
418
|
+
integer — `AgentUsageValueSchema` and `AgentTokenCountSchema` refuse a fractional `value`, and a
|
|
419
|
+
provider figure that is not a whole number is normalised to `unavailable` rather than thrown.
|
|
420
|
+
`AgentCostValueSchema.value` stays fractional, because money is.
|
|
421
|
+
|
|
422
|
+
`runs.inputPolicy` takes `queue` (default), `inject`, `interrupt`, `interrupt-next` or `supersede`, or a function of
|
|
423
|
+
the raw input returning one. `inject` lets a run in flight take a newly arrived input into its prompt
|
|
424
|
+
at a step boundary and answer it too; the absorption is committed in the **same transaction** as that
|
|
425
|
+
run's terminal record, via `CommitRunTerminal.absorb`, so a run that ends any other way leaves an
|
|
426
|
+
ordinary queued successor. The absorbed run ends with `terminalReason: 'absorbed'`, run state
|
|
427
|
+
`'superseded'`, `absorbedIntoRunId` naming the run that answered it, and **no assistant message of
|
|
428
|
+
its own**; a submission on its idempotency key resolves through that pointer to the answer
|
|
429
|
+
(→ ADR 0113).
|
|
430
|
+
|
|
431
|
+
`interrupt-next` interrupts the active run, waits for its real settlement and then executes the new
|
|
432
|
+
input before ordinary pending work. Ordinary work is not dropped or re-admitted, and urgent work is
|
|
433
|
+
FIFO within its own class. `AgentRun.queuePriority` persists the pending class;
|
|
434
|
+
`AgentRun.executionSequence` persists the actual first-acquisition order, so recovery and canonical
|
|
435
|
+
history preserve the same `A → C → B` order across equal timestamps and scan pages (→ ADR 0127).
|
|
436
|
+
|
|
437
|
+
With `queue`, a durable successor admission is not prompt eligibility: the current executor sees
|
|
438
|
+
only records through its own run boundary. Snapshot history is normalized to causal turn order
|
|
439
|
+
(assigned input(s), assistant, then successor input(s)) even when the storage codec physically
|
|
440
|
+
appended the successor before the predecessor checkpoint.
|
|
441
|
+
|
|
442
|
+
`AgentRuntimeStore` has two **bounded** reads beside `loadSnapshot`:
|
|
443
|
+
`loadRun({ conversationId, runId })` returns an `AgentRunView` — the run, the conversation version it
|
|
444
|
+
was read at, and the retained answer once the run is terminal — or `undefined`; `listActiveRuns(conversationId)`
|
|
445
|
+
returns the runs that have not ended in durable execution/priority order. Neither reads history, so
|
|
446
|
+
neither grows with the length of the conversation, and neither needs anything new from
|
|
447
|
+
`AgentRuntimeStoreDriver`. `loadSnapshot` and every mutation result still carry the whole
|
|
448
|
+
conversation — that is what the store's reducer validates against, and what the runtime builds a
|
|
449
|
+
prompt from (→ ADR 0112).
|
|
450
|
+
|
|
451
|
+
`AgentRuntimeStore.purgeConversation` is optional; `purgeAgentConversation(store, input)` explicitly
|
|
452
|
+
handles unsupported stores. Official memory and initialized SQLite stores refuse active runs,
|
|
453
|
+
remove every owned payload and reserve the conversation ID permanently. Empty snapshots are not
|
|
454
|
+
deletion receipts. Consumer metadata, files, event logs and UI cache invalidation remain outside
|
|
455
|
+
the transaction. See [purging a conversation](../guide/agent-runtime.md#purging-a-conversation).
|
|
456
|
+
|
|
457
|
+
Store command/result exports are `AcceptInputAndAssignRun`, `AcceptInputAndAssignRunSchema`,
|
|
458
|
+
`AcquireAgentRun`, `AcquireAgentRunSchema`, `CheckpointRunAssistant`,
|
|
459
|
+
`CheckpointRunAssistantSchema`, `CommitRunTerminal`, `CommitRunTerminalSchema`,
|
|
460
|
+
`RequestRunInterrupt`, `RequestRunInterruptSchema`, `AgentRunView`, `AgentRunViewSchema`,
|
|
461
|
+
`runStateForTerminalReason`,
|
|
462
|
+
`ACTIVE_AGENT_RUN_STATES`, `RecoverAgentRun`, `ReplaceCompactedRange`,
|
|
463
|
+
`ReplaceCompactedRangeSchema`, `AgentStoreMutationResult`, `AgentStoreMutationResultSchema`,
|
|
464
|
+
`AgentStoreAppliedSchema`, `AgentStoreConflictSchema`, `AgentStoreDuplicateSchema`,
|
|
465
|
+
`AgentStoreNotFoundSchema`, `AgentAdmissionReceipt`, `AgentAdmissionReceiptSchema`,
|
|
466
|
+
`AgentRuntimeHead`, `AgentStoredRun`, `AgentStoreCompareAndSwapResult`, `AgentHistoryMutation`,
|
|
467
|
+
`AgentRecoverableDescriptor`, `AgentRecoverableDescriptorSchema`, `AgentRecoverablePage` and
|
|
468
|
+
`AgentRecoverablePageSchema`.
|
|
469
|
+
|
|
470
|
+
History and context-budget exports are `projectAgentHistoryDetailed`,
|
|
471
|
+
`AgentHistoryProjectionDecision`, `AgentHistoryProjectionResult`, `selectAgentHistory`,
|
|
472
|
+
`SelectAgentHistoryOptions`, `AgentHistoryBudgetDecision`, `AgentHistoryBudgetResult`,
|
|
473
|
+
`AgentPromptBudget`, `AgentPromptSection`, `AgentPromptSectionContext`, `AgentTokenCount`,
|
|
474
|
+
`AgentTokenCountSchema`, `ComposeAgentPromptOptions` and `ComposedAgentPrompt`. Whole-turn history
|
|
475
|
+
selection never splits a tool chronology and reports why every canonical record was retained or
|
|
476
|
+
removed. `AgentHistoryEvidencePolicy` is the shared opt-in for marked failed-assistant evidence in
|
|
477
|
+
projection, budgeting and structured compaction; `isAssistantHistoryEvidence` applies it. The
|
|
478
|
+
compatibility default omits it. Approval message schemas are
|
|
479
|
+
`AgentToolApprovalRequestPartSchema` and `AgentToolApprovalResponsePartSchema`.
|
|
480
|
+
|
|
481
|
+
With `failedAssistant: 'assistant-marked'`, `selectCompactableHistory` and
|
|
482
|
+
`structuredCompaction` admit a failed prefix only when the entire turn's tool chronology
|
|
483
|
+
is complete. `eligibleMessages` stays raw: the summarizer must use the same policy in
|
|
484
|
+
`projectAgentHistoryDetailed` and preserve non-success/uncertain outcomes in its summary.
|
|
485
|
+
Even an empty opted-in failed assistant carries a non-success marker in that projection.
|
|
486
|
+
Use `incompleteToolTurn: 'error'` to refuse a range the projector cannot represent.
|
|
487
|
+
Compaction never deletes canonical effect events or the retained terminal receipt;
|
|
488
|
+
chronological completeness does not settle an external effect. See the
|
|
489
|
+
[failed-prefix recovery contract](../guide/agent-runtime.md#recovering-a-prefix-after-a-failed-turn).
|
|
490
|
+
|
|
491
|
+
Model exports are `AgentLanguageModelProvider`, `AgentModelCapability`,
|
|
492
|
+
`AgentModelCapabilitySchema`, `AgentModelDescriptor`,
|
|
493
|
+
`AgentModelDescriptorSchema`, `AgentModelRegistry`, `AgentModelRegistryConfig`,
|
|
494
|
+
`AgentModelRegistrySnapshot`, `AgentModelRegistrySnapshotSchema`, `AgentModelSnapshotPolicy`,
|
|
495
|
+
`AgentResolvedModel` and `validateAgentModelSnapshot`. Registry `preflight` validates availability,
|
|
496
|
+
provider and required capabilities without constructing the model; runtime `models.preflight`
|
|
497
|
+
runs before durable admission.
|
|
498
|
+
|
|
499
|
+
Delivery exports are `AgentAdmissionEventSchema`, `AgentAttemptResetEventSchema`, `AgentCheckpointEventSchema`,
|
|
500
|
+
`AgentRunStateEventSchema`, `AgentRunOperationEventSchema`, `AgentTerminalEventSchema`,
|
|
501
|
+
`AgentTransientDeltaEventSchema`,
|
|
502
|
+
`AgentReasoningStartEventSchema`, `AgentReasoningDeltaEventSchema`,
|
|
503
|
+
`AgentReasoningEndEventSchema`, `AgentToolStatusEventSchema`, `AgentToolProgressEventSchema` (what a
|
|
504
|
+
running tool reported through `ctx.reportProgress`, transient and never part of the model's input),
|
|
505
|
+
`AgentRuntimeEvent`,
|
|
506
|
+
`AgentRuntimeEventCursor`, `AgentRuntimeEventCursorSchema`, `AgentRuntimeCursorAdvance`,
|
|
507
|
+
`advanceAgentRuntimeEventCursor`, `agentDurableEventId`, `AgentRuntimeEventSink`,
|
|
508
|
+
`AgentRuntimeEventSinkConfig` and `createAgentRuntimeEventSink`. Cursor gaps require a canonical
|
|
509
|
+
snapshot reload; the bounded sink isolates transport failure and supports a typed projection step.
|
|
510
|
+
|
|
511
|
+
Managed effects and operator telemetry additionally export `AgentToolFenceConfig`,
|
|
512
|
+
`AgentToolFenceContext`, `AgentObservability`, `AgentRunEvent`, `AgentRunEventSchema`,
|
|
513
|
+
`AgentRunStartedEvent`, `AgentRunStartedEventSchema`, `AgentStepFinishedEvent`,
|
|
514
|
+
`AgentStepFinishedEventSchema`, `AgentRunTerminalEvent`, `AgentRunTerminalEventSchema`,
|
|
515
|
+
`AgentRunSinkConfig`, `AgentRunSinkDrop` and `AgentRunSinkError`. A monotonic run `fencingToken`
|
|
516
|
+
may accompany checkpoint/terminal writes and tool context; internal causes are redacted unless an
|
|
517
|
+
operator-only observability sink explicitly opts in.
|
|
518
|
+
|
|
519
|
+
### Completion and agent invocation receipts
|
|
520
|
+
|
|
521
|
+
`createModelInvocationLedger` constructs a `ModelInvocationLedger` from
|
|
522
|
+
`ModelInvocationConfig`: the existing store and model registry, a 32-byte payload
|
|
523
|
+
key, required host authorization, optional bounded payload size and `onAttempt`.
|
|
524
|
+
`complete(input, context, signal?)` executes only the supplied prompt, with no tools
|
|
525
|
+
or framework instructions; repeated keys return the existing invocation ID. It
|
|
526
|
+
resolves `{ invocationId, outcome, text?, receiptError? }`: `receiptError` says a
|
|
527
|
+
receipt could not be written and never changes `outcome` or drops `text`.
|
|
528
|
+
`read(input, context)` returns a bounded event page shared by agent and completion;
|
|
529
|
+
`readPayload(input, context)` requires a separate authorization action to decrypt
|
|
530
|
+
one protected artifact. See the [guide and migration example](../guide/agent-runtime.md#plain-completions-and-shared-invocation-receipts).
|
|
531
|
+
|
|
532
|
+
| Export | Kind | Purpose |
|
|
533
|
+
| --- | --- | --- |
|
|
534
|
+
| `CompletionInvocationInputSchema` / `CompletionInvocationInput` | schema/type | strict prompt, model-attempt list, deadline, idempotency key and trace input |
|
|
535
|
+
| `ModelInvocationTraceSchema` / `ModelInvocationTrace` | schema/type | operation, purpose, project, parent trace and optional experiment/case/profile |
|
|
536
|
+
| `ModelInvocationRecordSchema` / `ModelInvocationRecord` | schema/type | discriminated invocation start/finish and per-attempt requested/sent/effective evidence |
|
|
537
|
+
| `ModelInvocationAttemptContext` | type | conversation, operation, invocation, attempt, step and optional agent run identity |
|
|
538
|
+
| `currentModelInvocationAttempt` | function | returns causal IDs inside the provider transport; undefined outside an invocation |
|
|
539
|
+
|
|
540
|
+
The runtime `invocations` option takes this ledger and a trace callback; it requires
|
|
541
|
+
the same store and preserves the existing tool loop. `AgentRuntimeStore.appendEventOnce`
|
|
542
|
+
is an optional atomic capability required by receipt admission, and
|
|
543
|
+
`AgentRuntimeStore.findEventOnce` reads the event it wrote by kind and key. Built-in
|
|
544
|
+
stores supply both; custom adapters must honor the once-only transaction contract.
|
|
545
|
+
A driver's optional `events.find(transaction, { conversationId, eventId })` makes
|
|
546
|
+
both one lookup instead of a scan of the conversation log.
|