Skip to content

harness(openai): OpenAI Responses API (/v1/responses) + codex knobs#51

Merged
senamakel merged 1 commit into
mainfrom
harness/openai-responses-api
Jul 11, 2026
Merged

harness(openai): OpenAI Responses API (/v1/responses) + codex knobs#51
senamakel merged 1 commit into
mainfrom
harness/openai-responses-api

Conversation

@senamakel

Copy link
Copy Markdown
Member

Summary

Adds a second wire shape to OpenAiModel, selected by with_responses_api_primary(): the OpenAI Responses API (/v1/responses), which the OpenAI Codex OAuth path requires.

  • responses.rs — Responses request/response types + translation. build_responses_input folds system messages into instructions and maps user/assistant/tool turns to input items (assistant/tool → output_text, else input_text, matching the API's role/kind rules); extract_responses_text prefers the terminal output_text, else the first output_text content part; parse_responses_response maps onto ModelResponse (text + usage). Unit-tested.
  • Builderswith_responses_api_primary(), with_responses_omit_max_output_tokens() (Codex rejects the cap), with_extra_query_param() (Codex client_version), with_user_agent() (Codex CLI UA). authorized() now applies the UA + query params.
  • invoke() routes to /responses when responses_api_primary; a 400 implicating max_output_tokens retries once without it. stream() surfaces the unary result as a single terminal Completed (true Responses SSE is a follow-up).

Text-in/text-out for now — native tools over /responses are a follow-up; a harness embeds tool specs in the prompt for this path.

Commands run

  • cargo fmt --check
  • cargo test --lib openai:: — 65 pass
  • cargo clippy --lib -- -D warnings — clean

Note

Live per-provider validation (real OpenAI /responses + Codex OAuth) is deferred to a dedicated run; this lands the translation + wiring.

Add a second wire shape to OpenAiModel, selected by with_responses_api_primary():
the OpenAI Responses API (/v1/responses), which the codex OAuth path requires.

- responses.rs: ResponsesRequest/Response types + translation. build_responses_input
  folds system messages into  and maps user/assistant/tool turns to
   items (assistant/tool -> output_text, else input_text, matching the API's
  role/kind rules). extract_responses_text prefers the terminal , else
  the first output_text content part. parse_responses_response maps onto ModelResponse
  (text + usage). Unit-tested.
- OpenAiModel: with_responses_api_primary(), with_responses_omit_max_output_tokens()
  (codex rejects the cap), with_extra_query_param() (codex client_version),
  with_user_agent() (codex CLI UA). authorized() now applies the UA + query params.
- invoke() routes to /responses when responses_api_primary; a 400 implicating
  max_output_tokens retries once without it. stream() surfaces the unary result as
  a single terminal Completed (true Responses SSE is a follow-up).

Text-in/text-out for now (native tools over /responses are a follow-up; the harness
embeds tool specs in the prompt). fmt + clippy -D warnings clean; 65 openai tests pass.

NOTE: live per-provider validation deferred to a dedicated tinyagents run.
@senamakel senamakel merged commit 94a3e97 into main Jul 11, 2026
2 checks passed
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 11 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 16c32d94-3eb2-4542-8bb2-10b25320027b

📥 Commits

Reviewing files that changed from the base of the PR and between b580f1a and 949748a.

📒 Files selected for processing (3)
  • src/harness/providers/openai/mod.rs
  • src/harness/providers/openai/responses.rs
  • src/harness/providers/openai/transport.rs

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 949748a074

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +809 to +813
responses::ResponsesRequest {
model,
input,
instructions,
stream: None,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve tool/schema requests on Responses calls

When with_responses_api_primary() is used, this translator only forwards the model/messages-style input and output cap; normal agent runs still populate ModelRequest.tools, tool_choice, and response_format, and the model profile still advertises native tool calling/schema support. In those contexts the resolver will select this model, but the Responses request never tells OpenAI about the available tools or required schema, so tool execution and structured-output extraction can fail even though the capability was advertised. Please serialize the Responses equivalents or reject/disable these capabilities for this mode.

Useful? React with 👍 / 👎.

Comment on lines +178 to +183
let parsed: ResponsesResponse =
serde_json::from_value(value.clone()).unwrap_or(ResponsesResponse {
output: Vec::new(),
output_text: None,
usage: None,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Propagate malformed Responses bodies instead of blank success

If the Responses endpoint returns a 2xx body with an unexpected shape, the deserialization error is swallowed and callers receive an empty assistant message with finish_reason: "stop". That differs from the chat-completions parser and can turn provider/API drift into a successful blank answer, especially because error_on_empty_response is opt-in. Return a Result from this parser and propagate the serde/model error instead of defaulting to an empty response.

Useful? React with 👍 / 👎.

@senamakel senamakel deleted the harness/openai-responses-api branch July 11, 2026 22:37
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.

1 participant