Skip to content

[Bug] openai-chat V2 spawn_agent emits empty arguments when message schema contains encrypted:true #1774

Description

@ZHJay

Client or integration

Codex App

Provider or upstream service

burnopenai (OpenAI-compatible Chat Completions upstream through the openai-chat adapter)

OpenCodex version

2.19.0 (also present by static inspection on current dev at c71c827)

Endpoint or capability

/v1/responses to openai-chat / Chat Completions translation; V2 collaboration spawn_agent tool calls

Current behaviour

With V2 collaboration enabled and a routed openai-chat parent, Codex supplies a complete spawn_agent schema whose required message property carries the Responses-only annotation encrypted: true.

OpenCodex preserves required: ["message"], but also forwards the non-standard annotation unchanged in tools[].function.parameters to the Chat Completions upstream. In the reproduced provider/model combination, the upstream then emits a spawn_agent call with zero argument bytes; OpenCodex normalizes that to {}, and Codex rejects it because message is missing. No child agent is created, and the parent retries.

One archived session produced 24 spawn_agent calls: 24/24 had arguments exactly {}, and all 24 corresponding tool results reported missing field message.

The generic openai-chat path still forwards the annotation on current dev; only the Zen-specific schema sanitizer currently drops it.

Expected behaviour

At the Responses to Chat Completions adapter boundary, OpenCodex should remove the Responses-only encrypted schema annotation before serializing Chat Completions tools, while preserving:

  • required: ["message"] and all other supported schema constraints;
  • legitimate tool property/definition names that are literally encrypted;
  • literal data under keywords such as const, default, enum, and examples.

Native OpenAI Responses passthrough should continue to preserve the annotation. The routed parent should emit a valid, non-empty message and create the child once.

Minimal redacted request or reproduction

# Environment
# OpenCodex 2.19.0, macOS, V2 collaboration
# Parent: burnopenai/gpt-5.6-sol, reasoning effort xhigh

# 1. Start a fresh Codex App task using the routed parent.
# 2. Ask it to delegate exactly one self-contained task with spawn_agent.
# 3. Observe repeated empty spawn_agent calls and no child creation.

# The incoming schema at the adapter boundary contains:
{
  "type": "object",
  "properties": {
    "message": { "type": "string", "encrypted": true }
  },
  "required": ["message"]
}

# On unmodified 2.19.0, createOpenAIChatAdapter(...).buildRequest(...)
# serializes the same message schema to tools[].function.parameters,
# including encrypted:true.

A controlled forced-tool A/B used the same upstream, model, prompt, and spawn_agent tool:

message schema contains encrypted:true  -> arguments are empty ("" / {})
only the encrypted annotation removed   -> {"message":"Reply exactly: READY"}

The result was the same for flat and namespace: collaboration tool shapes, which rules out namespace conversion as the differentiator.

Actual response or error

function_call name=spawn_agent namespace=collaboration arguments={}
function_call_output failed to parse function arguments: missing field message at line 1 column 2

# Redacted session totals:
spawn_agent calls: 24
arguments exactly {}: 24
missing-field-message errors: 24
children created: 0

Upstream documentation

No public provider or JSON Schema specification was found for the Codex encrypted annotation. It is identified in this repository as a Responses/ChatGPT-backend-only marker introduced by upstream OpenAI Codex, and the same compatibility class was confirmed and fixed for Google/Kiro in #85 and defensively handled by the Anthropic adapter.

The concrete client requirement is that Responses-private schema metadata must not change required Chat Completions tool-call arguments during protocol translation.

Suggested mapping or implementation notes

Sanitize tool parameter schemas once in the generic openai-chat adapter before provider-specific Chat Completions formatting. Strip encrypted only when it is a schema keyword, not when it is a property/definition name or literal JSON data. The existing Anthropic implementation already distinguishes schema-name maps and literal-value keywords and may be a useful precedent.

A focused regression should assert that nested annotations are removed, required: ["message"] survives, a property literally named encrypted survives, literal encrypted data survives, and the input schema is not mutated.

I am happy to prepare a focused PR with the adapter fix and behavior-contract regression test.

Additional context and attachments

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

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