Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
138 commits
Select commit Hold shift + click to select a range
30035ea
[agentserver] responses: restore full spec 015/016 work on top of cor…
RaviPidaparthi Jun 2, 2026
cc80e7f
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 2, 2026
3fdbeff
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 2, 2026
5051faf
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 2, 2026
1d22833
[agentserver] spec 017 Phase 1: delete legacy stream surface, migrate…
RaviPidaparthi Jun 4, 2026
45ea7e0
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 4, 2026
e630d95
[agentserver] responses: migrate to core streams registry; delete leg…
RaviPidaparthi Jun 4, 2026
086eaa6
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 4, 2026
7177de3
[agentserver] responses: fix CrashHarness subprocess pipe-buffer dead…
RaviPidaparthi Jun 4, 2026
65a8047
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 4, 2026
f9b8cd6
[agentserver] responses: spec-compliant cancellation/failure handling…
RaviPidaparthi Jun 4, 2026
1ef1a25
[agentserver] responses: shutdown-event race + post-crash SSE stream …
RaviPidaparthi Jun 4, 2026
58d043f
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 4, 2026
cbcebc8
[agentserver] responses: complete spec-compliant cancellation/failure…
RaviPidaparthi Jun 4, 2026
6c758fe
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 4, 2026
09a496b
[agentserver] core: bound steering drain retries + drop etag fallback…
RaviPidaparthi Jun 4, 2026
337a7fc
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 4, 2026
dc2d88d
[agentserver] core: workaround hosted-store etag-comparison bug (alwa…
RaviPidaparthi Jun 4, 2026
9a3597a
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 5, 2026
3edb0a0
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 5, 2026
d26acf2
core: skip no-op activation PATCH on the recovery path
RaviPidaparthi Jun 5, 2026
20a18a1
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 5, 2026
1ee55b2
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 5, 2026
0b1dfe2
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 6, 2026
95d98c6
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 6, 2026
e355417
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 6, 2026
d4fe73b
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 8, 2026
060ea48
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 8, 2026
c44f5c7
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 9, 2026
1136a5c
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 9, 2026
d906727
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 9, 2026
648969f
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 11, 2026
01cebdd
[agentserver] responses: migrate for spec 019 (EventStreamGoneError →…
RaviPidaparthi Jun 11, 2026
eb75e31
[agentserver] responses: add authoritative durability SOT spec
Jun 14, 2026
99a06a3
[agentserver] responses: tidy developer guides to be standalone + dri…
Jun 14, 2026
a2648d9
[agentserver] responses: SOT spec — document the two valid handler ex…
Jun 14, 2026
e37a1c5
[agentserver] responses: merge feature/agentserver-durable-tasks (spe…
Jun 14, 2026
83deeb7
[agentserver] responses: add RED conformance tests for spec 023 migra…
Jun 14, 2026
8d6512f
[agentserver] responses: per-request primitive dispatch (spec 023 Pha…
Jun 14, 2026
242e86d
[agentserver] responses: tidy unit tests for spec 023 migration
Jun 14, 2026
aa0dbda
[agentserver] responses: sync SOT spec + dev guides + CHANGELOG for s…
Jun 14, 2026
e63ec19
[agentserver] responses: black formatting + spec 023 checkbox sync
Jun 14, 2026
d55a230
[agentserver] responses: add Row 5 e2e depth-coverage tests (audit ga…
Jun 14, 2026
0334b98
[agentserver] responses: RED conformance tests for spec 024 bookkeepi…
Jun 15, 2026
63e7a4a
[agentserver] responses: bookkeeping unification (spec 024 Phase 2)
Jun 15, 2026
f54fb98
[agentserver] RED tests for spec 024 Phase 3a (storage-root rename)
Jun 15, 2026
ff592d9
spec 024 Phase 3: storage-root rename + file-backed response store as…
Jun 15, 2026
97bf94f
spec 024 Phase 4: durable_background default False + composition-guar…
Jun 15, 2026
8c230e6
[agentserver] responses: public API simplification per spec 024 §A (s…
RaviPidaparthi Jun 15, 2026
d2a3cb7
[agentserver] responses: SOT spec architectural rewrite post-unificat…
RaviPidaparthi Jun 15, 2026
c64729f
[agentserver] responses: conformance test gap closure (spec 024 Phase 7)
RaviPidaparthi Jun 15, 2026
8c11d2b
[agentserver] responses: black formatter sweep (spec 024 Phase 8)
RaviPidaparthi Jun 15, 2026
b69096f
[agentserver] responses: spec 024 self-audit gate remediations (spec …
RaviPidaparthi Jun 15, 2026
7173cc5
[agentserver] responses: CHANGELOG entry for spec 024 (spec 024 Phase…
RaviPidaparthi Jun 15, 2026
7b93b7a
[agentserver] responses: spec 024 final quality-gate sweep (spec 024 …
RaviPidaparthi Jun 15, 2026
55c27c8
[agentserver] responses: final-audit closure (spec 024 Phase 10)
RaviPidaparthi Jun 15, 2026
76c5614
[agentserver] responses: docs audit pass — strip internal-spec refs, …
RaviPidaparthi Jun 15, 2026
ca37c24
[agentserver] responses: restore shipped 3-arg handler signature + de…
RaviPidaparthi Jun 15, 2026
f7b4f12
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 15, 2026
077293f
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 15, 2026
49ed697
[agentserver] responses: remove Claude sample + simplify steering che…
RaviPidaparthi Jun 15, 2026
937eb3d
[agentserver] responses: fix 4 pre-existing baseline failures (persis…
RaviPidaparthi Jun 15, 2026
38ba06d
[agentserver] core CHANGELOG: add storage_paths + AGENTSERVER_TASKS_B…
RaviPidaparthi Jun 15, 2026
5a26ad0
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 15, 2026
fcb2b64
[agentserver] responses: tighten Phase-1 persistence-failure stamp or…
RaviPidaparthi Jun 15, 2026
f1f808a
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 15, 2026
72fd18f
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 15, 2026
6f4a0a2
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 15, 2026
f63d6f4
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 15, 2026
460bd6b
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 15, 2026
3836cc8
[agentserver] responses spec-025 Phase 1: internal_metadata bags + re…
RaviPidaparthi Jun 16, 2026
32fe307
[agentserver] responses spec-025 Phase 2: strip internal_metadata on …
RaviPidaparthi Jun 16, 2026
6c886f5
[agentserver] responses spec-025 Phase 3: developer checkpoint primitive
RaviPidaparthi Jun 16, 2026
ea6f5be
feat(responses): unified exit_for_recovery() raise-internally recover…
RaviPidaparthi Jun 16, 2026
7481493
docs(responses): adopt unified exit_for_recovery() idiom in samples +…
RaviPidaparthi Jun 16, 2026
2531c1e
test(responses): map test_explicit_exit_for_recovery in CONTRACT_COVE…
RaviPidaparthi Jun 16, 2026
30e1a98
feat(responses): durability-contract Row 11 — developer checkpoint wr…
RaviPidaparthi Jun 16, 2026
d665637
fix(responses): make recovery output-seeding work per spec §6 (not re…
RaviPidaparthi Jun 16, 2026
b2024ad
docs(responses): checkpoint-driven recovery + metadata-facility guide…
RaviPidaparthi Jun 16, 2026
c3ef8d9
docs(responses): clean-room CHANGELOG for the unreleased durability p…
RaviPidaparthi Jun 16, 2026
5275cfa
docs(responses): current-state framing for the _responses.background …
RaviPidaparthi Jun 16, 2026
99dc5c9
style(responses): black-format spec-025 egress strip sites in _endpoi…
RaviPidaparthi Jun 16, 2026
6004f34
docs(responses): complete durable_metadata->conversation_chain_metada…
RaviPidaparthi Jun 16, 2026
2155081
fix(core/durable): track post-reclaim etag on cold-start recovery
RaviPidaparthi Jun 16, 2026
5988bae
Remove orphan bundled wheels from responses-spec016
RaviPidaparthi Jun 16, 2026
79976b8
fix(responses/durable): no duplicate response.created on recovery + g…
RaviPidaparthi Jun 16, 2026
fc9a757
docs+test(spec 026): contract clauses + guides + conformance assertion
RaviPidaparthi Jun 16, 2026
f01b5f9
docs(SOT): spec 026 recovery clauses in responses-durability-spec + c…
RaviPidaparthi Jun 17, 2026
f2e2278
docs(SOT): establish single normative ownership between the two durab…
RaviPidaparthi Jun 17, 2026
4e5fa78
Spec 026: add drop + created-gate conformance tests
RaviPidaparthi Jun 17, 2026
40b3e95
Spec 027: stream cursor is the seq-number SOT; retire dead last_seque…
RaviPidaparthi Jun 17, 2026
de2d90c
Spec 028: normalize FileResponseStore — one item copy under items/, p…
RaviPidaparthi Jun 17, 2026
0a15ce4
Spec 028 (FR-028-8): drop redundant per-response history.json
RaviPidaparthi Jun 17, 2026
ddb824c
Spec 028 SOT: document FileResponseStore normalized layout (§16.2.1) …
RaviPidaparthi Jun 17, 2026
d6e663a
Type the steering acceptance hook to return ResponseObject (not a loo…
RaviPidaparthi Jun 17, 2026
9ee3d76
Spec 029: restructure durability guides — fix drift, loosen over-mand…
RaviPidaparthi Jun 17, 2026
ab4d493
docs(handler-guide): fix yield-from for convenience generators to mat…
RaviPidaparthi Jun 17, 2026
4856d69
test(durability): Row 1 conformance under SSE keep-alive (RED)
RaviPidaparthi Jun 18, 2026
6743f4d
fix(durability): create durable task for stored streams under SSE kee…
RaviPidaparthi Jun 18, 2026
8801899
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 18, 2026
f3a36c5
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 18, 2026
378153a
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 18, 2026
5679367
test(responses-durability): spec 032 P1 — hard depth gate + recovery-…
RaviPidaparthi Jun 18, 2026
1fcfa5b
test(durability): close B3 client-cancel-during-recovery + reconcile …
RaviPidaparthi Jun 18, 2026
06b6aa0
fix(responses-durable): normalize agent_reference before persisting d…
RaviPidaparthi Jun 18, 2026
a8a1813
test(responses-durable): close conformance gap — recovery with reques…
RaviPidaparthi Jun 18, 2026
4bc53a4
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 19, 2026
6e2ddf0
fix(responses-durable): _persist_crash_failed terminal lands in clien…
RaviPidaparthi Jun 19, 2026
fc274be
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 19, 2026
74b0ec6
Spec 033 Phase 0: typed durable-recovery boundary (DurableResponseInput)
RaviPidaparthi Jun 24, 2026
fb36cd4
Spec 033 Phase 1: centralize durable dispatch (decide_disposition)
RaviPidaparthi Jun 24, 2026
e3cf818
Spec 033 Phase 2: decompose orchestrator god-methods (FR-005)
RaviPidaparthi Jun 24, 2026
9909fa1
fix(durability): preserve provider_created across cancel at created-t…
RaviPidaparthi Jun 24, 2026
f981511
test(durability): Spec 033 Phase 3 — pin streaming-wire seq single-au…
RaviPidaparthi Jun 24, 2026
8904ce6
style: black-format cancel-race regression test
RaviPidaparthi Jun 24, 2026
79e5372
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 24, 2026
9308462
refactor(responses): consume public core platform-contract surface (F…
RaviPidaparthi Jun 24, 2026
0d1e184
refactor(responses): drop vestigial ctx_params dict in primitive sele…
RaviPidaparthi Jun 24, 2026
934db85
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 25, 2026
fd02683
refactor(responses): reframe durable->resilient terminology (Spec 034…
RaviPidaparthi Jun 25, 2026
7f6b1b0
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 25, 2026
f441cd2
refactor(responses): storage-prose accuracy in reframe (Spec 034 §2.9a)
RaviPidaparthi Jun 25, 2026
a53ff27
refactor(responses): storage-prose in CHANGELOG (Spec 034 §2.9a)
RaviPidaparthi Jun 25, 2026
275619c
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 25, 2026
f3b23f9
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 25, 2026
34e5ad5
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 25, 2026
be5fdc1
fix(responses): correct module-path mis-swap in import-lint docstring…
RaviPidaparthi Jun 25, 2026
a38cb73
fix(samples): install local preview agentserver packages for response…
RaviPidaparthi Jun 25, 2026
a22e7b0
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 25, 2026
9e28ff0
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 25, 2026
a8f70e1
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 25, 2026
2cdc5de
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 25, 2026
859505d
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 25, 2026
078d2a4
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 25, 2026
7bd2f49
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 25, 2026
60be586
docs(samples): use raw docstrings so responses usage curls copy-paste…
RaviPidaparthi Jun 25, 2026
547c4b9
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 26, 2026
e8967c7
Merge branch 'feature/agentserver-durable-tasks' into feature/agentse…
RaviPidaparthi Jun 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 82 additions & 21 deletions sdk/agentserver/azure-ai-agentserver-responses/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,92 @@
# Release History

## 1.0.0b7 (2026-05-25)
## 1.0.0b8 (Unreleased)

### Features Added

- Added MCP output item builder enhancements for hosted MCP relay scenarios: `ResponseEventStream.add_output_item_mcp_call()` now supports caller-supplied item IDs, and MCP call `emit_done()` supports optional `output` and `error` payloads for canonical `mcp_call` persistence and replay.

## 1.0.0b6 (2026-05-21)

### Features Added

- Error source classification headers: All HTTP error responses now include `x-platform-error-source` with a value of `user`, `platform`, or `upstream` to indicate which component caused the error. Client validation errors (400/404) are classified as `user`, Foundry storage infrastructure errors (transport failures, 5xx) as `platform`, and developer handler exceptions as `upstream`. Platform errors additionally include `x-platform-error-detail` with truncated exception details (max 2048 characters) for diagnostics. Matches the container image specification §8 error source classification.

### Breaking Changes

- Removed the automatic `invoke_agent` server span that was created on each response creation request. Trace context propagation is now handled by the core `TraceContextMiddleware`, and user-created spans inside handlers are correctly parented without framework-generated spans.
- Removed `_safe_set_attrs`, `_wrap_streaming_response`, and `_classify_error_code` internal helpers (no longer needed without framework-level span management).
- Removed OTel error tagging attributes (`azure.ai.agentserver.responses.error.code`, `azure.ai.agentserver.responses.error.message`) that were set on the framework span.
- **Resilient background responses.** `ResponsesServerOptions(resilient_background=True)`
makes `store=true`, `background=true` responses survive process crashes:
the framework persists handler progress and re-invokes the registered
handler on the next process start when a prior attempt did not reach a
terminal event. Defaults to `False`.

- **Steerable conversations.** `ResponsesServerOptions(steerable_conversations=True)`
lets clients post a new turn on an in-flight conversation; the running
handler is woken (via the cancellation signal, distinguished by
`context.pending_input_count > 0`), drains the queued input on a fresh
invocation, and the turns are linked in a stable conversation chain.
Defaults to `False`.

- **`ResponseContext` resilience + steering surface.** Flat fields stamped on
each invocation: `context.is_recovery`, `context.is_steered_turn`,
`context.pending_input_count`, and `context.conversation_chain_id` (a stable
identifier shared by every turn of a conversation chain, usable as a key into
application-side session state).

- **Developer checkpoints.** `yield stream.checkpoint()` persists the
current response snapshot at a developer-chosen boundary (gated to resilient
background responses; a no-op otherwise; backpressured and idempotent). On a
recovered entry, `context.persisted_response` exposes the last persisted
snapshot so the handler can seed its stream and resume — the basis of the
one-`OutputItem`-per-phase recovery pattern.

- **`internal_metadata`.** A single-turn, platform-internal `MutableMapping[str, Any]`
on output items (`item.internal_metadata`) and on the response
(`stream.internal_metadata`). It is persisted with the response (so it is
available on recovery) and is always stripped before any client-facing
HTTP/SSE payload, and on ingress. Distinct from the public
`ResponseObject.metadata`.

- **`context.conversation_chain_metadata`.** Cross-turn, named-scope,
explicit-`flush()` resilient metadata over a conversation chain, typed by the
public `ConversationChainMetadataNamespace` Protocol.

- **`await context.exit_for_recovery()`.** A single uniform graceful-shutdown
recovery primitive that works in every handler shape (coroutine, async
generator, sync) — it raises `ResponseExitForRecovery` internally to leave
the response `in_progress` for next-lifetime recovery.

- **Stream recovery.** SSE events are persisted incrementally; clients reconnect
with `GET /responses/{id}?stream=true&starting_after=<event_id>` and resume
from their last received event.

- **Response acceptor hook.** Register `@app.response_acceptor` to customize the
response shape returned when a turn is queued behind an active steerable
conversation.

- **Storage.** `FileResponseStore` is exported from
`azure.ai.agentserver.responses` and is the default local-development store
(under `${AGENTSERVER_STATE_ROOT:-~/.agentserver}/responses/`) when no `store=`
is supplied in a non-hosted environment; pass
`store=InMemoryResponseProvider()` to opt out. The `AGENTSERVER_STATE_ROOT`
environment variable sets the local state storage root. A typed
`ResponseAlreadyExistsError` is raised by the response-store providers on a
duplicate `create_response` (the idempotent-create signal on recovery).

- **Error source classification headers.** HTTP error responses carry
`x-platform-error-source` (`user` / `platform` / `upstream`); platform errors
also include `x-platform-error-detail` with truncated diagnostics.

- **Handlers are `async def`.** `@app.response_handler` requires an async
handler with the `(request, context, cancellation_signal)` signature so it can
observe the `asyncio.Event` cancellation signal.

- Added resilient samples demonstrating real SDK integrations (Claude Agent SDK,
Copilot SDK, LangGraph) and resilient streaming / steering / multi-turn
patterns.

### Bugs Fixed

- Removed `ContentDecodePolicy` from the `FoundryStorageProvider` HTTP pipeline. The policy eagerly decoded every response body as JSON and crashed with `UnicodeDecodeError` when the storage backend (or an intermediary gateway/load-balancer) returned a non-UTF-8 body — for example a gzip-compressed payload, an HTML error page, or a transport-corrupted response. The crash propagated up before our error-classification code could see the response, masking the underlying status with a generic decode error. Our serializers and error-extraction helpers already call `http_resp.text()` lazily with defensive error handling, so the eager decode policy was never needed.

### Other Changes

- Platform header name constants (e.g. `x-platform-error-source`, `x-platform-error-detail`) are now imported from `azure-ai-agentserver-core` (`_platform_headers` module). Error source classification helpers remain internal to this package.
- Simplified request handling: baggage entries (`response_id`, `conversation_id`, `streaming`, `x-request-id`) are still set on each request, but span creation and lifecycle management are left to downstream frameworks.
- **Resilient background streaming responses now engage resilience even when SSE
keep-alive is enabled.** Previously the resilient task was created only on the
no-keep-alive streaming path, so when SSE keep-alive was enabled (e.g. the
hosted platform sets `SSE_KEEPALIVE_INTERVAL`), a `store=true`,
`background=true`, `stream=true` response ran the handler inline on the
request connection and never created a resilient task. Such responses could
hang `in_progress` on a client/proxy disconnect and were not recoverable.
Stored responses now always run via the resilient task; keep-alive comments are
interleaved into the wire stream while the resilient body runs independently of
the client connection.

## 1.0.0b5 (2026-04-22)

Expand All @@ -49,7 +110,7 @@

### Bugs Fixed

- `DELETE /responses/{id}` no longer returns intermittent 404 when the background task's eager eviction races with the delete handler. Previously, `try_evict` could remove the record from in-memory state between the handler's `get()` and `delete()` calls, causing `delete()` to return `False` and producing a spurious 404. The handler now falls through to the durable provider when the in-memory delete fails due to a concurrent eviction.
- `DELETE /responses/{id}` no longer returns intermittent 404 when the background task's eager eviction races with the delete handler. Previously, `try_evict` could remove the record from in-memory state between the handler's `get()` and `delete()` calls, causing `delete()` to return `False` and producing a spurious 404. The handler now falls through to the resilient provider when the in-memory delete fails due to a concurrent eviction.
- `POST /responses` with `background=true, stream=false` now correctly returns `status: "in_progress"` instead of `"completed"`. Handlers that yield events synchronously (no `await` between yields — the normal pattern with `ResponseEventStream`) would cause the background task to run to completion before `run_background` captured the initial snapshot. A cooperative yield after `response_created_signal.set()` now ensures the POST handler resumes promptly.
- Conversation history IDs (`previous_response_id`, `conversation_id`) are now validated eagerly before the handler is invoked. A nonexistent reference now returns a 404 error to the client immediately, instead of being silently ignored or surfacing as an opaque error deep inside the handler. The prefetched IDs are reused by `ResponseContext.get_history()`, eliminating a redundant provider call.

Expand Down
43 changes: 36 additions & 7 deletions sdk/agentserver/azure-ai-agentserver-responses/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,20 @@ This automatically installs `azure-ai-agentserver-core` as a dependency.

```python
@app.response_handler
def my_handler(
request: CreateResponse, context: ResponseContext, cancellation_signal: asyncio.Event
):
async def my_handler(request: CreateResponse, context: ResponseContext, cancellation_signal: asyncio.Event):
...
```

Handlers MUST be `async def` and take exactly three positional parameters
(`request`, `context`, `cancellation_signal`). Sync handlers and the 2-arg
signature `(request, context)` are hard-rejected at decoration time.
Cancellation is observed via the `cancellation_signal` event (set on
client cancel, `/cancel` API, or steering pressure). Server shutdown is
a **distinct** signal observed via `context.shutdown` — shutdown does
NOT fire the cancellation signal; handlers that care about both must
inspect each independently. See the handler implementation guide for
the full surface.

### Protocol endpoints

| Method | Route | Description |
Expand Down Expand Up @@ -90,14 +98,28 @@ The `ResponseContext` provides request-scoped state:
| Property / Method | Description |
|---|---|
| `response_id` | Unique ID for this response |
| `is_shutdown_requested` | Whether the server is draining |
| `conversation_id` / `conversation_chain_id` | Conversation identifiers; `conversation_chain_id` is the framework-computed stable id shared by every turn in a chain |
| `isolation` | `IsolationContext` with `user_key` and `chat_key` for multi-tenant state partitioning |
| `client_headers` | Dictionary of `x-client-*` headers forwarded from the platform (keys normalized to lowercase) |
| `query_parameters` | Dictionary of query string parameters |
| `shutdown` | `asyncio.Event` set on graceful server shutdown — distinct from the per-request cancellation signal |
| `client_cancelled` | `bool` set when the cancel cause is `/cancel` endpoint or non-bg POST disconnect |
| `is_recovery` | `bool` set on a crash-recovered re-entry |
| `is_steered_turn` | `bool` set on the drain re-entry that follows a steering input |
| `pending_input_count` | `int` count of queued steering inputs |
| `conversation_chain_metadata` | `ConversationChainMetadataNamespace` for handler-managed checkpoint state |
| `exit_for_recovery()` | `await` to opt into the graceful-shutdown recovery path |
| `get_input_items()` | Load resolved input items as `Item` subtypes |
| `get_input_text()` | Extract all text content from input items as a single string |
| `get_history()` | Load conversation history items |

The per-request cancellation signal is delivered as the **3rd
positional handler argument** (`cancellation_signal: asyncio.Event`),
not via a `ResponseContext` attribute. It fires on client cancel
(`/cancel` API or non-bg POST disconnect) or steering pressure; it
does NOT fire on server shutdown — `context.shutdown` is the
independent surface for that case.

### Streaming and background modes

The SDK automatically handles all combinations of `stream` and `background` flags:
Expand All @@ -113,13 +135,15 @@ The library orchestrates the complete response lifecycle: `created` → `in_prog

For detailed handler implementation guidance, see [docs/handler-implementation-guide.md](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/agentserver/azure-ai-agentserver-responses/docs/handler-implementation-guide.md).

### Resilience

Crash recovery is **opt-in** via `ResponsesServerOptions(resilient_background=True)`. When opted in, background responses with `store=True` are crash-recoverable: the handler is re-invoked on restart and the recovered context exposes `context.is_recovery == True`. Stream events are persisted incrementally so clients can reconnect and resume from where they left off. Without the opt-in (the default), a crash mid-handler marks the response `failed` instead of re-invoking the handler. For advanced scenarios (metadata checkpointing, multi-turn steering), see the [Resilient Responses Developer Guide](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/agentserver/azure-ai-agentserver-responses/docs/resilient-responses-developer-guide.md).

## Examples

### Echo handler

```python
import asyncio

from azure.ai.agentserver.responses import (
CreateResponse,
ResponseContext,
Expand Down Expand Up @@ -188,7 +212,7 @@ app = ResponsesAgentServerHost(options=options)
### Common errors

- **400 Bad Request**: The request body failed validation. Check that optional fields such as `model` (when provided) are valid and that `input` items are well-formed.
- **404 Not Found**: The response ID does not exist or has expired past the configured TTL.
- **404 Not Found**: The response ID does not exist. In hosted deployments persisted responses live in the Foundry hosted responses store; in local development they live under `${AGENTSERVER_STATE_ROOT:-~/.agentserver}/responses/` by default. A missing record may indicate the response was never persisted or was deleted via `DELETE /responses/{id}`.
- **400 Bad Request** (cancel): The response was not created with `background=true`, or it has already reached a terminal state.

### Reporting issues
Expand All @@ -214,6 +238,11 @@ Visit the [Samples](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/
| [File Inputs](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/agentserver/azure-ai-agentserver-responses/samples/sample_14_file_inputs.py) | Receive files via base64 data URL, URL, or file ID |
| [Annotations](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/agentserver/azure-ai-agentserver-responses/samples/sample_15_annotations.py) | Attach file_path, file_citation, and url_citation annotations |
| [Structured Outputs](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/agentserver/azure-ai-agentserver-responses/samples/sample_16_structured_outputs.py) | Return structured JSON as a `structured_outputs` item |
| [Resilient Copilot](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/agentserver/azure-ai-agentserver-responses/samples/sample_18_resilient_copilot.py) | GitHub Copilot SDK with `resilient_background=True, steerable_conversations=True` |
| [Resilient Streaming](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/agentserver/azure-ai-agentserver-responses/samples/sample_19_resilient_streaming.py) | Three-phase streaming handler with `resilient_background=True` and `context.conversation_chain_metadata` watermarks |
| [Resilient Steering](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/agentserver/azure-ai-agentserver-responses/samples/sample_20_resilient_steering.py) | `context.is_steered_turn` on the drain re-entry with `resilient_background=True, steerable_conversations=True` |
| [Resilient LangGraph](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/agentserver/azure-ai-agentserver-responses/samples/sample_21_resilient_langgraph.py) | LangGraph integration with `resilient_background=True, steerable_conversations=True` |
| [Resilient Multi-turn](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/agentserver/azure-ai-agentserver-responses/samples/sample_22_resilient_multiturn.py) | Multi-turn conversation with `resilient_background=True, steerable_conversations=False` |

- [Handler implementation guide](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/agentserver/azure-ai-agentserver-responses/docs/handler-implementation-guide.md) — Detailed reference for building handlers

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,22 @@

from . import _data_url as data_url
from ._options import ResponsesServerOptions
from ._response_context import IsolationContext, ResponseContext
from ._response_context import (
ConversationChainMetadataNamespace,
ExitForRecoverySignal,
IsolationContext,
ResponseContext,
ResponseExitForRecovery,
)
from .hosting._routing import ResponsesAgentServerHost
from .models import CreateResponse, ResponseObject
from .models._helpers import (
get_conversation_id,
get_input_expanded,
to_output_item,
)
from .store._base import ResponseProviderProtocol, ResponseStreamProviderProtocol
from .store._base import ResponseProviderProtocol
from .store._file import FileResponseStore
from .store._foundry_errors import (
FoundryApiError,
FoundryBadRequestError,
Expand All @@ -32,13 +39,16 @@
__all__ = [
"__version__",
"data_url", # pylint: disable=naming-mismatch
"ConversationChainMetadataNamespace",
"ExitForRecoverySignal",
"ResponseExitForRecovery",
"ResponsesAgentServerHost",
"ResponseContext",
"IsolationContext",
"ResponsesServerOptions",
"ResponseProviderProtocol",
"ResponseStreamProviderProtocol",
"InMemoryResponseProvider",
"FileResponseStore",
"FoundryStorageProvider",
"FoundryStorageSettings",
"FoundryStorageError",
Expand Down
Loading