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:
extensions/github-copilot/models-defaults.js → buildCopilotModelDefinition (the patch above).
models-DL4wItdF.js → resolveCopilotForwardCompatModel (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.
Bug
#72183was auto-closed on 2026-04-26 with a verdict that v2026.4.24 fixed theeager_input_streamingschema rejection ongithub-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
gateway.err.log: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-ailibrary which OpenClaw delegates to:pi-ai defaults
supportsEagerToolInputStreamingtotrueand readsmodel.compat.supportsEagerToolInputStreaming. The github-copilot plugin's model definitions don't setcompat, so pi-ai injects the field and Copilot's proxy returns400 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:
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:
extensions/github-copilot/models-defaults.js→buildCopilotModelDefinition(the patch above).models-DL4wItdF.js→resolveCopilotForwardCompatModel(builds an inline model definition for unregistered Copilot model IDs — also missingcompat).Both should set
compat: { supportsEagerToolInputStreaming: false }on Anthropic-API models (i.e. anything whereresolveCopilotTransportApireturns\"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.