hermes-agent/agent/transports
Ben Barclay f52feed1ef
fix(azure-foundry): scope Responses reasoning suppression to post-tool turns (#84320)
Azure Foundry's OpenAI-compatible Responses surface rejects the post-tool
follow-up payload with HTTP 400 `invalid_payload` when a replayed encrypted
`reasoning` item is sent alongside `function_call` / `function_call_output`.
The initial function-call request and ordinary multi-turn continuity are both
accepted, so the failure only appears after the first tool executes.

Detect the Foundry endpoint in `ResponsesApiTransport.build_kwargs` and drop
only the encrypted reasoning replay on that follow-up turn, leaving
function_call / function_call_output continuity intact.

Salvage of #59981, rebuilt on current main. Same root cause and fix direction
as the original, which was correct; this version resolves three defects:

- No `chat_completion_helpers.py` change. main already forwards `provider`
  and `base_url` to the Responses transport, so the original's re-added
  arguments produced `SyntaxError: keyword argument repeated: provider` on
  merge. Dropping the hunk removed the syntax error and the conflict.

- Host matching uses `utils.base_url_host_matches`, not a substring test.
  `".services.ai.azure.com" in base_url` also matches URLs carrying the
  domain in a path or query segment, which would silently disable reasoning
  replay on an unrelated provider.

- The post-tool predicate tests the trailing messages, not the whole history.
  Scanning for any tool call plus any tool result made it sticky: one tool
  call early in a conversation suppressed reasoning on every later turn.

- Tool calls pair on `call_id` as well as `id`. Responses histories carry the
  function call id in `call_id` while `id` holds the response item id
  (`fc_...`). Identity is resolved via the converter's own
  `_split_responses_tool_id`, covering composite `"call_x|fc_y"` ids and bare
  `fc_` ids on both sides of the pairing.

Tests: 27 cases across the transport and the live `build_api_kwargs` bridge,
including six parametrized tool-call id shapes, non-Foundry host lookalikes,
the sticky-history guard, parallel tool results, and an unpaired tool result.
Each guard was confirmed to catch its defect by reverting the fix.

Verified with `scripts/run_tests.sh tests/agent/ tests/run_agent/`:
532 files, 5602 tests passed, 0 failed.

Not verified against a live Azure Foundry endpoint — no credentials. The
original HTTP 400 reproduction and post-fix Foundry Project / Azure Container
Apps harness runs are @AshuJoshi's, from #59981. This change is verified at
the payload-construction layer only.

Closes #59981.

Co-authored-by: Ashu Joshi <AshuJoshi@users.noreply.github.com>
2026-08-14 12:41:26 +10:00
..
__init__.py
anthropic.py fix(anthropic): also normalize MCP-server tool names to mcp__ on OAuth wire 2026-06-17 13:20:29 +05:30
base.py
bedrock.py
chat_completions.py fix(transport): use getattr for supports_prompt_cache_key on stale profiles 2026-08-09 23:19:39 -07:00
codex.py fix(azure-foundry): scope Responses reasoning suppression to post-tool turns (#84320) 2026-08-14 12:41:26 +10:00
codex_app_server.py fix: add explicit UTF-8 encoding to all subprocess text=True calls (#53428) 2026-07-24 11:45:57 -07:00
codex_app_server_session.py fix(approval): classify CLI/TUI approval timeouts separately from explicit denials 2026-08-02 20:21:59 -07:00
codex_event_projector.py feat(mcp): adopt mcp__server__tool naming convention 2026-07-05 13:40:21 -07:00
hermes_tools_mcp_server.py fix: complete kanban review lifecycle 2026-08-10 12:43:46 -07:00
types.py fix(anthropic): preserve interleaved thinking/tool_use block order on replay 2026-06-10 20:45:16 -07:00