You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug] gateway: message level output_config is stripped when the request carries the per-turn-control beta #8711
When a /v1/messages request carries anthropic-beta: per-turn-control-2026-07-01, the gateway removes output_config from the messages that have one. The client's mid session effort change never reaches Anthropic.
The check is in stripAnthropicMessageOutputConfigUnlessBeta in backend/internal/service/gateway_request.go:
It returns the body untouched only when the header contains claude.BetaMidConversationOutputConfig, which is mid-conversation-output-config-2026-07-01, defined at
. There is no constant for per-turn-control-2026-07-01, so with only that beta the field is stripped, and a system message with an empty content is dropped completely.
To reproduce, send this to /v1/messages and look at the body the gateway forwards:
anthropic-beta: per-turn-control-2026-07-01
{
"model": "claude-opus-5-5",
"max_tokens": 256,
"messages": [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": "Hi, how can I help?"},
{"role": "system", "content": [], "output_config": {"effort": "low"}},
{"role": "user", "content": "Summarize that in one sentence."}
]
}
The forwarded body has no output_config on the third message, and the whole message is gone because its content is empty.
Expected: the body is forwarded unchanged, the same as with mid-conversation-output-config-2026-07-01. Claude Code sends per-turn-control-2026-07-01 in its anthropic-beta list, for example in the header capture described in #8394, and a message level output_config on a system message is the shape Anthropic documents for changing effort partway through a conversation: https://platform.claude.com/docs/en/build-with-claude/effort-per-message
Tested on the real upstream through gateway that doesn't strip it with OAuth account not passthrough and claude-opus-5, sent on CC with anthropic-beta: claude-code-20250219,per-turn-control-2026-07-01 and a system message carrying output_configgot 200, so upstream accepts the field under that beta
Row 3 in your table is the mimic path for clients that aren't Claude Code. Real Claude Code on OAuth isn't mimicked, so main drops the message there too
Activity
r266-tech commentedon Nov 12, 2026
核对了当前官方 per-message effort 文档:beta header、请求示例和可用性表列出的仍是
mid-conversation-output-config-2026-07-01。该页没有把per-turn-control-2026-07-01列为这个参数的别名。我用与
main@530c5e3a4相同的请求构造代码做了 9 个独立本地对照,使用本 issue 的四条消息和顶层effort: high:per-turn-control-2026-07-01mid-conversation-output-config-2026-07-01,或同时带两者per-turn-control-2026-07-01这确认了 API Key 路径上的本地差异,也给出了按当前文档可用的最小对照;尚未验证真实上游是否接受
per-turn-control单独授权这个字段。若已有该别名成功保留消息级 effort 的上游响应,请补充脱敏后的账号类型、是否透传、最终 beta header 及 HTTP 状态/错误,便于区分公开协议、账号专属行为或需要支持的别名。无需附密钥或完整会话。验证使用 Go 1.27.3/macOS arm64,未调用真实 Anthropic。AI 辅助源码核对和合成请求验证。
Anankke commentedon Nov 12, 2026
Tested on the real upstream through gateway that doesn't strip it with OAuth account not passthrough and claude-opus-5, sent on CC with
anthropic-beta: claude-code-20250219,per-turn-control-2026-07-01and a system message carryingoutput_configgot 200, so upstream accepts the field under that betaRow 3 in your table is the mimic path for clients that aren't Claude Code. Real Claude Code on OAuth isn't mimicked, so main drops the message there too
r266-tech commentedon Nov 12, 2026
你说得对:我原表格的 OAuth 行只验证了非 Claude Code 客户端的 mimic 分支,应明确标注为 “OAuth mimic”。它不能概括真实 Claude Code 的 OAuth 请求;此前的结论漏掉了这条路径。
已在
main@530c5e3a4的真实Forward入口补充对照,用 Claude Code UA 和合法metadata.user_id触发非 mimic 路径。结果确认:仅带claude-code-20250219,per-turn-control-2026-07-01时,真实 Claude Code OAuth、API Key 普通和 API Key 透传三条路径都会删除该控制消息;mimic 因最终 header 自带旧 beta 而保留。顶层 effort 均不受影响。修复已提交为 https://github.com/Wei-Shaw/sub2api/pull/8742(`bd89d3d94`):按最终 header 中任一相关 beta 保留消息级
output_config;无相关 beta 或两者均被策略过滤时保持原行为。39 项相关 test/subtest、完整 unit(26,895 通过 / 41 跳过)、integration(16,143 通过 / 16 跳过)及 lint 均已通过。PR 中保留并披露了首轮计费内存断言失败、main 对照复现和后续复验结果。你的 OAuth + Claude Code +
claude-opus-5HTTP 200 是这里的真实上游接受证据;本账号完成的是本地合成请求验证,没有请求真实 Anthropic,也未验证模型实际 effort 效果或 API Key 的真实上游行为。当前官方文档仍列旧 beta,不能把上述实测写成官方文档已声明两者等价。AI 辅助实现、验证与回复。