Files
agent-framework/python/packages/openai/tests
T
Evan Mattson 09a3d0d307 Python: Strip server-issued response item IDs under storage (#3295) (#5690)
Fixes microsoft/agent-framework#3295. When the OpenAI Responses chat
client sends a request that carries previous_response_id / conversation_id
/ conversation, the server already has the prior turn's response items
and rejects duplicates with "Duplicate item found with id fc_xxx". The
chat client was re-sending them inline whenever the input messages still
carried the items in additional_properties (workflow replay, history
providers, etc.), which broke any tool-using agent with persistent
history.

Decisions:
- Single chokepoint: _prepare_message_for_openai. When the resulting
  request uses service-side storage, drop function_call, reasoning,
  approval-request/response, and local-shell-call items from the wire
  input. Keep function_result with its call_id; the server pairs it to
  the prior function_call via that key.
- function_result is preserved unconditionally except for the local-shell
  variant, which carries its own server-issued item id.
- No public API change. Wire format change is subtractive and only on
  requests that would otherwise 400.
- Re-pointed the strict-xfail in test_full_conversation.py from #4047 to
  #3295. Kept xfail because the test asserts executor-level session-id
  clearing, which is the defense-in-depth half tracked by 3295-03; this
  slice closes the wire-level half.

Files:
- python/packages/openai/agent_framework_openai/_chat_client.py: strip
  rule applied alongside the existing reasoning-item branch.
- python/packages/openai/tests/openai/test_openai_chat_client.py: four
  new tests pin the contract (function_call, approval, local-shell-call
  stripped under storage; everything kept without storage). Updated
  pre-existing tests that exercised the storage-on path to either pass
  request_uses_service_side_storage=False explicitly or assert the new
  strip behavior.
- python/packages/foundry/tests/foundry/test_foundry_chat_client.py:
  same explicit storage-off opt-in for the inherited test.
- python/packages/core/tests/workflow/test_full_conversation.py:
  re-pointed xfail reason to #3295 and the executor-level follow-up.

Notes for next iteration:
- 3295-01 (HITL wire-format validation against live OpenAI/Foundry) was
  not run; it requires the user's API credentials. The PRD design is
  locked but the empirical confirmation is still pending. If script 3
  fails on either provider, this slice may need to be revisited.
- 3295-03 (clear service_session_id in AgentExecutor on full-history
  replay) remains open. After it lands the xfail in
  test_full_conversation.py can be removed.
- pytest was not run in this iteration because uv-based pytest commands
  required interactive approval. Validation rests on careful reading;
  next iteration should run the openai + core test suites.
09a3d0d307 ยท 2026-05-13 22:09:04 +00:00
History
..