You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Part of #113 (Claude Code integration). This is the core value-add.
When the model emits a gateway-ownedtool_use (web_search, MCP), the gateway must execute it server-side and continue the loop — never handing it back to Claude Code. The spike proved this is the only mechanism that works: Claude Code errors on any tool it didn't declare, so gateway tools must stay invisible to the client (see #98 → Verification).
Scope:
Map Anthropic tool_use/tool_result content blocks to the shared tool framework's gateway-owned vs. client-owned classification.
Run the hide-the-call loop (run_until_gateway_tools_complete, landed in refactor: drive gateway tool loop with LoopDecision (PR B) #83) on the Messages path: inject the gateway tool into the upstream call only, execute it, append the tool_result, loop, surface only the final assistant message.
Emit correct Anthropic SSE for surfaced calls and suppress hidden gateway calls (reuses the existing emit_gateway_*_events logic on main; keep block index contiguous).
Handle parallel tool_use, the full stop_reason set (incl. pause_turn), and streaming input_json_delta args.
Record the acceptance cassette — the upstream Messages turns (turn 0: model emits the gateway tool_use; turn 1: final text after the tool_result) so the loop is covered hermetically in CI, not only live. This records the upstream side, so it reuses the test: record real gateway tool loop cassettes (OpenAI + vLLM) #94 recorder pattern and doesn't depend on the loop existing — it can start immediately. May need a small recorder change for the Messages response shape.
Acceptance test: a real gateway-owned web_search turn completes end-to-end through /v1/messages with the tool hidden from the client, replayed from that cassette.
Dependency: the shared loop is currently typed to RequestPayload/ResponsePayload; Stage 2's clean form needs it factored to an API-agnostic shape. That factoring is owned by the pending Layering ADR (tool-framework.md Future Work), so this should sequence after / alongside that decision, not reshape the core unilaterally. (The cassette recording sub-task above has no such dependency and can begin right away.)
Part of #113 (Claude Code integration). This is the core value-add.
When the model emits a gateway-owned
tool_use(web_search, MCP), the gateway must execute it server-side and continue the loop — never handing it back to Claude Code. The spike proved this is the only mechanism that works: Claude Code errors on any tool it didn't declare, so gateway tools must stay invisible to the client (see #98 → Verification).Scope:
tool_use/tool_resultcontent blocks to the shared tool framework's gateway-owned vs. client-owned classification.run_until_gateway_tools_complete, landed in refactor: drive gateway tool loop with LoopDecision (PR B) #83) on the Messages path: inject the gateway tool into the upstream call only, execute it, append thetool_result, loop, surface only the final assistant message.emit_gateway_*_eventslogic onmain; keep blockindexcontiguous).tool_use, the fullstop_reasonset (incl.pause_turn), and streaminginput_json_deltaargs.tool_use; turn 1: final text after thetool_result) so the loop is covered hermetically in CI, not only live. This records the upstream side, so it reuses the test: record real gateway tool loop cassettes (OpenAI + vLLM) #94 recorder pattern and doesn't depend on the loop existing — it can start immediately. May need a small recorder change for the Messages response shape.web_searchturn completes end-to-end through/v1/messageswith the tool hidden from the client, replayed from that cassette.Dependency: the shared loop is currently typed to
RequestPayload/ResponsePayload; Stage 2's clean form needs it factored to an API-agnostic shape. That factoring is owned by the pending Layering ADR (tool-framework.md Future Work), so this should sequence after / alongside that decision, not reshape the core unilaterally. (The cassette recording sub-task above has no such dependency and can begin right away.)Happy to take this one.