Skip to content

Conversation

@eavanvalkenburg
Copy link
Member

Summary

Adds support for long-running agent operations and background responses, matching the dotnet implementation pattern adapted to Python conventions.

Fixes #2478

Changes

Core Types (_types.py)

  • Added ContinuationToken TypedDict — a simple JSON-serializable dict with response_id field
  • Added continuation_token: ContinuationToken | None to ChatResponse, ChatResponseUpdate, AgentResponse, and AgentResponseUpdate
  • Updated map_chat_to_agent_update and _process_update to propagate tokens

OpenAI Responses Client (_responses_client.py)

  • Added background: bool and continuation_token: ContinuationToken to OpenAIResponsesOptions
  • Non-streaming: polls via responses.retrieve(response_id) when continuation_token is provided
  • Streaming: resumes via responses.retrieve(response_id, stream=True) when continuation_token is provided
  • Sets continuation_token on responses when OpenAI status is in_progress or queued

Agent Layer (_agents.py)

  • Propagates continuation_token from ChatResponseAgentResponse in non-streaming path

Telemetry Fix (observability.py)

  • Fixed pre-existing Failed to detach context error in both ChatTelemetryLayer and AgentTelemetryLayer streaming paths
  • Root cause: trace.use_span() context was attached synchronously but detached in async cleanup hooks (different async context)
  • Fix: create spans directly with start_span() + span.end() for streaming, avoiding context attachment

Tests

  • 14 new unit tests covering token serialization, response types, background status parsing, streaming events, and options handling

Sample

  • samples/concepts/background_responses.py demonstrating non-streaming polling and streaming resumption patterns

Usage

# Non-streaming polling
response = await agent.run(messages="Task", options={"background": True})
while response.continuation_token is not None:
    await asyncio.sleep(2)
    response = await agent.run(options={"continuation_token": response.continuation_token})

# Streaming with resumption
stream = agent.run(messages="Task", stream=True, options={"background": True})
async for update in stream:
    last_token = update.continuation_token
# Resume: agent.run(stream=True, options={"continuation_token": last_token})

Copilot AI review requested due to automatic review settings February 10, 2026 13:49
@eavanvalkenburg eavanvalkenburg added python v1.0 Features being tracked for the version 1.0 GA labels Feb 10, 2026
@markwallace-microsoft markwallace-microsoft added the documentation Improvements or additions to documentation label Feb 10, 2026
@markwallace-microsoft
Copy link
Member

markwallace-microsoft commented Feb 10, 2026

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/a2a/agent_framework_a2a
   _agent.py167994%357, 378, 451–452, 489–490, 519–521
packages/core/agent_framework
   _agents.py3203589%475, 883, 920, 1019–1021, 1134, 1175, 1177, 1186–1191, 1197, 1199, 1209–1210, 1217, 1219–1220, 1228–1232, 1240–1241, 1243, 1248, 1250, 1284, 1324, 1344
   _types.py10459690%83, 92–93, 147, 152, 171, 173, 177, 181, 183, 185, 187, 205, 209, 235, 257, 262, 267, 271, 297, 301, 647–648, 1019, 1081, 1098, 1116, 1121, 1139, 1149, 1166–1167, 1169, 1187–1188, 1190, 1197–1198, 1200, 1235, 1246–1247, 1249, 1287, 1544, 1597, 1604, 1626, 1632, 1680, 1723–1728, 1750, 1755, 1921, 1933, 2176, 2185, 2206, 2301, 2526, 2733, 2803, 2815, 2822, 2833, 3037–3039, 3042–3044, 3048, 3053, 3057, 3169–3171, 3199, 3253, 3257–3259, 3261, 3272–3273, 3276–3280, 3286
   observability.py6118486%334, 336–338, 341–343, 348–349, 355–356, 362–363, 370, 372–374, 377–379, 384–385, 391–392, 398–399, 406, 662, 665, 673–674, 677–680, 682, 685–687, 690–691, 719, 721, 732–734, 736–739, 743, 751, 852, 854, 1003, 1005, 1009–1014, 1016, 1019–1023, 1025, 1137–1138, 1140, 1197–1198, 1333, 1387–1388, 1504–1506, 1565, 1735, 1889, 1891
packages/core/agent_framework/openai
   _responses_client.py6047787%298–301, 305–306, 309–310, 316–317, 322, 335–341, 362, 370, 393, 455, 487, 512, 518, 536–537, 559, 564, 621, 635, 652, 665, 720, 799, 804, 808–810, 814–815, 838, 907, 929–930, 945–946, 964–965, 1096–1097, 1113, 1115, 1194–1202, 1297, 1352, 1367, 1403–1404, 1406–1408, 1422–1424, 1434–1435, 1441, 1456
TOTAL16695207587% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
3964 225 💤 0 ❌ 0 🔥 1m 10s ⏱️

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Python support for long-running agent operations via OpenAI Responses “background” runs, including continuation token propagation across core response types, OpenAI client polling/resumption paths, telemetry fixes for streaming spans, plus tests and a sample.

Changes:

  • Introduces a ContinuationToken TypedDict and propagates it through ChatResponse* and AgentResponse* types and mapping/merge logic.
  • Extends OpenAIResponsesClient options with background + continuation_token, enabling non-streaming polling and streaming resumption via retrieve.
  • Fixes OpenTelemetry streaming span lifecycle handling and adds unit tests + a usage sample + changelog entry.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
python/packages/core/agent_framework/_types.py Adds ContinuationToken and plumbs continuation_token through response/update types and update processing.
python/packages/core/agent_framework/openai/_responses_client.py Adds background + continuation token support, including polling and stream resumption behavior.
python/packages/core/agent_framework/_agents.py Propagates continuation_token into AgentResponse (non-streaming path).
python/packages/core/agent_framework/observability.py Fixes streaming span detach errors by avoiding context attachment for spans closed in async cleanup.
python/packages/core/tests/openai/test_openai_responses_client.py Adds unit tests covering token serialization/propagation and background status handling.
python/samples/concepts/background_responses.py Adds a sample demonstrating polling and streaming resumption patterns.
python/CHANGELOG.md Documents the new long-running/background responses feature.

@eavanvalkenburg eavanvalkenburg added this pull request to the merge queue Feb 10, 2026
@eavanvalkenburg eavanvalkenburg removed this pull request from the merge queue due to a manual request Feb 10, 2026
@eavanvalkenburg eavanvalkenburg added this pull request to the merge queue Feb 10, 2026
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to a conflict with the base branch Feb 10, 2026
- Add ContinuationToken TypedDict to core types
- Add continuation_token field to ChatResponse, ChatResponseUpdate,
  AgentResponse, and AgentResponseUpdate
- Add background and continuation_token options to OpenAIResponsesOptions
- Implement polling via responses.retrieve() and streaming resumption
  in RawOpenAIResponsesClient
- Propagate continuation tokens through agent run() and
  map_chat_to_agent_update
- Fix streaming telemetry 'Failed to detach context' error in both
  ChatTelemetryLayer and AgentTelemetryLayer by avoiding
  trace.use_span() context attachment for async-managed spans
- Add 14 unit tests for continuation token types and background flows
- Add background_responses sample showing polling and stream resumption

Fixes microsoft#2478
- Make ContinuationToken provider-agnostic (total=False, optional task_id/context_id fields)
- Add background param to A2AAgent.run() controlling token emission
- Add poll_task() for single-request task state retrieval
- Add resubscribe support via continuation_token param on run()
- Extract _updates_from_task() and _map_a2a_stream() for cleaner code
- Streamline run()/streaming by removing intermediate _stream_updates wrapper
- Update A2A sample to show background=False (default) with link to background_responses sample
- Remove stale BareAgent from __all__
- Add 12 new A2A continuation token tests
@eavanvalkenburg eavanvalkenburg added this pull request to the merge queue Feb 10, 2026
Merged via the queue into microsoft:main with commit 35097d8 Feb 10, 2026
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation python v1.0 Features being tracked for the version 1.0 GA

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: Long running agents support

3 participants