本篇导读
前十一篇已经把 Agents SDK 的运行主线拆开了:
这些机制最终都要落到一个核心动作上:
调用模型,拿到模型响应,再把模型响应归一化成 SDK 能处理的 items。
这就是模型适配层的职责。
本篇重点回答五个问题:
先给结论:Runner 不关心具体 Provider
Agents SDK 的核心 run loop 不直接依赖 OpenAI Responses、Chat Completions、LiteLLM 或 Any-LLM 的请求结构。
它依赖的是统一接口:
class Model(abc.ABC):
async def get_response(...) –> ModelResponse:
...
def stream_response(...) –> AsyncIterator[TResponseStreamEvent]:
...
也就是说,run loop 只需要:
真正知道“怎么调用某个后端”的,是 model adapter:
| OpenAIResponsesModel | 调用 OpenAI Responses API |
| OpenAIResponsesWSModel | 通过 WebSocket 调用 OpenAI Responses API |
| OpenAIChatCompletionsModel | 调用 Chat Completions API,并做格式转换 |
| LitellmModel | 通过 LiteLLM 调用第三方 provider |
| AnyLLMModel | 通过 any-llm 调用 Responses 或 Chat Completions 风格 provider |
因此,模型适配层的核心设计是:
Runner 只看 Model 抽象;
Provider 负责把名字解析成 Model;
Adapter 负责 provider-specific 请求、能力校验、错误和 usage 归一化。
第十二篇关注的源码入口
本篇主要涉及这些文件:
| src/agents/models/interface.py | Model、ModelProvider、ModelTracing 抽象 |
| src/agents/models/openai_provider.py | OpenAI 默认 provider |
| src/agents/models/multi_provider.py | 前缀路由 provider |
| src/agents/models/openai_responses.py | OpenAI Responses adapter |
| src/agents/models/openai_chatcompletions.py | Chat Completions adapter |
| src/agents/models/chatcmpl_converter.py | Responses items 与 Chat messages 转换 |
| src/agents/model_settings.py | ModelSettings 定义和合并逻辑 |
| src/agents/models/default_models.py | 默认模型和默认 settings |
| src/agents/run_internal/turn_preparation.py | run loop 解析模型和 settings |
| src/agents/run_internal/run_loop.py | 调用 model.get_response() / stream_response() |
| src/agents/run_internal/model_retry.py | runner-managed retry |
| src/agents/extensions/models/litellm_model.py | LiteLLM adapter |
| src/agents/extensions/models/any_llm_model.py | Any-LLM adapter |
| docs/models/index.md | 模型配置文档 |
| examples/model_providers | 第三方 provider 示例 |
建议阅读顺序:
ModelTracing:模型调用的 trace 开关
ModelTracing 是模型 adapter 接收的 tracing 配置:
class ModelTracing(enum.Enum):
DISABLED = 0
ENABLED = 1
ENABLED_WITHOUT_DATA = 2
def is_disabled(self) –> bool:
return self == ModelTracing.DISABLED
def include_data(self) –> bool:
return self == ModelTracing.ENABLED
它来自 RunConfig:
def get_model_tracing_impl(
tracing_disabled: bool,
trace_include_sensitive_data: bool,
) –> ModelTracing:
if tracing_disabled:
return ModelTracing.DISABLED
if trace_include_sensitive_data:
return ModelTracing.ENABLED
return ModelTracing.ENABLED_WITHOUT_DATA
含义很明确:
| tracing_disabled=True | 模型 span 禁用 |
| trace_include_sensitive_data=True | span 记录输入输出 |
| trace_include_sensitive_data=False | span 存在,但不记录输入输出 |
这就是第十一篇提到的敏感数据边界在模型层的落点。
Model 接口
Model 是所有模型 adapter 的公共接口:
class Model(abc.ABC):
async def get_response(
self,
system_instructions,
input,
model_settings,
tools,
output_schema,
handoffs,
tracing,
*,
previous_response_id,
conversation_id,
prompt,
) –> ModelResponse:
...
stream_response(…) 参数几乎相同,只是返回异步事件流:
def stream_response(...) –> AsyncIterator[TResponseStreamEvent]:
...
注意几个设计点:
这意味着 Chat Completions adapter 也会收到这些参数,但它不一定支持。
它的处理策略是:
ModelProvider 接口
ModelProvider 只做一件事:把模型名解析成 Model 实例。
class ModelProvider(abc.ABC):
@abc.abstractmethod
def get_model(self, model_name: str | None) –> Model:
...
async def aclose(self) –> None:
return None
这个接口的边界很重要:
例如 OpenAI WebSocket Responses 模型可能持有持久连接,所以 OpenAIProvider.aclose() 要关闭缓存的 websocket model。
普通 HTTP Responses model 不需要在 provider 里缓存实例。
Runner 如何选择模型
turn_preparation.py 中的 get_model(…) 是模型解析入口:
def get_model(agent: Agent[Any], run_config: RunConfig) –> Model:
if isinstance(run_config.model, Model):
return run_config.model
elif isinstance(run_config.model, str):
return run_config.model_provider.get_model(run_config.model)
elif isinstance(agent.model, Model):
return agent.model
return run_config.model_provider.get_model(agent.model)
优先级是:
| 1 | RunConfig.model 是具体 Model 实例 |
| 2 | RunConfig.model 是字符串,通过 RunConfig.model_provider 解析 |
| 3 | Agent.model 是具体 Model 实例 |
| 4 | Agent.model 是字符串或 None,通过 RunConfig.model_provider 解析 |
这说明 RunConfig.model 可以覆盖 Agent 自己的模型。
例如:
agent = Agent(name="Assistant", model="gpt-5.4-mini")
result = await Runner.run(
agent,
"你好",
run_config=RunConfig(model="gpt-5.6-sol"),
)
本次 run 实际使用 gpt-5.6-sol。
ModelSettings 如何解析
模型 settings 不是简单拿 Agent 上的配置。
源码中有一层默认 settings 对齐逻辑:
def get_model_settings(agent: Agent[Any], run_config: RunConfig) –> ModelSettings:
model_settings = agent.model_settings
if model_settings == _implicit_model_settings_for_agent(agent):
model_settings = _model_settings_for_resolved_name(agent, run_config)
return model_settings.resolve(run_config.model_settings)
含义是:
ModelSettings.resolve(…) 的覆盖规则是:
changes = {
field.name: getattr(override, field.name)
for field in fields(self)
if getattr(override, field.name) is not None
}
即非 None 字段覆盖。
两个特殊合并:
默认模型和默认 Settings
当前源码中默认模型来自:
OPENAI_DEFAULT_MODEL_ENV_VARIABLE_NAME = "OPENAI_DEFAULT_MODEL"
def get_default_model() –> str:
return os.getenv(OPENAI_DEFAULT_MODEL_ENV_VARIABLE_NAME, "gpt-5.4-mini").lower()
默认是:
gpt-5.4-mini
GPT-5 系列会有默认 ModelSettings:
_GPT_5_NONE_DEFAULT_MODEL_SETTINGS = ModelSettings(
reasoning=Reasoning(effort="none"),
verbosity="low",
)
例如 gpt-5.4-mini 默认是:
ModelSettings(
reasoning=Reasoning(effort="none"),
verbosity="low",
)
非 GPT-5 模型默认是空 ModelSettings()。
这解释了一个常见现象:
Agent(name="A")
不传模型时,并不是完全没有模型配置。默认模型如果是 GPT-5 系列,SDK 会给它补一组低延迟默认 settings。
OpenAIProvider:默认模型 Provider
OpenAIProvider 是默认 provider。
它的构造参数包括:
OpenAIProvider(
api_key=None,
base_url=None,
websocket_base_url=None,
openai_client=None,
organization=None,
project=None,
use_responses=None,
use_responses_websocket=None,
strict_feature_validation=False,
responses_websocket_options=None,
buffer_streamed_tool_calls=False,
)
几个关键点:
默认 client 解析:
self._client = _openai_shared.get_default_openai_client() or AsyncOpenAI(
api_key=self._stored_api_key or _openai_shared.get_default_openai_key(),
base_url=self._stored_base_url or os.getenv("OPENAI_BASE_URL"),
websocket_base_url=(
self._stored_websocket_base_url or os.getenv("OPENAI_WEBSOCKET_BASE_URL")
),
http_client=shared_http_client(),
)
这说明你可以用环境变量或代码全局配置 OpenAI client。
切换默认 OpenAI API
默认是 Responses:
set_default_openai_api("responses")
也可以切换为 Chat Completions:
from agents import set_default_openai_api
set_default_openai_api("chat_completions")
切换后,OpenAIProvider().get_model("…") 会返回不同 adapter:
| Responses HTTP | OpenAIResponsesModel |
| Responses WebSocket | OpenAIResponsesWSModel |
| Chat Completions | OpenAIChatCompletionsModel |
如果只想本次 run 使用 Chat Completions,更推荐直接传 provider:
provider = OpenAIProvider(use_responses=False)
result = await Runner.run(
agent,
"你好",
run_config=RunConfig(model_provider=provider),
)
这样不会影响进程内其他 run。
OpenAI Responses Model
OpenAIResponsesModel 的非流式调用是:
with response_span(disabled=tracing.is_disabled()) as span_response:
response = await self._fetch_response(...)
它最终调用:
response = await client.responses.create(**create_kwargs)
_build_response_create_kwargs(…) 负责构造 Responses 请求。
核心字段包括:
create_kwargs = {
"previous_response_id": ...,
"conversation": ...,
"instructions": ...,
"model": ...,
"input": list_input,
"include": include,
"tools": tools_param,
"prompt": ...,
"temperature": ...,
"top_p": ...,
"truncation": ...,
"max_output_tokens": ...,
"tool_choice": tool_choice_param,
"parallel_tool_calls": parallel_tool_calls,
"text": response_format,
"store": ...,
"prompt_cache_options": ...,
"reasoning": ...,
"metadata": ...,
"context_management": ...,
}
这条路径天然支持 Responses 的能力:
所以 OpenAI-only 应用默认推荐走 Responses。
Responses 工具转换
Responses adapter 会把 SDK tools 和 handoffs 转成 Responses 工具参数。
converted_tools = Converter.convert_tools(
tools,
handoffs,
model=effective_computer_tool_model,
tool_choice=model_settings.tool_choice,
)
Converter.convert_tool_choice(…) 支持的选择包括:
同时它会校验不合法组合。例如 deferred-loading function tools 没有 ToolSearchTool() 时,tool_choice="required" 可能会被拒绝。
这类校验放在 adapter 层是合理的:只有 adapter 知道目标 API 支持什么。
Responses 输出格式
结构化输出通过 text 字段传给 Responses API:
{
"format": {
"type": "json_schema",
"name": "final_output",
"schema": output_schema.json_schema(),
"strict": output_schema.is_strict_json_schema(),
}
}
如果没有结构化输出,返回 omit。
如果设置了 ModelSettings.verbosity,adapter 会把它放到 response format 相关结构中:
if model_settings.verbosity is not None:
if response_format is not omit:
response_format["verbosity"] = model_settings.verbosity
else:
response_format = {"verbosity": model_settings.verbosity}
这也是为什么 ModelSettings 不是简单照搬到 API 参数,而是需要 adapter 逐项解释。
OpenAI Chat Completions Model
Chat Completions adapter 的核心工作是转换。
SDK 内部输入是 Responses 风格 items,但 Chat Completions API 要的是 messages:
converted_messages = Converter.items_to_messages(
input,
model=self.model,
base_url=str(self._client.base_url),
strict_feature_validation=self._strict_feature_validation,
)
如果有 system instructions,会插到 messages 开头:
if system_instructions:
converted_messages.insert(
0,
{"content": system_instructions, "role": "system"},
)
最终调用:
ret = await self._get_client().chat.completions.create(**create_kwargs)
核心字段包括:
create_kwargs = {
"model": self.model,
"messages": converted_messages,
"tools": tools_param,
"temperature": ...,
"top_p": ...,
"frequency_penalty": ...,
"presence_penalty": ...,
"max_tokens": ...,
"tool_choice": tool_choice,
"response_format": response_format,
"parallel_tool_calls": parallel_tool_calls,
"stream": ...,
"stream_options": ...,
"store": ...,
"reasoning_effort": ...,
"verbosity": ...,
"top_logprobs": ...,
}
Chat Completions 路径会把返回的 ChatCompletionMessage 再转换回 Responses 风格 output items:
items = Converter.message_to_output_items(message)
这保证 run loop 后续仍然处理统一的 SDK item。
Chat Completions 不支持的能力
Chat Completions adapter 会收到接口中的 Responses-only 参数,例如:
默认兼容模式下,它会 warning 并忽略。
如果启用 strict validation:
provider = OpenAIProvider(
use_responses=False,
strict_feature_validation=True,
)
这些不匹配会变成 UserError。
开发期建议打开 strict validation,避免某些字段被静默降级。
生产期是否打开,要看你是否依赖兼容老 provider 的容忍行为。
Responses 与 Chat Completions 对比
| SDK 默认推荐 | 是 | 否 |
| OpenAI hosted tools | 支持更多 | 支持有限 |
| previous_response_id | 支持 | 不支持 |
| conversation_id | 支持 | 不支持 |
| prompt-managed request | 支持 | 不支持 |
| Responses tool search | 支持 | 不支持 |
| 输入格式 | Responses items | chat messages |
| SDK 转换成本 | 低 | 高 |
| 第三方 provider 兼容性 | 取决于 provider | 通常更好 |
| stream terminal 语义 | 原生 Responses events | 需要转换成 Responses 风格 events |
实用建议:
Streaming 终止语义
Responses stream 的终止事件不是简单的“流结束就成功”。
Responses adapter 会检查:
如果收到 failed 或 incomplete terminal,会转换成 ModelBehaviorError。
Chat Completions stream 则需要 ChatCmplStreamHandler 把 chat chunks 转换成 Responses 风格 events。
这也是 adapter 层的职责:不同 provider 的 stream 协议不同,但 run loop 只消费统一的 TResponseStreamEvent。
ModelResponse:统一返回值
无论底层是 Responses 还是 Chat Completions,最终都要返回:
ModelResponse(
output=response.output,
usage=usage,
response_id=response.id,
request_id=getattr(response, "_request_id", None),
)
或由 Chat Completions 转换后的:
ModelResponse(
output=items,
usage=usage,
response_id=None,
)
output 是 SDK 后续处理的关键:
只要 adapter 归一化正确,run loop 不需要知道底层 provider。
ModelSettings 到请求参数的映射
ModelSettings 是 SDK 统一模型配置:
| temperature | 采样温度 |
| top_p | nucleus sampling |
| frequency_penalty | 频率惩罚 |
| presence_penalty | 存在惩罚 |
| tool_choice | 工具选择 |
| parallel_tool_calls | 是否允许并行工具调用 |
| truncation | Responses 截断策略 |
| max_tokens | 最大输出 token |
| reasoning | 推理模型配置 |
| verbosity | 输出详略 |
| metadata | provider metadata |
| store | 是否服务端存储响应 |
| response_include | Responses include |
| top_logprobs | top token logprobs |
| retry | runner-managed retry |
| context_management | Responses context management |
| prompt_cache_options | prompt cache 配置 |
| extra_args | 直接传给 provider 的额外参数 |
但不是每个 adapter 都支持所有字段。
例如:
所以 ModelSettings 是统一入口,不是统一 wire format。
extra_args 的重复键保护
两个 OpenAI adapter 都会检查 extra_args 与显式参数是否重复。
例如 Responses:
duplicate_extra_arg_keys = sorted(
k
for k in extra_args
if k in create_kwargs and not _is_openai_omitted_value(create_kwargs[k])
)
如果重复,会抛:
responses.create() got multiple values for keyword argument '…'
这可以避免同一个字段既通过 ModelSettings.temperature 传,又通过 extra_args={"temperature": …} 传,造成行为不确定。
建议:
Runner-managed Retry
模型重试不是默认开启的。
需要显式设置:
from agents import ModelRetrySettings, ModelSettings, retry_policies
model_settings = ModelSettings(
retry=ModelRetrySettings(
max_retries=2,
policy=retry_policies.network_error(),
)
)
run loop 调用模型时会包一层:
new_response = await get_response_with_retry(
get_response=lambda: model.get_response(...),
rewind=rewind_model_request,
retry_settings=model_settings.retry,
get_retry_advice=model.get_retry_advice,
previous_response_id=previous_response_id,
conversation_id=conversation_id,
)
重试需要考虑 replay safety。
特别是:
这些场景不能简单按 HTTP 500 或网络错误重放。
Adapter 可以通过 get_retry_advice(…) 提供 provider-specific 建议。OpenAI、LiteLLM、Any-LLM adapter 都会复用 OpenAI 风格 retry advice 提取逻辑。
Provider-managed retry 与 Runner retry
OpenAI SDK、LiteLLM、any-llm 自身也可能有重试机制。
Runner-managed retry 在重放时会通过 contextvar 禁用 provider-managed retries:
provider_managed_retries_disabled(disabled=True)
adapter 里会检查:
if should_disable_provider_managed_retries():
return client.with_options(max_retries=0)
这样避免两层 retry 叠加,导致请求次数难以控制。
文章里的实践建议是:如果你需要可解释、可审计的重试策略,优先使用 runner-managed retry,并明确 policy。
MultiProvider:基于前缀的路由
MultiProvider 是默认 RunConfig.model_provider。
它支持按模型名前缀路由:
| gpt-5.4-mini | OpenAI provider |
| openai/gpt-4.1 | OpenAI provider,默认去掉 openai/ |
| litellm/openrouter/openai/gpt-5.4-mini | LitellmProvider |
| any-llm/openrouter/openai/gpt-5.4-mini | AnyLLMProvider |
源码中默认说明:
class MultiProvider(ModelProvider):
"""Maps model based on prefix."""
如果遇到未知前缀,默认抛 UserError。
如果你使用 OpenAI-compatible endpoint,并且后端期望完整 namespaced model id,可以配置:
provider = MultiProvider(
openai_base_url="https://openrouter.ai/api/v1",
openai_api_key="…",
openai_prefix_mode="model_id",
unknown_prefix_mode="model_id",
)
这样 openai/gpt-4.1 不会被当成 OpenAI alias 去掉前缀。
OpenAI-compatible endpoint
最小接入方式是自定义 AsyncOpenAI:
from openai import AsyncOpenAI
from agents import OpenAIChatCompletionsModel
client = AsyncOpenAI(
api_key="provider_api_key",
base_url="https://provider.example.com/v1",
)
model = OpenAIChatCompletionsModel(
model="provider-model-name",
openai_client=client,
)
然后放到 Agent:
agent = Agent(
name="Assistant",
instructions="你是一个简洁助手。",
model=model,
)
如果要按 run 生效,可以写 ModelProvider:
class CustomModelProvider(ModelProvider):
def get_model(self, model_name: str | None) –> Model:
return OpenAIChatCompletionsModel(
model=model_name or "provider-model-name",
openai_client=client,
)
再传入:
result = await Runner.run(
agent,
"你好",
run_config=RunConfig(model_provider=CustomModelProvider()),
)
这适合一个 run 内所有 Agent 都走同一个自定义 provider 的场景。
LiteLLM adapter
LitellmModel 通过 LiteLLM 调用第三方 provider。
直接使用:
from agents.extensions.models.litellm_model import LitellmModel
agent = Agent(
name="Assistant",
model=LitellmModel(
model="openrouter/openai/gpt-5.4-mini",
api_key="…",
),
)
或使用 MultiProvider 前缀:
agent = Agent(
name="Assistant",
model="litellm/openrouter/openai/gpt-5.4-mini",
)
LiteLLM adapter 基本走 Chat Completions 风格:
源码中调用形态:
ret = await litellm.acompletion(
model=self.model,
messages=converted_messages,
tools=converted_tools or None,
temperature=model_settings.temperature,
tool_choice=self._remove_not_given(tool_choice),
response_format=self._remove_not_given(response_format),
parallel_tool_calls=parallel_tool_calls,
api_key=self.api_key,
base_url=self.base_url,
**extra_kwargs,
)
适合:
Any-LLM adapter
AnyLLMModel 的特点是可以按 provider 能力选择 Responses 或 Chat Completions:
def _selected_api(self) –> Literal["responses", "chat_completions"]:
if self.api is not None:
...
return "responses" if self._supports_responses() else "chat_completions"
直接使用:
from agents.extensions.models.any_llm_model import AnyLLMModel
agent = Agent(
name="Assistant",
model=AnyLLMModel(
model="openrouter/openai/gpt-5.4-mini",
api_key="…",
),
)
或使用 MultiProvider 前缀:
agent = Agent(
name="Assistant",
model="any-llm/openrouter/openai/gpt-5.4-mini",
)
如果 provider 支持 Responses,它会走 _get_response_via_responses(…);否则走 _get_response_via_chat(…)。
这比 LiteLLM 多了一个选择层:
| LiteLLM | Chat Completions 风格 |
| Any-LLM | Responses 或 Chat Completions,取决于 provider 能力 |
但选择更多也意味着更要测试 provider 能力差异。
非 OpenAI Provider 与 Tracing
第三方 provider 示例里通常会调用:
set_tracing_disabled(disabled=True)
原因是默认 tracing 会上传到 OpenAI traces backend,需要 OpenAI API key。
如果你的模型 provider 不是 OpenAI,但仍想使用 OpenAI tracing,可以单独设置 tracing export key:
from agents import set_tracing_export_api_key
set_tracing_export_api_key("sk-…")
或者接入自定义 tracing processor。
生产建议:
混用模型时的边界
Agents SDK 允许一个 workflow 中不同 Agent 使用不同模型。
例如:
triage_agent = Agent(
name="Triage agent",
model="gpt-5.4-mini",
)
expert_agent = Agent(
name="Expert agent",
model=OpenAIChatCompletionsModel(
model="provider-model",
openai_client=custom_client,
),
)
但混用模型要注意:
文档也建议:同一个 workflow 尽量使用同一种 model shape。只有确实需要时再混用。
实践一:显式使用 OpenAI Responses
默认情况下 OpenAIProvider 已经走 Responses。
你仍然可以显式写清楚:
from agents import Agent, OpenAIProvider, RunConfig, Runner
agent = Agent(
name="Assistant",
instructions="你是一个简洁助手。",
model="gpt-5.4-mini",
)
provider = OpenAIProvider(use_responses=True)
result = await Runner.run(
agent,
"用一句话解释 Responses API。",
run_config=RunConfig(model_provider=provider),
)
如果要启用 websocket transport:
provider = OpenAIProvider(
use_responses=True,
use_responses_websocket=True,
)
WebSocket transport 适合需要复用连接或特定低延迟场景,但要注意连接生命周期和 keepalive 配置。
实践二:切换到 Chat Completions
如果 provider 不支持 Responses,可以用 Chat Completions:
from openai import AsyncOpenAI
from agents import Agent, OpenAIChatCompletionsModel
client = AsyncOpenAI(
api_key="provider_api_key",
base_url="https://provider.example.com/v1",
)
agent = Agent(
name="Assistant",
instructions="你是一个简洁助手。",
model=OpenAIChatCompletionsModel(
model="provider-model",
openai_client=client,
strict_feature_validation=True,
),
)
开发期建议打开 strict_feature_validation=True。
如果发现代码依赖 conversation_id、prompt、Responses tool search 等能力,就应该切回 Responses 或调整功能设计。
实践三:使用 LiteLLM
from agents import Agent, Runner, function_tool, set_tracing_disabled
set_tracing_disabled(True)
@function_tool
def get_weather(city: str) –> str:
return f"{city} 天气晴。"
agent = Agent(
name="Assistant",
instructions="你只用俳句回答。",
model="litellm/openrouter/openai/gpt-5.4-mini",
tools=[get_weather],
)
result = await Runner.run(agent, "东京天气怎么样?")
这里 litellm/ 前缀会被 MultiProvider 路由到 LitellmProvider。
如果要传显式 key,使用 LitellmModel(…) 直接构造更清楚。
实践四:使用 Any-LLM
from agents import Agent, Runner, set_tracing_disabled
set_tracing_disabled(True)
agent = Agent(
name="Assistant",
instructions="你是一个简洁助手。",
model="any-llm/openrouter/openai/gpt-5.4-mini",
)
result = await Runner.run(agent, "你好")
Any-LLM 会解析 provider:
openrouter/openai/gpt-5.4-mini
provider 是 openrouter,provider model 是 openai/gpt-5.4-mini。
如果你要强制 API 类型:
AnyLLMModel(
model="openrouter/openai/gpt-5.4-mini",
api="chat_completions",
)
这适合 provider 同时支持多种 API,但你希望固定行为的场景。
测试建议
模型适配层测试不能只测 final output。
至少覆盖:
本仓库已有相关测试:
新增 provider 或 adapter 时,应优先参考这些测试风格。
常见错误
第一,把 ModelSettings 当成所有 provider 都支持的参数集合。
它是 SDK 统一配置入口,不代表所有 adapter 都能原样支持每个字段。
第二,用 Chat Completions 但依赖 Responses-only 功能。
例如 conversation_id、prompt、tool search、deferred-loading Responses tools。
第三,混用 Responses 与 Chat Completions 后没有测 streaming。
非流式能跑不代表 streaming event 归一化正确。
第四,忽略 strict validation。
开发期不开 strict validation,容易把字段静默降级成 warning。
第五,把 extra_args 当成万能出口。
重复传参会报错;未知 provider 参数也可能只在运行时失败。
第六,第三方 provider 不关闭 tracing。
没有 OpenAI tracing key 时,默认 exporter 可能出现 401 或跳过上报。
第七,重试策略过于粗暴。
带 conversation_id 或已开始 streaming 的请求不能简单重放。
第八,没有关闭持久 provider 资源。
WebSocket Responses model 和某些第三方 client 可能持有连接,应在生命周期结束时调用 provider/model 的 close。
本篇小结
本篇拆解了 Agents SDK 的模型适配层。
核心结论:
下一篇会进入 MCP 集成:让 Agent 使用外部工具生态,理解 MCP server 如何映射为 SDK tools,以及连接、缓存、过滤和审批如何工作。
网硕互联帮助中心





评论前必须登录!
注册