Skip to content

[Provider compatibility] Cloud Code Assist rejects structured output on Gemini models #4669

Closed

Description

@agentHits

Client or integration

Codex App

Provider or upstream service

google-antigravity / Cloud Code Assist

OpenCodex version

2.56.0

Endpoint or capability

/v1/responses structured output / text.format

Current behaviour

Inbound requests with response_format / text.format routed to Gemini models on Cloud Code Assist (google-antigravity) are rejected locally with HTTP 400 before reaching the network:

google cloud-code-assist structured output is not implemented by opencodex — remove response_format or route this model through AI Studio or Vertex

Expected behaviour

Gemini models on Cloud Code Assist should accept structured output (json_schema and json_object) using the same generationConfig path as AI Studio and Vertex, placing responseMimeType and responseJsonSchema inside envelope.request.generationConfig. Non-Gemini models on Cloud Code Assist should continue to fail closed with an explicit rejection.

Minimal redacted request or reproduction

# Inbound request to OpenCodex proxy with text.format (structured output) routed to a Gemini model on Cloud Code Assist:
POST /v1/responses
{
  "model": "google-antigravity/gemini-3.8-flash",
  "text": {
    "format": {
      "type": "json_schema",
      "name": "result",
      "schema": {
        "type": "object",
        "properties": { "status": { "type": "string" } },
        "required": ["status"]
      }
    }
  }
}

Actual response or error

HTTP 400

{
  "error": {
    "message": "google cloud-code-assist structured output is not implemented by opencodex — remove response_format or route this model through AI Studio or Vertex"
  }
}

Upstream documentation

Gemini API structured output documentation: https://ai.google.dev/api/generate-content

Cloud Code Assist envelope wraps the Gemini generateContent request under envelope.request.

Suggested mapping or implementation notes

Allow Gemini models (modelId starting with gemini-) on Cloud Code Assist to pass structured output into generationConfig (responseMimeType: "application/json" and responseJsonSchema). The existing compileGoogleWireBody whitelist already allows both keys, carrying them into envelope.request.generationConfig. Non-Gemini models served through Cloud Code Assist should remain explicitly refused.

Additional context and attachments

Observed on OpenCodex 2.56.0 when Codex Desktop helper/worker requests with response_format are routed to google-antigravity/gemini-3.8-flash.

Checks

  • I searched existing provider and compatibility issues.
  • The request and response were redacted.
  • The expected behaviour is based on an upstream specification or a concrete client requirement.

Activity

  1. lidge-jun commented on Sep 15, 2026

    @lidge-jun
    Owner

    리뷰 · 우선순위 58 / 80

    이 이슈는 Google Cloud Code Assist(google-antigravity) 경로에서 Gemini 모델로 가는 structured output(text.format / response_format) 이 네트워크에 나가기 전에 로컬 HTTP 400 으로 거절된다는 호환성 보고다. 지금 dev(HEAD 9b711073a, 패키지 2.56.0)의 src/adapters/google.ts buildRequest 는 requestedTextFormat 이 있고 provider.googleMode === "cloud-code-assist" 이면 모델과 무관하게 바로 throw 한다. 메시지 문구가 이슈에 적힌 것과 같다: “google cloud-code-assist structured output is not implemented by opencodex — remove response_format or route this model through AI Studio or Vertex”. 그래서 Codex Desktop helper 가 google-antigravity/gemini-3.8-flash 로 json_schema 를 보내면 AI Studio/Vertex 와 달리 CCA 에서만 막힌다.

    기대 동작은 이슈 제안과 같다. modelId 가 gemini- 로 시작하면 AI Studio/Vertex 와 같이 generationConfig.responseMimeType / responseJsonSchema 를 채우고, CCA 엔벨로프는 그 flat body 를 envelope.request 안으로 감싼다. 비 Gemini(예: Claude-on-CCA)는 계속 명시 거절해야 한다. 침묵하면 스키마 없는 일반 문장이 성공처럼 보이기 때문이다. 이미지 출력 모델과 스키마 없는 json_schema 거절은 그대로 두는 것이 현재 불변식과 맞다.

    이미 고치는 초안 PR #4670 이 열려 있다(작성자 agentHits, Closes #4669). 거절 게이트를 Gemini 예외로 좁히고, envelope 위치·Claude-on-CCA 거절 회귀와 structure/providers/google.md 문구를 같이 맞춘다. grok-bot 은 #4670 에 별도 리뷰를 이미 남겼다(우선순위 69). 이 이슈 자체는 재현·기대·매핑 제안이 코드와 잘 맞고, 중복 이슈로 보이지 않는다. types.ts/config.ts 스플릿과 무관하다.

    라인 / 경로 수준:

    라인 798–807 (src/adapters/google.ts) - CCA 이면 structured output 전부 거절. 이슈 재현의 직접 원인이다
    라인 809–821 - 이미지 출력 모델·스키마리스 json_schema 거절은 CCA 완화와 독립적으로 남아야 한다
    라인 832–833 근처 - CCA thought 경로는 이미 /^gemini-/ 로 wire id 를 본다. 이슈 제안의 gemini- 허용과 같은 축이다
    경로 PR #4670 - draft. ready·CI·가능하면 한 번 CCA 스모크 후 머지하면 이 이슈를 닫을 수 있다

    메인테이너의 판단이 필요한 지점

    너의 추천
    새 구현 PR을 또 열지 말고 #4670 초안을 ready 로 밀어서 이 이슈를 닫는 쪽을 권한다. 이슈 본문의 매핑 제안과 현재 dev 코드·#4670 diff 가 같은 이야기다. 중복 close 대상이 아니라 “PR 대기 중” 상태로 두면 된다. types/config 스플릿 때문에 닫을 이슈가 아니다.

    이 댓글은 grok-bot이 작성했습니다

  2. honjow commented on Sep 16, 2026

    @honjow

    Upstream probe: responseJsonSchema is silently ignored on CCA — responseSchema is the key that actually constrains output

    I hit the same refusal on 2.56.0 (Codex auto-review against google-antigravity/gemini-3.8-flash) and ran a direct probe against the Cloud Code Assist envelope to check what the wire actually honors. The current PR direction (#4670, and the closed #4693) lifts the gate correctly, but both carry the schema in generationConfig.responseJsonSchema, which CCA does not enforce. This matters because it silently reintroduces exactly the failure the refusal gate was written to prevent: unconstrained prose returning as success.

    Probe method

    Direct POST {base}/v1internal:generateContent with the same envelope opencodex builds (model/userAgent/requestType/project/requestId/request), real Antigravity OAuth token, real IDE User-Agent, gemini-3.8-flash-medium.

    Discriminating prompt: "Summarize the history of the Eiffel Tower." — it never mentions JSON, a schema, or the enum value. The schema requires verdict_code with a single-value enum ZQ7-ALPHA, a token the model cannot produce by chance.

    {"type":"object","properties":{"verdict_code":{"type":"string","enum":["ZQ7-ALPHA"]}},"required":["verdict_code"]}

    Results (repeat runs, same envelope)

    request.generationConfig Constrained? Raw model output
    responseMimeType only (control) no "The Eiffel Tower, one of the world's most recognizable landmarks, has a rich his…"
    + responseJsonSchema (lowercase, object) no prose, no verdict_code
    + responseJsonSchema (lowercase, JSON-stringified) no prose, no verdict_code
    + responseSchema (Gemini typed form) yes {"verdict_code": "ZQ7-ALPHA"}

    responseJsonSchema behaves identically to the control: HTTP 200, schema silently dropped, prose returned. responseSchema constrains correctly. Reproduced on gemini-3.8-flash-medium (all four cases), and the same split held on gemini-3.7-flash (responseJsonSchema → prose, responseSchema → conforming JSON).

    Claude-on-CCA differs from the assumption in #4670

    #4670 keeps a blanket refusal for non-Gemini models on CCA. That refusal is currently untestable in the direction that matters, because Claude-on-CCA takes a different transport for structured output rather than ignoring it:

    claude-sonnet-4-6 + responseJsonSchema  -> prose text part
    claude-sonnet-4-6 + responseSchema      -> functionCall: {"name":"json_mode","args":{"verdict_code":"ZQ7-ALPHA"}}
    claude-sonnet-4-6 + responseMimeType    -> prose text part
    

    So on this envelope Claude answers a structured-output request with a synthetic functionCall named json_mode carrying the conforming arguments, instead of text. A refusal for Claude would therefore also be a compatibility decision worth stating explicitly, not just "unimplemented" — and if it is ever admitted, the json_mode call has to be unwrapped back into assistant text, or it will surface as a bogus tool call to the client.

    Suggested correction

    • Keep lifting the gate for gemini-* (that part of fix(google): allow structured output for Gemini models on Cloud Code Assist #4670 is right).
    • Carry the schema as generationConfig.responseSchema in Gemini's typed form (OBJECT/STRING/ARRAY/INTEGER/NUMBER/BOOLEAN) on Cloud Code Assist. The AI Studio / Vertex path can keep responseJsonSchema; the two keys are not interchangeable here.
    • responseSchema is a new key for the compileGenerationConfig whitelist in google-wire-compiler.ts — it is currently not listed, so setting it in the adapter alone is dropped before the wire. (The same trap the existing comment already warns about for the other two keys.)
    • Note that responseMimeType: "application/json" alone does not constrain CCA output either (control row above), so a fix that ships only responseMimeType would still return prose.

    Environment

    • opencodex 2.56.0 (@bitkyc08/opencodex, installed at ~/.local/lib/node_modules)
    • Provider google-antigravity, googleMode: "cloud-code-assist", baseUrl https://daily-cloudcode-pa.googleapis.com
    • CCA models probed: gemini-3.8-flash-medium, gemini-3.7-flash-medium, claude-sonnet-4-6
    • All requests and outputs redacted; no credential material included.
  3. lidge-jun commented on Sep 16, 2026

    @lidge-jun
    Owner

    Landed via #4719 at f6843be (on tip f6843be with lane #4719; member #4670). dev is not the default branch so GitHub did not auto-close from the PR's Closes line.

    이 댓글은 grok-bot이 작성했습니다

  4. lidge-jun commented on Sep 16, 2026

    @lidge-jun
    Owner

    Landed via #4719 at f6843be (member #4670). Cloud Code Assist Gemini models now allow structured output (text.format / response_format). Closing as completed.

  5. lidge-jun commented on Sep 16, 2026

    @lidge-jun
    Owner

    Landed via #4670 at 3169dfe (via maintainer lane #4719 at f6843be). dev is not the default branch so GitHub did not auto-close from the PR's Closes line.

    이 댓글은 grok-bot이 작성했습니다

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    providerProvider adapters, OpenAI-compat presets, upstream API quirksprovider-compatibilityProvider compatibility reports

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions