Skip to content

OpenAI-compatible tool schema marks all properties as required, breaking optional tool arguments #468

@kuangxinfeng-26

Description

@kuangxinfeng-26

Description

In CLIProxyAPIPlus, the OpenAI-compatible request sent upstream appears to incorrectly mark all tool schema properties as required, even when the original tool schema contains optional fields.

This breaks tool/function calling clients that rely on optional arguments.

I verified this with request logs and can confirm the malformed schema is already present in the upstream API request body generated by CLIProxyAPIPlus.


Version

CLIProxyAPIPlus: v6.9.1-0-plus


Expected behavior

If the original tool schema is:

{
  "type": "object",
  "properties": {
    "sessionKey": { "type": "string" },
    "label": { "type": "string" },
    "agentId": { "type": "string" },
    "message": { "type": "string" },
    "timeoutSeconds": { "type": "number" }
  },
  "required": ["message"]
}

then the upstream OpenAI-compatible request should preserve that structure:

  • message required
  • sessionKey optional
  • label optional
  • agentId optional
  • timeoutSeconds optional

Actual behavior

The tool schema sent upstream becomes:

{
  "type": "object",
  "required": ["sessionKey", "label", "agentId", "message", "timeoutSeconds"],
  "properties": {
    "sessionKey": { "type": "string" },
    "label": { "type": "string" },
    "agentId": { "type": "string" },
    "message": { "type": "string" },
    "timeoutSeconds": { "type": "number" }
  }
}

So optional fields are incorrectly promoted into required.

This causes downstream failures. For example, a tool that expects sessionKey or label (mutually exclusive optional selectors) becomes unusable because both are marked required.


Concrete impact

One affected tool is sessions_send.

Its intended schema is effectively:

  • sessionKey?
  • label?
  • agentId?
  • message required
  • timeoutSeconds?

But the upstream request generated by CLIProxyAPIPlus marks all of them as required.

This causes real breakage such as:

  • client forced to send both sessionKey and label
  • backend rejects request with:
    • Provide either sessionKey or label (not both).

Additional evidence

This is not limited to one tool.

In the same logged request, other tools also had the same problem:

  • read
  • write
  • edit
  • process
  • sessions_spawn

It looks like the transformation layer is systematically turning all properties into required.

So this seems to be a generic tool/function schema conversion bug, not a tool-specific schema bug.


What I verified

I checked the original application/tool schema before CLIProxyAPIPlus:

  • optional fields were defined correctly

I also enabled request logging in CLIProxyAPIPlus and confirmed the malformed schema is already present in the outbound API request body.

So this does not appear to be:

  • a downstream model interpreting the schema incorrectly
  • a backend tool implementation bug
  • a single-tool schema authoring mistake

It appears to happen during CLIProxyAPIPlus request/tool schema transformation.


Suspected area

Likely somewhere in the OpenAI-compatible tool/function schema conversion path, where properties may be getting incorrectly copied into required.

Possibly related areas:

  • OpenAI-compatible request transformation
  • tool/function schema translation
  • JSON Schema generation / rewriting

Reproduction idea

Any client that exposes tools with optional properties should be enough.

For example, define a tool like:

{
  "type": "function",
  "function": {
    "name": "example_tool",
    "description": "test",
    "parameters": {
      "type": "object",
      "properties": {
        "foo": { "type": "string" },
        "bar": { "type": "string" },
        "baz": { "type": "string" }
      },
      "required": ["baz"]
    }
  }
}

Expected upstream payload:

  • only baz is required

Actual upstream payload observed:

  • foo, bar, baz all become required

Notes

I checked the generated request log rather than only inspecting client-side tool metadata, so this issue is confirmed in the actual payload emitted by CLIProxyAPIPlus.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions