> https://router.one/zh/blog/openai-agents-sdk-vs-claude-agent-sdk-vs-pydantic-ai 的 Markdown 镜像，供 AI 助手与爬虫使用。Router One 是 OpenAI 兼容的统一 LLM API 网关。
> 发布：2026-09-11 · 作者：Router One Team

# OpenAI Agents SDK、Claude Agent SDK、Pydantic AI、CrewAI 横评：一把网关 Key 全接入

_五个 Agent SDK 接入 Router One 对照：各自用哪个类或环境变量指向网关、走哪种协议、能调哪些模型系列，一把 Key、每次调用一条 Trace。_

五个 Agent 框架，同一个问题：把模型调用改走 Router One 之后，到底变了什么？框架本身没有变——**OpenAI Agents SDK** 自带处理 handoff、guardrail 和 session 的循环；**Claude Agent SDK** 把 Claude Code 的引擎和权限机制嵌进你的应用；**Pydantic AI** 提供类型化输出；**CrewAI** 运行角色化的 crew；**LangChain** 在 LangGraph 运行时之上搭 Agent。变的是底下那次请求：一把 `sk-` Key，[/models](https://router.one/zh/models) 里的精确模型 id，以及每次模型请求在 Dashboard → Logs 里的一条 Trace——模型、tokens、花费、延迟、状态和 request_id。网关负责请求，循环仍归框架。

一句话结论。**OpenAI Agents SDK**：在 Router One client 上显式构造 Chat Completions 模型，关掉 tracing。**Claude Agent SDK**：Claude Code 的两个环境变量、一个精确的 Claude 系列 id，每一轮就是一条 `/v1/messages` Trace。**Pydantic AI**：`OpenAIChatModel` 加 `OpenAIProvider`，五者中接入面最小。**CrewAI**：`custom_openai=True` 加 `openai/` 前缀规则。**LangChain 与 LangGraph**：`ChatOpenAI` 配 `use_responses_api=False`，LangGraph 不改变请求本身。

## 对照表

| SDK | 语言 | 怎样指向网关 | 实际协议 | 能到达的目录系列 | 留在 SDK 侧的部分 |
| --- | --- | --- | --- | --- | --- |
| OpenAI Agents SDK | Python；另有 TypeScript 版 | `AsyncOpenAI(base_url=…, api_key=…)` 放进 `OpenAIChatCompletionsModel`；`set_tracing_disabled(True)` | Chat Completions（直接传模型名则默认走 Responses） | 全部聊天模型；Responses 原生服务 GPT 系列与 DeepSeek id | 函数工具、handoff、guardrail、session、tracing |
| Claude Agent SDK | Python、TypeScript | `ClaudeAgentOptions(env={...})` 传入 `ANTHROPIC_BASE_URL` 与 `ANTHROPIC_AUTH_TOKEN`，或在 shell 里导出 | Anthropic Messages；引擎自己拼 `/v1/messages` | 当前上架的 Claude 系列 id | 工具执行、权限、hooks、session、subagent |
| Pydantic AI | Python | `OpenAIChatModel(id, provider=OpenAIProvider(base_url=…, api_key=…))` | Chat Completions（`openai:` 简写意味着 Responses） | 全部聊天模型 | Agent 循环、校验、工具、消息历史 |
| CrewAI | Python | `LLM(model="openai/" + id, custom_openai=True, base_url=…, api_key=…)`，或 `MODEL`、`OPENAI_API_BASE`、`OPENAI_API_KEY` 环境变量 | Chat Completions（`api="responses"` 可切换） | 全部聊天模型 | Agent 循环、任务顺序、委派、工具、记忆 |
| LangChain / LangGraph | Python；JS/TS 用 `useResponsesApi: false` | `ChatOpenAI(base_url=…, api_key=…, model=…, use_responses_api=False)` | Chat Completions（用到 Responses 专属功能时切到 Responses） | 全部聊天模型 | 图、Agent 循环、工具、状态与持久化 |

五者中有四个说的是 Chat Completions，而 `/v1/chat/completions` 服务目录里的所有聊天模型，所以同一个 `anthropic/claude-sonnet-5` 或 `openai/gpt-5.5` id 在下面每份配置里都能用；Claude Agent SDK 的引擎说 Anthropic Messages，只能到达 Claude 系列 id。最后一列是边界——里面没有一项跑在网关上。

## OpenAI Agents SDK：显式的 Chat Completions 模型，关掉 tracing

SDK 通过默认 provider 在 Responses API 上解析字符串模型名，并且用与模型调用相同的那把 Key 把 trace 上传到 OpenAI 服务器。指南绕开了这两个默认值：带 Router One base URL 和 Key 的 `AsyncOpenAI` client，包进 `OpenAIChatCompletionsModel`，于是每次请求都是 `POST /v1/chat/completions`，任何聊天模型 id 都能用；再加上 `set_tracing_disabled(True)`，因为 Router One 的 Key 顶替不了 `platform.openai.com` 的 Key。

```python
import os
from openai import AsyncOpenAI
from agents import Agent, OpenAIChatCompletionsModel, Runner, set_tracing_disabled

set_tracing_disabled(True)
client = AsyncOpenAI(
    base_url="https://api.router.one/v1",
    api_key=os.environ["ROUTER_ONE_API_KEY"],
)
model = OpenAIChatCompletionsModel(
    model=os.environ["ROUTER_ONE_MODEL_ID"],
    openai_client=client,
)
```

文件剩下的部分是 `Agent(..., model=model)` 和 `Runner.run_sync(agent, prompt, max_turns=3)`。只有当你的 Agent 用到的每个 id 在模型页都列出 `/v1/responses`，并且需要托管工具或 `previous_response_id` 时，才保留 Responses 默认；把 Claude、Gemini 或 Grok 的 id 发到那里，会在调用任何模型之前收到 HTTP 400 `model '<id>' must be called via …`——这个端点接受什么见 [Responses API 页](https://router.one/zh/codex-responses-api)。

**坑在这里。** `OPENAI_AGENTS_DISABLE_TRACING=1` 也能关掉 tracing；仍想用 OpenAI 的 Traces 面板，就用 `set_tracing_export_api_key(...)` 单独给导出器一把 Key，并在全局注册 client 时传 `use_for_tracing=False`。指南：[OpenAI Agents SDK 接入 Router One](https://router.one/zh/integrations/openai-agents-sdk)。

## Claude Agent SDK：两个变量、一个精确 Claude id、每轮一条 Trace

SDK 拉起随包附带的 Claude Code 引擎，工具在你的机器上执行，每一轮模型调用都是一次 Anthropic Messages 请求。把它指向 Router One 和把 Claude Code 指向 Router One 是同一件事：`ANTHROPIC_BASE_URL` 填不带 `/v1` 的主机根地址 `https://api.router.one`，因为引擎会自己拼上 `/v1/messages`；`ANTHROPIC_AUTH_TOKEN` 以 Bearer 头携带你的 Key；`ANTHROPIC_API_KEY` 不需要设置。两个变量通过 `env` 传入或在 shell 里导出都行，因为 Python SDK 会把 `env` 合并到继承的环境之上。

```python
options = ClaudeAgentOptions(
    model=os.environ["ROUTER_ONE_MODEL_ID"],
    env={
        "ANTHROPIC_BASE_URL": "https://api.router.one",
        "ANTHROPIC_AUTH_TOKEN": os.environ["ROUTER_ONE_API_KEY"],
    },
    max_turns=3,
)
```

之后 `query(prompt=..., options=options)` 逐条产出引擎的消息。`model` 必须是 [/models](https://router.one/zh/models) 里详情页列出 `POST /v1/messages` 的精确 id，不能是 `sonnet` 这类别名——别名在客户端解析成内置默认 id。这个端点也列出了 DeepSeek id，但 Claude Code 的网关文档写明 Anthropic 不支持把它路由到非 Claude 模型，所以 SDK 请保持使用 Claude 系列 id。

**坑在这里。** TypeScript 里 `options.env` 会整个替换环境，要把 `process.env` 展开进去。Claude Code 设置文件里的 `env` 块会同时覆盖 shell 和 `options.env`——删掉那里旧的 `ANTHROPIC_BASE_URL`，或传 `setting_sources=[]`。残留的 `ANTHROPIC_API_KEY` 会作为第二个请求头一起发出，请 unset 掉。`max_budget_usd` 比较的是 SDK 内置价格表算出的客户端估算，官方文档明确说不能据此做财务决策；真正止损的是 Key 上的 `maxSpend`。指南：[Claude Agent SDK 接入 Router One](https://router.one/zh/integrations/claude-agent-sdk)；终端里同样两个变量的用法见 [Claude Code 国内接入](https://router.one/zh/claude-code-china)。

## Pydantic AI：先 OpenAIChatModel，再选类型化输出模式

按当前 Pydantic AI 文档，`Agent('openai:...')` 里不带类名的 `openai:` 前缀对应的是 `OpenAIResponsesModel`，所以指南显式构造模型：`OpenAIChatModel` 选定 `/v1/chat/completions`，`OpenAIProvider` 接收带 `/v1` 的 base URL 和 Key，目录 id 原样传入，自带的前缀也保留。

```python
from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.openai import OpenAIProvider

model = OpenAIChatModel(
    os.environ["ROUTER_ONE_MODEL_ID"],
    provider=OpenAIProvider(
        base_url="https://api.router.one/v1",
        api_key=os.environ["ROUTER_ONE_API_KEY"],
    ),
)
agent = Agent(model, output_type=str)
```

`output_type=str` 让第一次请求不依赖工具和 JSON schema 输出；`agent.run_sync(prompt, usage_limits=UsageLimits(request_limit=3))` 限制 Pydantic AI 为本次运行记录的模型请求次数。

**坑在这里。** 类型化输出是模型能力开始起作用的地方：把 `BaseModel` 传给 `output_type`（或用 `ToolOutput`）走的是输出工具，模型必须支持工具调用；`NativeOutput` 用模型原生的 JSON schema 响应格式；`PromptedOutput` 把 schema 写进提示、事后校验。校验重试会产生额外的模型请求，每次各有一条 Trace，所以类型化输出失败时先退回 `output_type=str`。指南：[Pydantic AI 接入 Router One](https://router.one/zh/integrations/pydantic-ai)；另见[结构化输出页](https://router.one/zh/llm-structured-outputs)。

## CrewAI：custom_openai=True 与 openai/ 前缀规则

CrewAI 从每个模型字符串里读 provider 前缀并据此选客户端：`anthropic/` 或 `google/` 开头的 id 会走 CrewAI 自带的对应厂商路径，要求那家的 API 和 Key。`custom_openai=True` 覆盖这个选择，让任何 id 都固定走 OpenAI SDK 的 Chat Completions 路径；此模式下 CrewAI 只去掉最前面的一个 `openai/` 段，其余原样发送。

```python
from crewai import Agent, Crew, LLM, Task

llm = LLM(
    model="openai/" + os.environ["ROUTER_ONE_MODEL_ID"],
    custom_openai=True,
    base_url="https://api.router.one/v1",
    api_key=os.environ["ROUTER_ONE_API_KEY"],
)
```

把 `llm=llm` 传给每个 `Agent`，加上 `Task` 和 `Crew`，`crew.kickoff()` 返回的结果里 `.raw` 就是文本。因为会被吃掉一层前缀，GPT 系列 id 要写两遍——`openai/openai/gpt-5.5`——否则发出去的是不带前缀的 `gpt-5.5`；Logs 里 model 一列应显示完整的目录 id。脚手架生成的项目也可以改用 `MODEL`、`OPENAI_API_BASE` 和 `OPENAI_API_KEY`，`MODEL` 同样写成 `openai/` 加目录 id。

**坑在这里。** `agents.yaml` 里的纯字符串或 `Agent(llm="...")` 在构建时拿不到 base URL，会被交给 CrewAI 的 LiteLLM 兜底路径，而它默认没有安装——把模型放进 `MODEL` 或 `LLM` 对象。`api="responses"` 会让同一个对象改走 `/v1/responses`，所以 `api` 保持默认值。`crew.usage_metrics` 是 token 统计，不是账单；`CREWAI_TRACING_ENABLED` 是 CrewAI 的 tracing，不是网关的。指南：[CrewAI 接入 Router One](https://router.one/zh/integrations/crewai)。

## LangChain 与 LangGraph：ChatOpenAI 配 use_responses_api=False

`ChatOpenAI` 直接接收 base URL 和 Key，指南用 `use_responses_api=False` 把这条固定在 Chat Completions 上；JS/TS 的对应选项是 `useResponsesApi: false`。官方集成页写明：用到 Responses 专属功能或设置 `use_responses_api=True` 时，`ChatOpenAI` 会改走 Responses API；显式传入的 `base_url` 优先于 `OPENAI_API_BASE` 和 `OPENAI_BASE_URL` 两个环境变量——所以两者都写进代码。

```python
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    base_url="https://api.router.one/v1",
    api_key="sk-your-router-one-key",
    model="<model-id-from-/models>",
    use_responses_api=False,
)

print(llm.invoke("Hello!").content)
```

LangGraph 不改变这一点。LangChain 文档把 LangChain 定义为 Agent 框架，把 LangGraph 定义为底下的运行时——持久执行、流式、人在回路、持久化——而 `create_agent` 接受已初始化的模型实例，所以上面这个 `llm` 就是 Agent 或手写图节点发往 Router One 的东西。checkpoint 和状态留在你的进程里。

**坑在这里。** 原生 Anthropic 功能或非标准的供应商字段需要匹配的集成和端点；启用内置工具或会话状态功能可能让 LangChain 切到 Responses——启用前重新核对模型页。指南：[LangChain 接入 Router One](https://router.one/zh/integrations/langchain)；端点细节见[流式输出](https://router.one/zh/llm-streaming)和[工具调用](https://router.one/zh/llm-tool-calling)两页。

## 网关做什么、不做什么

Router One 负责模型请求。每一次请求它都在 Dashboard → Logs 记一条 Trace——模型、输入输出 tokens、花费、延迟、HTTP 状态、request_id——并执行 Key 上的上限：`maxSpend`，以及对付失控循环的 `rateLimit` 和 `tokenLimitTpm`。id 发到不服务它的端点，会在调用任何模型之前被 HTTP 400 拒绝；各端点接受和拒绝的清单见 [API 兼容性事实页](https://router.one/zh/facts/api-compatibility.md)。

它不执行工具、不保存 Agent 状态，也不替框架跑循环。函数工具、handoff、权限检查、session、subagent、checkpoint 和校验重试都跑在你的进程里；`/v1/responses` 上的托管工具字段会被接受并计量，但 Router One 自己不执行工具。网关也没有 embeddings 端点——这五者的 RAG pipeline 近亲 [Haystack 指南](https://router.one/zh/integrations/haystack)展示了边界落在哪里。账本记什么，见[成本追踪页](https://router.one/zh/llm-cost-tracking)。

## 给一次 Agent 运行定预算

上面每个框架都有循环上限，但没有一个是花费上限：OpenAI Agents SDK 的 `max_turns` 数模型调用次数（不传时为 10），Claude Agent SDK 的 `max_turns` 数工具调用往返轮数，Pydantic AI 的 `UsageLimits(request_limit=...)` 数它记录的请求次数。重试在这些上限之外，而每一次到达网关的尝试都是独立请求，各有自己的 Trace 和费用；`total_cost_usd`、`crew.usage_metrics` 这类客户端数字是估算或统计，不是你实际被扣的钱。

真正止损的上限在 Key 上：一个框架一把 Key，各设 `maxSpend`，失控的运行到顶即停、返回 402，钱包和其他 Key 不受影响。按 request_id 核账——按 Key、时间窗和精确模型过滤 Logs，把条数对上框架报告的轮数或步数，保留失败 Trace 的 request_id。被取消的流式请求既不会被悄悄扣费，也不会被悄悄记零：在 `POST /v1/chat/completions` 和 `POST /v1/responses` 上，客户端中途取消的请求记为 HTTP 499 `client_cancelled`，只按上游实际报告的用量计费；网关最多等 5 秒拿最终 usage，释放预留余额，不重试也不故障转移（见[定价事实页](https://router.one/zh/facts/pricing.md)）。

到 [router.one](https://router.one/zh) 为每个框架建一把 Key，各设上限，让 Trace 告诉你哪个循环值这笔账。

## 常见问题

**Claude 优先的团队该选哪个 SDK？**
想把 Claude Code 的引擎——文件和 shell 工具、权限模式、subagent——嵌进应用，就选 Claude Agent SDK：它说 Anthropic Messages，只用 Claude 系列 id。不需要那个引擎的话，另外四个都能在 /v1/chat/completions 上调用 Claude id，之后想试别的系列只是换 id，不是换框架。

**GPT 优先的团队该选哪个 SDK？**
OpenAI Agents SDK，真正要决定的是端点：它的 Responses 默认路径原生服务当前上架的 GPT 系列和 DeepSeek id，带托管工具和 previous_response_id；显式的 OpenAIChatCompletionsModel 则对所有聊天模型可用。SDK 自己也建议一个工作流只用一种模型形态。

**一把 Key 能同时接五个框架吗？**
能。本文每份配置接受的都是同一把 sk- Key，每次调用都落进同一个钱包。更好的做法是一个框架一把 Key：每把各带自己的 maxSpend，Dashboard → Logs 按 Key 过滤，哪个框架花了多少是事实而不是估算。

**Responses 和 Chat Completions 的区别重要吗？**
它决定哪些 id 能用、哪些功能存在。/v1/chat/completions 服务所有聊天模型；/v1/responses 原生服务 GPT 系列和 DeepSeek id，并承载 Responses 专属功能；/v1/messages 以 Anthropic 格式服务 Claude 系列和 DeepSeek id。配错了会在调用任何模型之前收到 HTTP 400 must be called via …——这时换 id 或换模型类，不要改 base URL。

## 相关页面

- 本页规范地址：https://router.one/zh/blog/openai-agents-sdk-vs-claude-agent-sdk-vs-pydantic-ai
- LLM API 网关与路由：https://router.one/zh/llm-api-gateway
- 全部博客文章：https://router.one/zh/blog
- 模型与每模型 token 价格：https://router.one/zh/models （markdown：https://router.one/zh/models.md ）
- 定价：https://router.one/zh/pricing
- API 文档（markdown）：https://router.one/zh/docs.md
- 公司事实（markdown）：https://router.one/zh/facts/company.md
