@agen-ai/agent-runtime 0.3.1 → 0.4.1

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.
Files changed (50) hide show
  1. package/README.md +288 -29
  2. package/dist/adapterValidation.d.ts +1 -1
  3. package/dist/adapterValidation.js +199 -92
  4. package/dist/artifacts.js +0 -1
  5. package/dist/contractErrors.d.ts +16 -3
  6. package/dist/contractErrors.js +42 -6
  7. package/dist/hostBindings/index.d.ts +4 -0
  8. package/dist/hostBindings/index.js +9 -0
  9. package/dist/hostBindings/lifetime.d.ts +25 -0
  10. package/dist/hostBindings/lifetime.js +147 -0
  11. package/dist/hostBindings/opening.d.ts +14 -0
  12. package/dist/hostBindings/opening.js +82 -0
  13. package/dist/hostBindings/schema.d.ts +9 -0
  14. package/dist/hostBindings/schema.js +169 -0
  15. package/dist/hostBindings/types.d.ts +71 -0
  16. package/dist/hostBindings/types.js +0 -0
  17. package/dist/hostBindings/validation.d.ts +14 -0
  18. package/dist/hostBindings/validation.js +107 -0
  19. package/dist/index.d.ts +3 -0
  20. package/dist/index.js +7 -0
  21. package/dist/internal/objectShape.d.ts +2 -0
  22. package/dist/internal/objectShape.js +7 -0
  23. package/dist/outputValidation.js +3 -2
  24. package/dist/providerDriver.js +0 -1
  25. package/dist/providerInstanceRegistry.js +2 -1
  26. package/dist/sessionCleanup.d.ts +9 -0
  27. package/dist/sessionCleanup.js +17 -0
  28. package/dist/sessionInteractions/index.d.ts +2 -0
  29. package/dist/sessionInteractions/index.js +1 -0
  30. package/dist/sessionInteractions/lifetime.d.ts +52 -0
  31. package/dist/sessionInteractions/lifetime.js +251 -0
  32. package/dist/sessionInteractions/request.d.ts +42 -0
  33. package/dist/sessionInteractions/request.js +308 -0
  34. package/dist/sessionInteractions/types.d.ts +54 -0
  35. package/dist/sessionInteractions/types.js +10 -0
  36. package/dist/sessionInteractions/validation.d.ts +21 -0
  37. package/dist/sessionInteractions/validation.js +119 -0
  38. package/dist/sessionValidation.d.ts +15 -2
  39. package/dist/sessionValidation.js +155 -318
  40. package/dist/sessions.d.ts +31 -4
  41. package/dist/testing/conformance.d.ts +3 -3
  42. package/dist/testing/conformance.js +24 -31
  43. package/dist/testing/fakeProvider.js +59 -49
  44. package/dist/turnExecution/execution.d.ts +26 -0
  45. package/dist/turnExecution/execution.js +214 -0
  46. package/dist/turnExecution/receipts.d.ts +6 -0
  47. package/dist/turnExecution/receipts.js +39 -0
  48. package/dist/turnExecution/requests.d.ts +19 -0
  49. package/dist/turnExecution/requests.js +56 -0
  50. package/package.json +2 -2
package/README.md CHANGED
@@ -8,8 +8,11 @@ sessions; each returned session owns its binding and conversation-local operatio
8
8
 
9
9
  The runtime depends only on `@agen-ai/agent-protocol`. It has no concept of tenants, SaaS
10
10
  workspaces, assigned users, database rows, persistence sequence, visibility, billing, host boots,
11
- leases, or storage policy. A host must authorize and select an instance before calling this SPI.
12
- This source package implements Agent Protocol V9 as part of the coordinated SDK `0.3.1` contract.
11
+ distributed leases, or storage policy. A host must authorize and select an instance before calling this SPI.
12
+ This source package implements Agent Protocol V11 at coordinated SDK version `0.4.1`,
13
+ which remains unpublished. The published release remains `0.4.0` with V10. The source candidate
14
+ also includes the additive session-interaction API.
15
+ Upgrade consumers from `0.3.1` using the coordinated release and its migration guide.
13
16
  The SDK contract version is independent of private transport and product persistence versions. This
14
17
  is intentionally one coordinated tuple rather than a deployable mixed-version graph.
15
18
 
@@ -17,7 +20,7 @@ is intentionally one coordinated tuple rather than a deployable mixed-version gr
17
20
 
18
21
  - `@agen-ai/agent-runtime` exports the public driver, instance, adapter, session, output,
19
22
  readiness, account-quota port validation, bounded-evidence, artifact-candidate,
20
- capability-bound interaction validation, and registry APIs.
23
+ capability-bound interaction validation, session-lifetime interaction and cleanup APIs, and registry APIs.
21
24
  - `@agen-ai/agent-runtime/environment` exports the instance discovery and session observation ports.
22
25
  - `@agen-ai/agent-runtime/testing` exports the deterministic fake provider and reusable
23
26
  conformance runner.
@@ -27,8 +30,10 @@ is intentionally one coordinated tuple rather than a deployable mixed-version gr
27
30
  1. Define an `AgentProviderDriver` with `defineAgentProviderDriver`.
28
31
  2. Give caller-owned instance definitions to `createAgentProviderRegistry`.
29
32
  3. Select a materialized instance by opaque `instanceId`.
30
- 4. Create, resume, or branch a provider session through its adapter.
31
- 5. Consume each `runTurn` or `resolveRequest` output stream incrementally. Neutral `AgentEvent`
33
+ 4. Create, resume, or branch a provider session through its adapter. If supported and needed,
34
+ supply the session-interaction handler on that opening input before calling the adapter.
35
+ 5. Call `startTurn` and consume its single `outputs` stream incrementally. Submit human answers with
36
+ the same execution's `resolveRequest`, which returns an independent delivery receipt. Neutral `AgentEvent`
32
37
  output carries bounded provider source evidence atomically. A `request.opened` output may also
33
38
  carry separately bounded, non-truncated provider request context for continuation; lifecycle,
34
39
  authentication, artifact, and standalone diagnostic evidence remain separate output variants.
@@ -70,33 +75,91 @@ Explicit iterator return and normal end join native cleanup for at most 1,000 ms
70
75
  Approval continuations are refusal-first. Before delegating to the candidate adapter, the
71
76
  validated session proves that the request is still pending and unexpired and that a selected
72
77
  `optionId` was offered by that exact request. Provider-emitted approval requests must correlate to
73
- a live item or exact proposed-plan artifact, and every option must fit an advertised
74
- persistence/scope mode. Item identities are monotonic throughout a turn, including every request
78
+ a live item or exact proposed-plan artifact. A scoped consequence must fit an exact advertised
79
+ persistence/scope mode; a provider-managed remembrance consequence requires
80
+ `providerManagedRemembrance: true` and retains explicit unknown duration and applicability.
81
+ A delivered answer does not prove that a provider wrote a remembered rule. Exact offered IDs,
82
+ once-only response entry, and uncertain-delivery fencing remain unchanged.
83
+ Present every offered option's decision and consequence, then return the exact option chosen by
84
+ the caller; options with the same immediate decision can have different consequences. A human
85
+ handler should run independently while the original `execution.outputs` reader keeps consuming
86
+ progress. Resolve on that same execution, inspect its receipt, and retain its output and cleanup
87
+ owners through terminal settlement. A remembered answer creates no SDK rule or future automatic
88
+ answer; later requests still need their own offered choice. An uncertain answer must not be replayed.
89
+
90
+ Item identities are monotonic throughout a turn, including every request
75
91
  continuation: an adapter cannot restart an observed identity, change its kind, erase prior progress
76
92
  through an unknown-status update, regress it from in-progress to pending, or revive it after a
77
93
  terminal event or status. An `item.completed` event must carry `completed`, `failed`, or `canceled`
78
94
  status. Completion-only snapshots remain valid when no earlier lifecycle event was observed.
79
95
 
80
- The host should serialize mutating operations for a given session. Separate session objects may
81
- run concurrently, so provider implementations must isolate their conversation-local state.
96
+ A session reserves one turn execution synchronously at `startTurn`. Native execution stays lazy until
97
+ its first output pull; an unused handle has no provider effects. Separate sessions run concurrently.
98
+ The execution's `outputs` has exactly one consumer and one outstanding pull. Its ownership continues
99
+ across human requests until native terminal output, entered response/control settlement, and cleanup.
82
100
 
83
101
  Materialization-scoped context usage remains monotonic only within one native provider process. A
84
102
  provider that replaces that process emits a `process.started` lifecycle output as the explicit
85
103
  boundary before reporting usage from the replacement. Validation then clears only the
86
104
  `materialization` occupancy, cumulative counters, and compaction allowance; logical `session`
87
105
  measurements remain continuous.
88
- `runTurn` and `resolveRequest` both preserve consumer backpressure: the provider does not resume
89
- until the consumer requests the next output. Each stream must end at a completed turn or exactly
90
- one newly pending request. If a consumer abandons a stream, a provider throws, or either stream
91
- ends before that stable boundary, the validated session becomes unusable and must be closed rather
92
- than retried. The validated `runTurn` input may observe `onProviderExecutionStarted`; validation
93
- invokes it exactly at candidate-port delegation, after runtime prechecks pass, and never forwards it
94
- to the candidate adapter. A delegated mutating operation that throws or returns an invalid result
95
- has the same effect. Pre-aborted operations fail with `AbortError`; close and disposal must be safe
96
- to call repeatedly. An accepted interruption of an already-waiting turn does not prove that the
97
- turn terminalized; unless the result also carries a terminal event, the validated session becomes
98
- unusable and must be closed and rematerialized. A close failure makes the session unusable while
99
- leaving close itself retryable.
106
+ `startTurn(input)` returns `{ turnId, outputs, resolveRequest }`. `outputs` preserves per-output
107
+ backpressure and stays open during `waiting_for_request`; the consumer can call
108
+ `execution.resolveRequest({ resolution })` as soon as it receives `request.opened`, before its next
109
+ pull. A later queued waiting observation cannot revive an already answered request. No response
110
+ creates or acquires another output stream.
111
+
112
+ `resolveRequest` returns one of these delivery receipts:
113
+
114
+ - `{ status: "delivered" }`: the provider-owned handler accepted the exact canonical answer or step.
115
+ This includes a mapped form-intent step whose later field answer is still pending. It does not
116
+ establish a universal transport write, model consumption, effect completion, or turn success.
117
+ - `{ status: "rejected", requestState: "pending" | "unavailable", error }`: the provider definitively
118
+ refused this answer. Only `pending` preserves that exact callback's answerability; `unavailable`
119
+ retires it. Neither value terminalizes the original output owner.
120
+ - `{ status: "delivery_uncertain", error }`: native delivery started without definitive acceptance
121
+ or refusal. Further mutation and replay are forbidden; the original output/cleanup owner remains.
122
+
123
+ Local parsing, request correlation, expiry, and pre-abort failures reject with their precise original
124
+ errors before candidate entry. Validation atomically claims an answer before invoking the optional
125
+ synchronous `onProviderExecutionStarted` observer and then the candidate. The runtime strips this
126
+ observer from candidate input. A throwing observer prevents native entry and preserves the request
127
+ only while it remains answerable. An unexpected candidate response exception carries
128
+ `AgentProviderDelegatedOperationError` with `operation: "resolve_request"` and started-execution evidence;
129
+ it also forbids further mutation. Concurrent duplicate answers cannot enter the provider twice.
130
+
131
+ The turn input has the same synchronous start observer at its lazy candidate-entry boundary, after
132
+ prechecks pass. Abort or iterator return before the first pull releases the reservation without
133
+ poisoning the session. An aborted old handle rejects on a later pull. Abandoning an entered output
134
+ consumer stops admission and closes its native owner; an incomplete stream makes the session unusable.
135
+ Interruption remains a session control: dispatch acceptance leaves the original stream open to
136
+ observe actual native cancellation completion. Its `AgentProviderTurnInterruptionResult` carries only
137
+ status and optional error; interruption cannot return turn output. A reserved turn rejects interruption
138
+ with `active_turn_mismatch`, including after iterator acquisition; the first pull must enter the provider.
139
+ Abort or return cancels a reservation locally. Admitted interruption suspends exact request admission;
140
+ definitive failed interruptions restore only the unchanged live callback after every overlapping
141
+ interruption fails. A concurrent response refusal with `requestState: "pending"` retains that callback
142
+ through suspension; an accepted interruption withdraws it regardless of response completion order.
143
+
144
+ Close first stops admission, signals cancellation, and initiates native quiescence; it then joins
145
+ entered output/response work and drains host callbacks before releasing resources. Native close is
146
+ initiated before joining acknowledgments that depend on it. A failed close keeps the stopped owner
147
+ and host binding retained while close remains retryable. Successful close and disposal are idempotent.
148
+
149
+ Ordinary answers past a request's `expiresAt` fail locally. A canonical `canceled` resolution still
150
+ checks the live handler's availability; expiry alone cannot establish delivery. Terminal observation
151
+ fences new answers even while an entered response is settling, and waiting observations cannot
152
+ reopen an older request. A host must cancel human decisions when their execution ends and join
153
+ those tasks during cleanup. Keep the session or exact opening-cleanup receipt if cleanup fails;
154
+ disposing its registry or host resources before quiescence would lose the retained owner.
155
+
156
+ `runtime.retrying` reports a retry already owned by the provider on the active turn. It preserves
157
+ turn ownership, pending requests, and per-output backpressure; it neither starts another execution
158
+ nor completes the turn. It is rejected before `turn.started`, after `turn.completed`, after a
159
+ `final_diff` terminal materialization, and from session-operation observations. The event's neutral
160
+ failure category and recovery hint describe the observed condition. A recovery hint never authorizes
161
+ replaying work or changes an uncertain execution outcome. Contract failures, delegated-operation
162
+ started evidence, and retained cleanup responsibilities remain separate from those failure values.
100
163
 
101
164
  When context usage is advertised, the validated session enforces the declared measurement scopes
102
165
  and cumulative fields across turns. Identical consecutive samples and decreasing cumulative
@@ -104,13 +167,19 @@ counters are rejected. Occupancy may decrease only after a completed advertised
104
167
  the next accepted sample consumes that allowance. Context output remains subject to the same
105
168
  per-output backpressure and terminal ordering as every other provider event.
106
169
 
107
- When `capabilities.turns.steer` is true, the session exposes `steering.steerTurn`. Steering accepts
170
+ When `capabilities.turns.steer.kind` is `supported`, the session exposes `steering.steerTurn`. Steering accepts
108
171
  the existing turn ID plus the same canonical `parts` and optional `summary` used to start a turn.
109
- It does not create or own an output stream: model output continues on the original `runTurn`
110
- iterator. The receipt is exactly `delivered`, `rejected` with a bounded neutral error, or
172
+ It requires provider entry on the first output pull; a reserved or merely acquired execution rejects
173
+ steering with `active_turn_mismatch` without calling the provider.
174
+ It does not create or own an output stream: model output continues on the original execution's
175
+ `outputs` iterator. The receipt is exactly `delivered`, `rejected` with a bounded neutral error, or
111
176
  `delivery_uncertain` with a bounded neutral error. A provider must use uncertainty when delivery
112
177
  may have started but its authoritative acknowledgement was lost; callers cannot safely replay that
113
- result. The validated runtime preserves pre-delegation validation and abort errors unchanged, while
178
+ result. A returned `delivery_uncertain` makes the validated session unusable for further mutation.
179
+ Keep its original output reader owned while it drains toward terminality; a pending request does not
180
+ end that stream or restore mutation authority. Close the unusable session to quiesce work that cannot
181
+ finish without another response, then rematerialize before further work. The validated runtime preserves pre-delegation
182
+ validation and abort errors unchanged, while
114
183
  provider-delegated steering failures throw `AgentProviderDelegatedOperationError` with the original
115
184
  cause and explicit started-execution evidence so a host can retire the unusable session. Platform
116
185
  scheduling and provider-native queue modes are intentionally outside this SPI.
@@ -128,6 +197,167 @@ identity, declared bounds, forward-only lifecycle transitions, and per-output ba
128
197
  the operation result may settle. Collaboration and generated-resource observations retain the
129
198
  same correlation and lifecycle validation at their respective ports.
130
199
 
200
+ ## Session-lifetime interactions
201
+
202
+ An adapter can offer a decision outside any model turn through `sessionInteractions`.
203
+ Its support declaration is separate from V11 turn capabilities: absence means
204
+ `{ kind: 'unsupported' }`; supported adapters name exact `openingOperations`, declare
205
+ `requestKinds: ['decision']` and require `producerOwnership: 'exclusive'`. Supplying
206
+ `interactions` for an unsupported opening raises `session_interactions_unsupported` before
207
+ delegating that opening. An adapter's create support does not imply resume or branch support.
208
+
209
+ Install `interactions.onRequest` before opening. The callback receives a bound
210
+ `AgentSessionInteraction` containing the portable request, an eligibility signal, a
211
+ terminal promise and `respond({ choiceId, signal? })`. The handler can return immediately
212
+ after handing the capability to an owned UI, or return the promise for its work. Opening
213
+ may return while the decision remains pending; questions can also arrive after return.
214
+ Do not block session creation waiting for every human decision or route these decisions
215
+ through `startTurn`, `AgentEvent`, or an execution's `resolveRequest`.
216
+
217
+ For an already selected `adapter`, host-owned `openingInput` and UI-owned map, register early:
218
+
219
+ ```ts
220
+ import type { AgentProviderCreateSessionInput, AgentSessionInteraction } from '@agen-ai/agent-runtime';
221
+
222
+ const pending = new Map<string, AgentSessionInteraction>();
223
+ const input: AgentProviderCreateSessionInput = {
224
+ ...openingInput,
225
+ interactions: {
226
+ onRequest(interaction) {
227
+ pending.set(interaction.request.requestId, interaction);
228
+ },
229
+ },
230
+ };
231
+ const session = await adapter.createSession(input);
232
+ // Present the request target and every choice consequence before selecting a choice.
233
+ // Answer using that retained interaction's respond({ choiceId }) capability.
234
+ // The UI retires terminal entries and observes interaction.signal.
235
+ ```
236
+
237
+ The complete public [lifecycle example](../../examples/lifecycle-interactions.ts) uses a
238
+ consumer-owned adapter, opens with a pending decision, selects a synthetic decline and joins
239
+ cleanup without a model turn. It needs only the core protocol/runtime dependency closure.
240
+ For an ordinary noninteractive opening, omit `interactions` from the input. The runtime
241
+ does not install an automatic answer policy; a provider requiring a handler must reject that
242
+ opening. Keep authentication and interactive materialization in their existing owners.
243
+
244
+ `respond` validates the choice against this exact request and allows one active response:
245
+
246
+ | Receipt | Meaning |
247
+ | --- | --- |
248
+ | `delivered` | The provider-owned handler accepted the exact choice. The interaction becomes `answered`; this does not prove a wire write, native consumption, effect completion or persistent storage. |
249
+ | `rejected` with `requestState: 'pending'` | Definitive refusal preserves this request's eligibility. A second response while one is active also receives pending refusal; it cannot start overlapping native delivery. |
250
+ | `rejected` with `requestState: 'unavailable'` | The request has retired and the capability cannot answer it again. |
251
+ | `delivery_uncertain` | Entered delivery did not establish acceptance or refusal. The session is fenced against further mutation; close it without replaying the choice. |
252
+
253
+ Malformed choices and pre-aborted response inputs preserve their original errors before provider
254
+ entry. An entered response that throws or exceeds its response deadline returns uncertainty,
255
+ even if the provider later settles. Closing or aborting does not make an entered answer safe
256
+ to repeat. Successful cleanup never resolves that uncertainty or authorizes replay.
257
+
258
+ Terminal variants are `answered`, `rejected`, `delivery_uncertain`, `withdrawn`, `expired`,
259
+ `session_closed`, and `failed`. `interaction.signal` controls answer eligibility and UI
260
+ presentation; terminal settlement records the decision lifecycle. Neither means the native
261
+ producer, entered response or callback has stopped. Close first fences admission and starts
262
+ native shutdown, then joins the actual response, terminal and callback work. A callback that
263
+ ignores abort remains owned. Request expiry or handler failure fails the interaction owner;
264
+ cleanup and its original failure remain observable through the owning session.
265
+
266
+ The runtime validates integer overrides once on the opening context:
267
+
268
+ | Limit | Default | Allowed override |
269
+ | --- | --- | --- |
270
+ | `maxRetainedRequests` | 8 | 1 to 32 |
271
+ | `maxRetainedBytes` | 524,288 bytes | 65,536 to 2,097,152 bytes |
272
+ | `requestTimeoutMs` | 300,000 ms | 1,000 to 1,800,000 ms |
273
+ | `responseTimeoutMs` | 30,000 ms | 1,000 to 120,000 ms |
274
+ | `cleanupTimeoutMs` | 30,000 ms | 1,000 to 120,000 ms |
275
+
276
+ Request eligibility uses the earlier provider expiry or runtime request deadline. Retained
277
+ capacity includes terminal requests whose native terminal, response or callback has not drained.
278
+ Unknown fields, fractional values and values outside the bounds reject the opening context.
279
+ The opening signal applies until the session is adopted; later cancellation belongs to the
280
+ returned session or a specific response rather than the completed opening call.
281
+
282
+ If an opening fails with incomplete cleanup, use
283
+ `isAgentProviderSessionCleanupErrorFor(error, openingInput)` with the exact input object
284
+ passed to the adapter, such as `input` above.
285
+ Retain that `AgentProviderSessionCleanupError` and its bound `retryCleanup()`; keep the
286
+ registry, instance, host resources and installation references owned until it succeeds.
287
+ A returned session with failed close likewise retains cleanup through the session and any
288
+ returned cleanup error. An observation timeout does not detach the actual work. Retry joins
289
+ the same owner and never opens another session or resends a choice. Serialized errors and
290
+ request IDs cannot restore callable cleanup or response authority. Adapter authors use
291
+ `createAgentProviderSessionCleanupError({ openingInput, providerKey, errors, retryCleanup })`
292
+ to preserve a failed opening's exact cleanup owner.
293
+
294
+ ## Session-local host tools and instructions
295
+
296
+ A host can pass an optional `AgentSessionHostBinding` when creating, resuming or branching a
297
+ session. The binding contains tool definitions, an invocation callback, optional instructions and
298
+ an idempotent `release` callback. Its callbacks close over host authorization; model arguments do
299
+ not supply that authority. This is an additive runtime SPI. It does not enable managed delegation
300
+ or change native collaboration by itself.
301
+
302
+ The optional `@agen-ai/agent-orchestration` package sits above this SPI. It owns managed target policy,
303
+ scoped tools and generated delegation guidance; the runtime has no dependency on that package or
304
+ its explicit MCP transport. A parent's end-turn boundary leaves its session binding alive and does
305
+ not cancel independently owned children. AgenAI Workspaces preferences and Hostd production
306
+ integration remain separate product work.
307
+
308
+ An adapter declares `hostBinding` support, its `callback` or `mcp` transport, and the instruction
309
+ placements it can materialize. Missing support means unsupported. `system` and `developer`
310
+ placements require the corresponding trusted native channels; `tool_context` means tool/server
311
+ guidance. The runtime rejects unsupported requests before native session creation. Adapter authors
312
+ must reject collisions with their native tools and actually install the requested binding.
313
+
314
+ Tools use a bounded, closed JSON Schema 2020-12 subset: objects with declared properties and no
315
+ additional properties, bounded arrays and strings, finite numbers, safe integers, booleans and
316
+ null. Root schemas declare the dialect. References, remote loading, regular expressions, coercion
317
+ and executable validation are unsupported. A binding allows up to 32 tools, 64 KiB of definition
318
+ data, 32 KiB argument/result envelopes and 16 concurrent callbacks. Runtime validation precedes
319
+ callback entry and validates returned results; callback exceptions become sanitized tool errors.
320
+
321
+ Every opening needs a fresh binding object, including resume and branch. The validated opening
322
+ claims a minimally valid binding before other opening checks. After that claim, opening failures
323
+ own cleanup; malformed minimal bindings remain caller-owned and a duplicate claim cannot release
324
+ the original session's binding. `validateAgentSessionHostBinding` validates metadata without claiming it. Explicit transport
325
+ adapters can reuse `validateAgentHostToolInvocation({ binding, invocation })` against that validated
326
+ metadata and `validateAgentHostToolResult(value)` without duplicating the bounded schema interpreter.
327
+ These pure validators do not invoke callbacks, claim leases or provide lifecycle ownership.
328
+
329
+ If a provider opening fails before returning a session and native resources are still pending,
330
+ throw `createAgentProviderSessionCleanupError({ providerKey, openingInput, errors, retryCleanup })`.
331
+ `openingInput` must be the exact context object received by the create/resume/branch port. The
332
+ validated adapter adopts only that exact identity and provider key, stops new host callbacks, and
333
+ retains the original binding. Explicit cleanup retry first quiesces provider resources and then
334
+ releases the binding; propagation does not add another native cleanup attempt. Successful native
335
+ cleanup is retained when only host release needs retry. A plain or foreign cleanup error cannot
336
+ claim the current opening. Callers can use `isAgentProviderSessionCleanupErrorFor(error, input)`
337
+ against their original opening object to identify the retained responsibility.
338
+
339
+ Closing stops new invocations and aborts active callback signals, then joins provider cleanup and
340
+ callback settlement before releasing the host binding. Ending a turn does not release it. Providers
341
+ must quiesce their output/control producers before their close succeeds and clean up partial native
342
+ resources before throwing an opening error without a session. Preserve callback method receivers.
343
+ Hosts must close their sessions before disposing the instance or registry. Registry disposal retains
344
+ its existing instance ownership and does not inventory or close caller-owned session bindings.
345
+
346
+ Cleanup failure leaves authority closed and cleanup retryable. An opened session retries through
347
+ `session.close`. If opening fails and cleanup also fails, catch
348
+ `AgentProviderSessionCleanupError` and check
349
+ `isAgentProviderSessionCleanupErrorFor(error, originalOpeningInput)` before assigning its retained
350
+ handle to an opening. Use a distinct input object for each opening and preserve the exact object
351
+ passed to create, resume or branch; copied inputs
352
+ and constructed errors do not match the runtime's private ownership evidence. This also covers
353
+ invalid candidates without host tools. `AgentProviderHostBindingCleanupError` remains the compatible
354
+ subclass for failures involving a claimed host binding. A provider can propagate another opening's
355
+ error, so `instanceof` alone does not establish ownership. Call the matching error's single-flight
356
+ `retryCleanup()` to finish retained cleanup. It closes the exact rejected session before releasing
357
+ the binding; a completed close is not repeated when only host release failed. Keep this error and
358
+ its diagnostic causes on the trusted host boundary. Never serialize its handle or raw diagnostics
359
+ into a model tool result.
360
+
131
361
  ## Minimal driver
132
362
 
133
363
  ```ts
@@ -178,6 +408,19 @@ The runtime distinguishes programmer/contract failures from provider failures:
178
408
  Provider-native exceptions should be normalized or safely wrapped at the provider boundary. Do
179
409
  not attach credentials, raw prompts, product identities, or unbounded output to public errors.
180
410
 
411
+ Use `AgentError.category`, `code` and `recovery` to describe an expected operational condition.
412
+ They do not replace `AgentProviderContractError`, delegated-operation start evidence, or cleanup
413
+ exceptions. A `runtime.error` observation is not a terminal event; `runtime.retrying` keeps the same
414
+ turn active. Render a definitive failed turn from its `turn.completed` result instead of counting
415
+ each error observation as another failure. A transient classification or a quota reset never proves
416
+ that prior tool effects can be repeated.
417
+
418
+ Cancellation must retain the current stream and resource owners until native settlement and callback
419
+ quiescence are established. An accepted interruption acknowledges dispatch; it does not establish
420
+ cancellation completion. If the outcome remains unknown, preserve that uncertainty, close the unusable
421
+ session and retain any failed cleanup handle for explicit retry. Successful cleanup does not settle
422
+ the uncertain operation or authorize resending it.
423
+
181
424
  ## Scoped environment observation
182
425
 
183
426
  `MaterializedAgentProviderInstance.environment` discovers a caller-selected workspace and
@@ -207,11 +450,13 @@ turn/request ordering, request resolution, steering, interruption, configuration
207
450
  close, and idempotent disposal. Unsupported operations must remain explicit discriminants and
208
451
  must not expose handlers.
209
452
 
210
- The coordinated SDK version for this source is `0.3.1`, and the source implements Agent Protocol
211
- V9. The earlier public `0.3.0` release implemented the same protocol and remains historical.
212
- Upgrade all three SDK packages together. Every materialized instance requires `environment` and
453
+ The coordinated source SDK version is `0.4.1`, remains unpublished and implements Agent Protocol V11.
454
+ The published coordinated release remains `0.4.0` with V10.
455
+ The earlier public `0.3.0` and `0.3.1` releases implemented V9 and remain historical.
456
+ Keep installed packages in the seven-package SDK release family on the coordinated version; the
457
+ orchestration and ACP packages remain optional. Every materialized instance requires `environment` and
213
458
  `accountQuota`; every session requires `environment`. The former standalone `integrations`
214
- observation port is removed. The public runtime implements Agent Protocol V9 with one current
459
+ observation port is removed. The public runtime implements Agent Protocol V11 with one current
215
460
  adapter/session surface. Package versions remain independent of private transport and product
216
461
  persistence versions.
217
462
 
@@ -222,3 +467,17 @@ From the public repository root, run `pnpm check`.
222
467
  It installs tarballs into a temporary project outside the workspace, typechecks every documented
223
468
  entrypoint, runs the fake provider and parser flow, and removes the temporary directory. It never
224
469
  publishes or accesses release credentials.
470
+
471
+ The public repository also contains `examples/delegation`: a shared host composition with direct
472
+ and credentialless ACP workflows plus a separately qualified SQLite/inbox CLI. From that root,
473
+ `pnpm examples:delegation` exercises real steering, queued resume, cancellation and live approval;
474
+ `pnpm examples:delegation:acp` invokes scoped MCP tools and demonstrates a child surviving its
475
+ parent's end-turn boundary. The installed-tarball consumer runs the same source. Synthetic evidence
476
+ does not certify native agents or authorize replay of an uncertain turn.
477
+
478
+ For the smallest runnable lifecycle example, use
479
+ [`examples/live-request-output.ts`](../../examples/live-request-output.ts) in the public repository
480
+ with `pnpm examples:live-request-output`. It observes unrelated output before answering an exact
481
+ request, with one reader and joined cleanup. The public
482
+ [migration guide](../../MIGRATING-TO-0.4.md#continuous-turn-output-and-independent-answers) shows the
483
+ published-`0.3.1` before-example and an independent human-handler pattern for `0.4.0`.
@@ -1,4 +1,4 @@
1
1
  import { type AgentCapabilities } from "@agen-ai/agent-protocol";
2
2
  import type { AgentProviderAdapter } from "./sessions.js";
3
- export declare function validateAgentProviderAdapter(capabilityInput: AgentCapabilities, adapter: AgentProviderAdapter): AgentProviderAdapter;
3
+ export declare function validateAgentProviderAdapter(capabilityInput: AgentCapabilities, adapterInput: AgentProviderAdapter): AgentProviderAdapter;
4
4
  //# sourceMappingURL=adapterValidation.d.ts.map