Skip to content

Tool schema compression rebuilds input_schema from a short allowlist and drops strict, pattern, const and oneOf #116

Description

@Android-Login-Analysis

Summary

The tool description compressor rebuilds each tool's input_schema rather than copying it. Keywords that are not on its allowlist do not survive, so a caller's parameter constraints are absent from the upstream request. The call returns 2xx.

Root cause

Verified at 23cc328c1838. src/prompts/system.js:87

const input_schema = tool.input_schema || { type: "object", properties: {} };
const compressed = {
  ...
  input_schema: {
    type: input_schema.type || "object",
    properties: {},
    required: input_schema.required || [],
  }
};
...
if (input_schema.properties) {
  for (const [key, value] of Object.entries(input_schema.properties)) {
    compressed.input_schema.properties[key] = { ... };
  }
}

The rebuild keeps type, properties and required. It does not carry strict from the tool level, and the per-property copy does not carry pattern, const or oneOf. Called from src/orchestrator/index.js:1565.

Captured

Client:

{"model": "<provider-model>", "messages": [{"role": "user", "content": "G1 controlled request."}],
 "tools": [{"type": "function", "function": {"name": "tool_a", "description": "Controlled G1 tool.",
            "strict": true, "parameters": {"type": "object", "properties": {}}}}]}

The forwarded request carries the rebuilt schema with no strict.

Reproduction

Built from this repository at an unmodified commit. The upstream is a recording endpoint that stores the exact request bytes it receives and returns a fixed valid response.

curl -X POST http://localhost:<port>/v1/chat/completions \
  -H 'content-type: application/json' -H "authorization: Bearer $KEY" \
  -d '{"model":"<provider-model>","messages":[{"role":"user","content":"hi"}],
       "tools":[{"type":"function","function":{"name":"tool_a","description":"t","strict":true,
                 "parameters":{"type":"object","properties":{"recipient":{"type":"string","pattern":"^(alice|bob)$"}},"required":["recipient"]}}}]}'

Compare pattern and strict in the outbound request.

Expected

Compression is aimed at description length, so the schema does not need rebuilding to achieve it. Copying input_schema through and compressing only the text fields would keep the constraints. If the rebuild is needed for another reason, then the keyword list should at least cover the enforceable ones, and a caller whose constraint is dropped should be told rather than getting a 2xx.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions