Skip to content

Pin OpenAI Agents SDK to chat-completions API#54

Closed
inf-quantavius wants to merge 1 commit into
context-labs:mainfrom
inf-quantavius:fix/sdk-use-chat-completions
Closed

Pin OpenAI Agents SDK to chat-completions API#54
inf-quantavius wants to merge 1 commit into
context-labs:mainfrom
inf-quantavius:fix/sdk-use-chat-completions

Conversation

@inf-quantavius

@inf-quantavius inf-quantavius commented May 22, 2026

Copy link
Copy Markdown
Contributor

Summary

The OpenAI Agents SDK defaults to the Responses API (/v1/responses), which the OpenAI-compatible providers HALO targets (Inference.net, OpenRouter, vLLM, …) do not implement; only api.openai.com does. The live integration test test_call_subagent_through_sdk_adapter_live started failing because the SDK posted to /v1/responses on the dev gateway, which closed the connection mid-stream — surfacing as APIConnectionError: Connection error. and turns_used=0.

Sister live test test_synthesize_traces_through_sdk_adapter_live keeps passing because it bypasses the SDK and calls client.chat.completions.create() directly.

Fix:

  • engine/main.py: call set_default_openai_api(\"chat_completions\") next to the existing set_default_openai_client(...) so HALO production is portable across the OpenAI-compatible ecosystem out of the box. Real OpenAI supports both APIs, so chat-completions is a strict superset.
  • tests/conftest.py: same call in pytest_configure, so the live integration tests that invoke tool factories directly via wired_tools (and never enter stream_engine_async) inherit the same default.
  • tests/unit/test_main.py: regression guard test_engine_pins_sdk_to_chat_completions_api.

Failing run for reference: https://github.com/context-labs/HALO/actions/runs/26316222866/job/77475862061

Test plan

  • Unit tests pass locally
  • Live integration tests pass on this branch via workflow_dispatch

Note

Medium Risk
Changes the OpenAI Agents SDK process-global default endpoint selection, which could affect all SDK calls at runtime, but is a small, targeted compatibility fix backed by tests.

Overview
Pins the OpenAI Agents SDK to use the chat_completions API instead of the default Responses API to ensure HALO works with OpenAI-compatible providers that don’t implement /v1/responses.

The engine now calls set_default_openai_api("chat_completions") alongside set_default_openai_client(...), tests pin the same default in pytest_configure for integration paths that bypass engine startup, and a new unit test guards the expected API selection.

Reviewed by Cursor Bugbot for commit 978b651. Bugbot is set up for automated code reviews on this repo. Configure here.

The SDK defaults to the Responses API (``/v1/responses``), which the
OpenAI-compatible providers HALO targets (Inference.net, OpenRouter,
vLLM, …) do not implement; only api.openai.com itself does. When the
live ``test_call_subagent_through_sdk_adapter_live`` integration test
spun up a subagent against the dev gateway, the SDK's Responses
streaming hit the gateway and got back a closed connection, surfacing
as ``APIConnectionError`` and zero turns used.

Fix: call ``set_default_openai_api("chat_completions")`` at engine run
start in ``stream_engine_async`` (so production is portable across the
OpenAI-compatible ecosystem) and in ``tests/conftest.py``'s
``pytest_configure`` (so test paths that invoke tool factories
directly via ``wired_tools``, without going through
``stream_engine_async``, inherit the same default). Real OpenAI
supports both APIs, so this is a strict superset.

Regression guard: ``test_engine_pins_sdk_to_chat_completions_api``
asserts ``stream_engine_async`` invokes ``set_default_openai_api`` with
``"chat_completions"`` exactly once.
@inf-quantavius

Copy link
Copy Markdown
Contributor Author

Heads up — I cannot trigger the live integration workflow myself: engine--integration-tests-live.yml only fires on workflow_dispatch / workflow_call, and my PAT (inf-quantavius) doesn't have admin rights to dispatch it. A maintainer needs to dispatch it against this PR's head:

gh workflow run engine--integration-tests-live.yml --repo context-labs/HALO --ref refs/pull/54/head

(or just click Run workflow and pick fix/sdk-use-chat-completions after pulling the branch into upstream).

Local evidence the fix lands the SDK on the right API path: with the change in place, the e2e tests' stack trace now goes through openai/resources/chat/completions/completions.py:2714 (chat-completions); before the change it was hitting agents/models/openai_responses.py:601. Same code path, different API choice — which is exactly what we want.

francescov1 pushed a commit that referenced this pull request May 23, 2026
…bal default

PR #50 ("Isolate the OpenAI Agents SDK") replaced an env-var-driven
configure_default_sdk_client(provider) with an unconditional
set_default_openai_client(client, use_for_tracing=False) inside
stream_engine_async. That works in production (where every Runner.run_streamed
goes through that entrypoint) but breaks tests that invoke the call_subagent
tool directly via tests/integration/tool_isolation_kit.wired_tools — those
never enter stream_engine_async, so the SDK default stays None and
OpenAIProvider lazy-constructs its own AsyncOpenAI from OPENAI_BASE_URL /
OPENAI_API_KEY env vars, dropping default_headers and any deterministic
close path. test_call_subagent_through_sdk_adapter_live started failing on
2026-05-22 with `APIConnectionError: Connection error.` raised mid-stream
against a request that never left the runner.

Fix: pass model_provider=OpenAIProvider(openai_client=client) on every
RunConfig the engine constructs. This makes prod and tests symmetric —
both paths now wire HALO's configured AsyncOpenAI to the SDK explicitly,
no global state, no env-var fallback. The engine still owns the client's
lifecycle (constructed in stream_engine_async, closed in its finally;
the wired_tools test path owns its own instance).

Bonus: removes a layer of SDK global state, which was already a footgun
for callers running multiple engines / multiple test modules in one
process.

Closes the regression that motivated the (now-closed) workaround PR #54.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants