本文介绍如何为 Claude Code Router(下文简称 CCR)编写自定义转换器,以兼容某些对 OpenAI 兼容 API 有细微差别的大模型提供商、私有或企业部署模型服务。

**背景:**CCR 可以将 OpenAI、OpenRouter、DeepSeek、Gemini 等供应商的 OpenAI 兼容接口适配为 Claude Code 所需的 API,从而实现多模型支持与 API 中转。CCR 自带多种常见平台的转换器及一键配置模板,但对于非主流或企业自部署的服务,仍可能遇到请求/响应格式不一致的问题,此时可以通过自定义转换器解决兼容性。

本文示例来自我在公司内部私有部署的 OpenAI 兼容服务上遇到的问题:**目标服务要求 messages[].content 必须为字符串,而 CCR 在转发时将 content 作为数组(结构化块)发送,导致服务返回参数校验错误。**

标准的 OpenAI 风格请求体(/v1/chat/completions)通常为:

{
  "model": "gpt-4.1",
  "messages": [
    { "role": "system", "content": "你是一个有帮助的助手。" },
    { "role": "user", "content": "你好!" }
  ]
}


但 Claude Code 的所有请求参数中,content 字段表示为一组结构化块(数组),示例:

{
  "messages": [
    {
      "role": "system",
      "content": [
        { "type": "text", "text": "You are Claude Code...", "cache_control": { "type": "ephemeral" } },
        { "type": "text", "text": "You are a file search specialist...", "cache_control": { "type": "ephemeral" } }
      ]
    },
    {
      "role": "user",
      "content": [ { "type": "text", "text": "Warmup", "cache_control": { "type": "ephemeral" } } ]
    }
  ],
  "model": "internal-qwen3-235b-xxx",
  "max_tokens": 50000,
  "temperature": 1,
  "stream": false
}


目标服务在校验时会报错,原因是它只接受字符串类型的 content

为了解决这个不兼容问题,我们可以编写一个简单的转换器,把数组形式的 content 序列化为字符串再发给后端。CCR 自定义转换器是解决不同供应商/自研服务间细微接口差异的有效手段。你可以在请求进入(transformRequestIn)或响应返回(transformResponseOut)阶段进行调整。

**示例转换器(node.js):**

// ~/.claude-code-router/gf-transformer.js
class GFTransformer {
  name = 'gf';
  endPoint = '/v1/chat/completions';

  // transformRequestIn 用于在请求发送到目标 provider 之前修改请求体
  async transformRequestIn(request, provider) {
    if (Array.isArray(request.messages)) {
      request.messages = request.messages.map(message => {
        if (message.content && typeof message.content !== "string") {
          message.content = JSON.stringify(message.content)
        }
        return message;
      });
    }
    return request;
  }
}

module.exports = GFTransformer;


**如何使用该自定义转换器:**

1). 在本机创建转换器文件(以 Unix 风格的用户目录为例):

- ~/.claude-code-router/gf-transformer.js,内容为上面的转换器代码。

2). 在 CCR 配置中注册转换器并关联到 Provider(示例 ~/.claude-code-router/config.json):

{
  "transformers": [
    {
      "name": "gf",
      "path": "~/.claude-code-router/gf-transformer.js",
      "options": { "project": "gf-dev" }
    }
  ],
  "Providers": [
    {
      "name": "gf-dev",
      "transformer": ["gf"]
    }
  ]
}


注意:上面 Providers 配置示例中,将 transformer 配置为一个字符串数组(列出要启用的转换器名称)。具体格式请以你所使用 CCR 版本的配置文档为准,某些版本可能使用不同的字段名或结构。

3). 保存配置后,重启 CCR:

ccr restart


4). 使用 ccr code 发起请求,即可正常使用上私有模型了。也可以执行 ccr ui 命令,从浏览器打开 CCR web ui 界面,即可以在模型配置、自定义转换器等处看到我们自定义的转换器信息。

**总结与建议**

开启 CCR 的日志功能,并设置为DEBUG级别,可以在 logs 目录下看到 Claude Code 所有的请求与响应详情。

Claude Code 请求体内容还是比较大的,请求与响应对 token 消耗得都非常多,所以对模型能力要求还是比较高的,模型支持上下文长最大长度至少需要在 128k 以上,普通小模型基本无法实用。

**扩展参考:**

- Claude Code Router
- Claude Code 国内安装配置及使用技巧参考指南
- CCR(Cluade Code Router) 自定义路由实现模型自动选择的方法