Skip to content

github-copilot: tools[].eager_input_streaming still rejected on v2026.4.29 (re: #72183) #75348

Description

@finchinslc

Bug

#72183 was auto-closed on 2026-04-26 with a verdict that v2026.4.24 fixed the eager_input_streaming schema rejection on github-copilot/claude-*. It did not. The bug is 100% reproducible on v2026.4.29.

I'm filing this as a new issue because #72183 is locked.

Reproduction

$ openclaw --version
OpenClaw 2026.4.29 (a448042)

$ openclaw agent --agent main --model github-copilot/claude-haiku-4.5 --message "ping"
EMBEDDED FALLBACK: Gateway agent failed; running embedded agent: GatewayClientRequestError: FailoverError: LLM request failed: provider rejected the request schema or tool payload.

gateway.err.log:

[agent/embedded] embedded run failover decision: stage=assistant decision=fallback_model reason=format from=github-copilot/claude-haiku-4.5 rawError=400 tools.0.custom.eager_input_streaming: Extra inputs are not permitted
[model-fallback/decision] candidate=github-copilot/claude-haiku-4.5 reason=format next=... detail=400 tools.0.custom.eager_input_streaming: Extra inputs are not permitted

70+ such 400s in my logs over a 7-day window before I traced the cause.

Root cause — why #72183's auto-close was wrong

The Codex review on #72183 checked OpenClaw's internal Anthropic transport (src/agents/anthropic-transport-stream.ts → convertAnthropicTools) and correctly concluded that path emits only {name, description, input_schema}. The verdict was "already fixed."

But Copilot requests don't take that path. They go through the bundled @mariozechner/pi-ai library which OpenClaw delegates to:

// node_modules/@mariozechner/pi-ai/dist/providers/anthropic.js
function getAnthropicCompat(model) {
    return {
        supportsEagerToolInputStreaming: model.compat?.supportsEagerToolInputStreaming ?? true,
        supportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true,
    };
}

function convertTools(tools, isOAuthToken, supportsEagerToolInputStreaming, cacheControl) {
    return tools.map((tool, index) => {
        return {
            name: ...,
            description: tool.description,
            ...(supportsEagerToolInputStreaming ? { eager_input_streaming: true } : {}),
            input_schema: { ... },
        };
    });
}

pi-ai defaults supportsEagerToolInputStreaming to true and reads model.compat.supportsEagerToolInputStreaming. The github-copilot plugin's model definitions don't set compat, so pi-ai injects the field and Copilot's proxy returns 400 tools.0.custom.eager_input_streaming: Extra inputs are not permitted.

This is documented behavior on pi-ai's side: see pi-coding-agent docs/models.md:

By default pi sends per-tool eager_input_streaming: true. If a proxy or Anthropic-compatible backend rejects that field, set supportsEagerToolInputStreaming to false.

The github-copilot plugin needs to set this flag on every Copilot model definition. It currently does not.

Reproducible local fix

Patching dist/extensions/github-copilot/models-defaults.js:

 function buildCopilotModelDefinition(modelId) {
     const id = modelId.trim();
     if (!id) throw new Error(\"Model id required\");
     return {
         id,
         name: id,
         api: resolveCopilotTransportApi(id),
         reasoning: false,
         input: [\"text\", \"image\"],
         cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
         contextWindow: DEFAULT_CONTEXT_WINDOW,
-        maxTokens: DEFAULT_MAX_TOKENS
+        maxTokens: DEFAULT_MAX_TOKENS,
+        compat: { supportsEagerToolInputStreaming: false }
     };
 }

After this patch + openclaw gateway restart, Copilot tool-using requests succeed cleanly. Verified end-to-end on v2026.4.29.

Suggested upstream fix

Two paths build Copilot model objects and both need the flag:

  1. extensions/github-copilot/models-defaults.jsbuildCopilotModelDefinition (the patch above).
  2. models-DL4wItdF.jsresolveCopilotForwardCompatModel (builds an inline model definition for unregistered Copilot model IDs — also missing compat).

Both should set compat: { supportsEagerToolInputStreaming: false } on Anthropic-API models (i.e. anything where resolveCopilotTransportApi returns \"anthropic-messages\"). Non-Anthropic models can keep the default; the flag is ignored on other transports.

Severity

This is a silent money-burn bug. Copilot requests fail → fallback chain triggers → if any paid provider (OpenRouter Anthropic, etc.) is in the chain, it bills the user. A user reported ~$5/day in OpenRouter costs they couldn't explain until they audited the logs. The default OpenClaw fallback chain at install time may include OpenRouter Anthropic depending on onboarding choices.

Note re: #72183 closure process

The Codex review's "release evidence" cited an empty git diff v2026.4.24..HEAD -- <files> as proof of fix. That's tautological — an empty diff is also what you'd see if the bug were equally present in both revisions, which is what's actually happening here. Worth tightening the auto-close criteria to require positive evidence (a passing reproduction or a referenced fix commit) rather than absence-of-change.

Happy to PR the one-line fix if helpful — let me know which reviewer to ping.

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleMarked as stale due to inactivity

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions