azure-ai-agentserver-responses_2.0.0b0
Pre-release2.0.0b0 (2026-07-29)
Features Added
-
Added the
azure.ai.agentserver.responses.aionamespace with asyncResponseEventStreamconvenience generators that use the same method names as the sync stream, such asoutput_item_message()andoutput_item_compaction(). -
Added local
TypedDictmodel contract generation for the Responses protocol, including generated type aliases, union aliases, andpy.typedpackaging support. -
Added dict-native wire payload helpers and request validators for validating protocol payloads without depending on generated model internals.
-
ResponseContext.conversation_chain_id(and the resilient task id it backs) now follows the native id convention:cchain_<partition><scope>for conversation-scoped chains,rchain_<partition><scope>for steerable response-linkage chains, or theresponse_idverbatim for a non-steerable one-shot. The id embeds the chain's partition key for co-location and carries a deterministic(agent, session)scope;task_id == conversation_chain_idexactly. Replaces the previous opaqueresilient-resp-<32-hex>form. -
Resilient background responses.
ResponsesServerOptions(resilient_background=True)
makesstore=true,background=trueresponses 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 toFalse. -
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 toFalse. -
ResponseContextresilience + steering surface. Flat fields stamped on
each invocation:context.is_recovery,context.is_steered_turn,
context.pending_input_count, andcontext.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_responseexposes 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-internalMutableMapping[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
publicConversationChainMetadataNamespaceProtocol. -
await context.exit_for_recovery(). A single uniform graceful-shutdown
recovery primitive that works in every handler shape (coroutine, async
generator, sync) — it raisesResponseExitForRecoveryinternally to leave
the responsein_progressfor next-lifetime recovery. -
Stream recovery. SSE events are persisted incrementally; clients reconnect
withGET /responses/{id}?stream=true&starting_after=<event_id>and resume
from their last received event. -
Response acceptor hook. Register
@app.response_acceptorto customize the
response shape returned when a turn is queued behind an active steerable
conversation. -
Storage.
FileResponseStoreis exported from
azure.ai.agentserver.responsesand is the default local-development store
(under${AGENTSERVER_STATE_ROOT:-~/.agentserver}/responses/) when nostore=
is supplied in a non-hosted environment; pass
store=InMemoryResponseProvider()to opt out. TheAGENTSERVER_STATE_ROOT
environment variable sets the local state storage root. A typed
ResponseAlreadyExistsErroris raised by the response-store providers on a
duplicatecreate_response(the idempotent-create signal on recovery). -
Handlers are
async def.@app.response_handlerrequires an async
handler with the(request, context, cancellation_signal)signature so it can
observe theasyncio.Eventcancellation signal.
Breaking Changes
-
Removed a-prefixed async convenience generator methods from the sync
ResponseEventStreamand sync builder classes. Useazure.ai.agentserver.responses.aio.ResponseEventStreamfor async streaming convenience methods. -
Replaced generated model classes in
azure.ai.agentserver.responses.modelswith dict-nativeTypedDictcontracts. Model constructors such asItemMessage(...)andCreateResponse(...)now produce plain dictionaries instead of generated model instances. -
Removed runtime model-class behavior from response protocol models. Code should no longer rely on attribute access,
isinstance(..., ModelType),.as_dict(), or generated model base-class behavior. -
Replaced most generated enum classes with string literal type aliases. Use string values directly for protocol fields, for example
"completed","message", or"function_call_output". -
The resilient-task input persisted for a
store=truebackground response now
carries a singleuser_id_key(the durable per-user partition key) instead of
the previoususer_isolation_key/chat_isolation_keypair; conversation
scoping continues to useconversation_id.
Migration Guide
Async response event stream helpers now live under the aio namespace and no longer use the a prefix.
Before:
from azure.ai.agentserver.responses import ResponseEventStream
stream = ResponseEventStream(response_id=context.response_id, request=request)
async for event in stream.aoutput_item_message(token_stream()):
yield eventAfter:
from azure.ai.agentserver.responses.aio import ResponseEventStream
stream = ResponseEventStream(response_id=context.response_id, request=request)
async for event in stream.output_item_message(token_stream()):
yield eventBuilder async helpers follow the same pattern: use builders from azure.ai.agentserver.responses.aio.streaming and drop the a prefix. For example, atext_content(...) becomes text_content(...), aarguments(...) becomes arguments(...), and asummary_part(...) becomes summary_part(...).
Protocol models are now dict-native. Construction still works, but the result is a dictionary:
from azure.ai.agentserver.responses.models import ItemMessage, MessageContentInputTextContent
message = ItemMessage(
role="user",
content=[MessageContentInputTextContent(type="input_text", text="hello")],
)Before:
if isinstance(item, ItemMessage):
text = item.content[0].textAfter:
if item.get("type") == "message":
text = item.get("content", [{}])[0].get("text")Before:
status = ResponseStatus.COMPLETEDAfter:
status = "completed"Bugs Fixed
-
Steering now works on the first turn of a conversation. In a
steerable_conversations=truedeployment, the first turn (a request with no
conversation_idand noprevious_response_id) is now hosted on the
multi-turn chain primitive instead of a one-shot task. Because all turns of a
chain share a stableconversation_chain_id— and therefore the same backing
task — a steered turn posted onto an in-flight first turn previously queued
onto a one-shot task that completed and auto-deleted before draining the
queued input, leaving the steered turn stuckin_progress. The first turn now
suspends between turns and drains queued steering inputs correctly. -
context.conversation_chain_idis now stable across every turn of a
conversation. Previously it returned the rawprevious_response_id(the
immediate predecessor), so it shifted on every turn after the second — breaking
its use as a stable per-conversation key (e.g. an upstream SDK session id). It
is now derived from the partition key embedded in the chain's response IDs
(which every turn shares), so all turns of a chain — and the resilient task
that backs them — resolve to the same identity. The value is now an opaque,
agent/session-scoped hash rather than a raw id. (Known limitation: a client
that supplies its ownresponse_idwith a mismatched embedded partition can
shift the chain identity for later turns.)
Other Changes
- Bumped the minimum
azure-ai-agentserver-coredependency to>=2.0.0b9. - Reworked the resilient responses samples:
sample_21_resilient_langgraphis now a real-time streaming LangGraph agent that composes LangGraph's checkpointer with the framework's response checkpoints (see the "Composing an External Durable Engine" section of the handler guide), added real crash-harness e2e coverage for samples 19–22, and removed the copilot sample. - Updated response hosting, persistence, streaming, validation, samples, and tests to operate on JSON-compatible wire dictionaries.
- Updated model generation tooling to use TypeSpec Python
models-mode=typeddictand removed generated model shim files.