Claude Code 升级后 DeepSeek API 报错 messages[x].role: unknown variant system 终极解决方案

问题现象

使用 Claude Code(VSCode/Cursor 插件或 CLI)配合 DeepSeek API 时,报错:

text 复制代码
API Error: 400 Failed to deserialize the JSON body into the target type: 
messages[1].role: unknown variant system, expected user or assistant

claude --print 模式正常,但交互模式(IDE 插件)必现。

根本原因

Claude Code v2.1.153+ 在交互模式下,会将某些上下文指令(如 CLAUDE.md 内容、skills 注入等)以 role: "system" 的形式直接放入 messages 数组,而非 Anthropic 规范要求的顶层 system 参数。DeepSeek 的 /anthropic 兼容端点对此做了严格校验,直接拒绝。

本质上是 DeepSeek 的 Anthropic 兼容层对消息格式的容错不如官方 API。

环境变量方案(治标)

在 ~/.claude/settings.json 的 env 中添加:

json 复制代码
{
  "env": {
    "ANTHROPIC_MODEL": "deepseek-v4-pro",
    "CLAUDE_CODE_DISABLE_NON_ESSENTIAL_BETAS": "1",
    "CLAUDE_CODE_BETAS": "",
    "DISABLE_AUTOUPDATER": "1"
  }
}

此方案通过禁用 Beta 功能来减少不兼容性,但实测不一定对所有版本/场景生效。

本地代理方案(治本,推荐)

写一个 Python 代理,拦截 Claude Code 发出的请求,自动把 messages 数组中的 system 角色消息移到顶层 system 参数,再转发给 DeepSeek。

创建代理脚本 claude_proxy.py

python 复制代码
import http.server, json, urllib.request

TARGET = "https://api.deepseek.com/anthropic"
API_KEY = "你的DeepSeek-API-Key"
PORT = 9877

class Proxy(http.server.BaseHTTPRequestHandler):
    def do_POST(self):
        length = int(self.headers.get("Content-Length", 0))
        body = self.rfile.read(length)
        try:
            parsed = json.loads(body)
            msgs = parsed.get("messages", [])
            extra, cleaned = [], []
            for m in msgs:
                if m.get("role") == "system":
                    c = m.get("content", "")
                    extra.append(c if isinstance(c, str)
                        else " ".join(x.get("text","") for x in c
                            if x.get("type") == "text"))
                else:
                    cleaned.append(m)
            if extra:
                existing = parsed.get("system", "")
                if isinstance(existing, list):
                    existing = " ".join(
                        x.get("text","") for x in existing
                        if x.get("type") == "text")
                parsed["system"] = (existing + "\n\n" if existing else "") + "\n\n".join(extra)
                parsed["messages"] = cleaned
                body = json.dumps(parsed).encode()
        except:
            pass
        url = TARGET + self.path
        req = urllib.request.Request(url, data=body, method="POST")
        for k, v in self.headers.items():
            if k.lower() not in ("host", "content-length"):
                req.add_header(k, v)
        try:
            resp = urllib.request.urlopen(req, timeout=60)
            rbody = resp.read()
            self.send_response(resp.status)
            for k, v in resp.headers.items():
                if k.lower() not in ("transfer-encoding", "content-length", "connection"):
                    self.send_header(k, v)
            self.end_headers()
            self.wfile.write(rbody)
        except Exception as e:
            self.send_response(502)
            self.end_headers()
            self.wfile.write(str(e).encode())

    def log_message(self, f, *a):
        pass

http.server.HTTPServer(("127.0.0.1", PORT), Proxy).serve_forever()

启动代理

bash 复制代码
python claude_proxy.py

修改配置

修改 ~/.claude/settings.json,将 ANTHROPIC_BASE_URL 指向代理:

json 复制代码
{
  "env": {
    "ANTHROPIC_BASE_URL": "http://localhost:9877",
    "ANTHROPIC_MODEL": "deepseek-v4-pro"
  }
}

重启 Claude Code 即可

开机自启(可选)

代理默认只在当前会话运行,重启电脑后会停。设为开机自启:

Win+R → 输入 shell:startup → 回车,在该文件夹新建 claude_proxy.bat:

batch 复制代码
@start /min python "文件路径\claude_proxy.py"

之后每次开机代理都会自动在后台运行,无需手动启动。

如果还不行:例如你装了别的智能体

在 Cursor/VSCode 的 settings.json 中加上:

batch 复制代码
{
  "claudeCode.environmentVariables": [
    { "name": "CLAUDE_CODE_DISABLE_NON_ESSENTIAL_BETAS", "value": "1" },
    { "name": "CLAUDE_CODE_BETAS", "value": "" },
    { "name": "DISABLE_AUTOUPDATER", "value": "1" }
  ]
}

CLAUDE_CODE_DISABLE_NON_ESSENTIAL_BETAS=1 禁掉了 Claude Code 新版本自动启用的 Beta 功能(如 interleaved-thinking、prompt-caching-scope),这些 Beta 会导致请求格式与 DeepSeek 的 Anthropic 兼容代理不兼容。

注意事项

  • 重启电脑后代理会自动停止,需重新启动 python claude_proxy.py
  • 如果 DeepSeek 后续修复了兼容性问题,可去掉代理恢复直连
  • 建议同时设置 DISABLE_AUTOUPDATER=1 防止 Claude Code 自动升级引入新的不兼容

参考

相关推荐
言乐610 小时前
Python语音检索
开发语言·python·django·virtualenv·pygame
泡茶喝茶写代码10 小时前
A股量化数据工程:从 REST 接口到策略信号(第 1 篇):指数列表与实时行情接入
java·python·股票数据api·股票数据·股票数据api接口·股票api数据接口·股票量化数据接口
happylifetree10 小时前
Python34-35:核心语法-流程控制语句-循环-综合案例
python
吃饱了得干活11 小时前
Agent 的记忆与工具:从上下文窗口到 MCP
python·agent·mcp
燐妤11 小时前
LangGraph-复习总览
python·ai·面试·agent·学习方法·langgraph
尹人入圣11 小时前
市面上IP驱动产业新场景新工具
运维·网络·python·tcp/ip
打工仔折腾 AI12 小时前
从BPE到SentencePiece:Transformer分词原理与Python实战对比
android·人工智能·python·深度学习·langchain·transformer·ai agent 实战
骑着蜗牛撵大象32712 小时前
Qt 事件机制详解:从 QEvent 派生类到事件过滤器的全景指南
前端·python
流形填表12 小时前
题库迁移实战:Excel中间格式与列映射
python·excel
东方芷兰12 小时前
Agent 技术摘要 06 —— Harness、原生视觉、Jev、mmproj、dsh
人工智能·笔记·python·ai·langchain·ai编程