入门 📋 6 个步骤 第 547 / 548 篇

用 OpenAI Responses API 搭会联网与调工具的 Agent

OpenAI 在 2026 把 Responses API 推成统一接口,内置 web_search 联网、strict 函数调用与流式。本教程从零跑通 Responses API,让 Agent 实时联网查最新信息、按 schema 调你的工具、逐字流式输出。

2026.10.19· 5 分钟上手· 约 1679 字· 🔌 OpenAI Responses API / 🌐 联网 Agent

你以前用 Chat Completions 调大模型、自己拼 function calling 的循环,每次都要重建对话历史、手管工具调用。2026 年 OpenAI 把 Responses API 推成了统一接口:内置联网检索、文件检索、strict 模式函数调用、流式输出一次到位,而且调用之间用 previous_response_id 自动串起上下文,不用你手动搬运历史。本教程从装 SDK、拿 Key 开始,一步步搭出一个会实时联网、能按 schema 调你的工具、还能逐字流式打印的 Agent。

🔌 本教程适合:已经会一点 Python、想用 OpenAI 最新统一接口搭 Agent 的初学者与开发者。你只需要一个 OpenAI API Key,不需要自己搭搜索服务或向量库。文中模型与工具类型名以官方文档当前版本为准。

Step 1:环境准备——装 SDK 与配置 Key

1 三行装好并验证能联通

Responses API 由官方 openai Python SDK 提供,装好后在环境变量里放好 Key,用最小一段代码确认能拿到回复。下面统一从环境变量读取密钥,别把 Key 写进代码或提交到仓库。

pip install -U openai

# 终端里设置(仅当前会话):
export OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxx"

from openai import OpenAI
client = OpenAI()  # 自动读 OPENAI_API_KEY 环境变量

密钥安全:API Key 等同于你账户的「花钱权限」,只放环境变量或密钥管理服务,绝不进代码仓库或前端。多人协作时给 Key 设用量上限,避免误用烧钱。

Step 2:第一次调用 Responses API(流式输出)

2 用 stream 逐字打印

和旧的 chat.completions 不同,Responses API 的入口是 client.responses.create / stream。传入 model 与 input(直接给字符串即可),开启 stream 后用事件流逐字输出。模型名随官方文档更新,下文以 gpt-6 示例,实际以你账户可用的模型为准。

with client.responses.stream(
    model="gpt-6",
    input="用三句话解释什么是 Agent。",
) as stream:
    for event in stream:
        if event.type == "response.output_text.delta":
            print(event.delta, end="", flush=True)
        elif event.type == "response.completed":
            print("\n[完成]")

final = stream.get_final_response()
print("用量 tokens:", final.usage.output_tokens)
💡 流式让用户体验更好(先看到前半句),也方便做打字机效果。如果不需要逐字,把 stream 换成普通 create,直接读 response.output_text 即可。

Step 3:加 web_search 内置工具,让 Agent 实时联网

3 一行开启,自带引用

Responses API 把「联网搜索」做成内置工具:你只要在 tools 数组里加一项,模型自己决定要不要搜,搜索在 OpenAI 服务端完成,不需要你接搜索 API 或解析结果。回复里会带 url 引用,可以展示给用户建立信任。工具类型名早期文档写作 web_search,新版多为 web_search_preview,以官方文档为准。

response = client.responses.create(
    model="gpt-6",
    input="2026 年 Responses API 有哪些内置工具?分别解决什么问题?",
    tools=[{"type": "web_search_preview"}],
)
print(response.output_text)

# 遍历输出项,打印它实际搜了什么
for item in response.output:
    if item.type == "web_search_call":
        print("搜索词:", item.query)

真实性提示:联网工具返回的是实时网页内容,质量取决于网络来源;涉及数字、日期、政策等关键信息,仍建议核对原始出处。工具类型名随 SDK 版本变化,若报「未知工具类型」,先查官方文档确认当前名称。

Step 4:定义自己的函数,启用 strict 模式

4 让模型按 schema 调你的代码

除了内置工具,你也可以注册自己的函数。把函数名、描述、参数 JSON Schema 写进 tools 数组,开启 strict: true 后,OpenAI 用约束解码保证返回的参数 100% 符合 schema——这在生产环境很关键,因为畸形 JSON 会直接打断你的执行逻辑。模型返回的是 function_call 类型的输出项,你本地执行函数后把结果回灌。

tools = [{
    "type": "function",
    "name": "get_weather",
    "description": "查询某城市当前天气",
    "parameters": {
        "type": "object",
        "properties": {
            "city": {"type": "string"},
            "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
        },
        "required": ["city", "unit"],
        "additionalProperties": False
    },
    "strict": True
}]
🔑 描述是模型决定「何时调用」的依据:写清楚函数的用途、输入和适用场景,比写能力名字命中率高得多。

Step 5:状态化——用 previous_response_id 串起多轮

5 不用手动搬运对话历史

Responses API 的服务端会保存每次调用的状态。下一轮只要带上 previous_response_id,模型就拥有完整上下文,你不必自己拼接历史消息。下方演示:第一次请求拿到 function_call,本地执行后把 function_call_output 回灌,再用 previous_response_id 衔接,模型据此生成最终回答。

response = client.responses.create(
    model="gpt-6",
    tools=tools,
    input="东京和柏林现在多少度?",
)
calls = [o for o in response.output if o.type == "function_call"]

results = []
for call in calls:
    args = json.loads(call.arguments)
    data = {"temperature": 18, "unit": args["unit"]}  # 你的真实实现
    results.append({
        "type": "function_call_output",
        "call_id": call.call_id,
        "output": json.dumps(data, ensure_ascii=False),
    })

final = client.responses.create(
    model="gpt-6",
    previous_response_id=response.id,
    input=results,
)
print(final.output_text)

边界:函数执行要设超时与失败兜底——网络抖动或参数异常时返回结构化错误,而不是让整个 Agent 循环卡死。涉及写操作的函数(发邮件、下单)务必加人工确认或权限校验。

Step 6:把「工具返回→再请求」封成循环

6 一个最小可复用的 Agent 循环

把上面的单次交互扩成循环:只要模型还产出 function_call,就本地执行并回灌,直到它给出最终文本。这就是 Responses API 上最朴素的 Agent 循环,兼顾内置工具与你的自定义函数。

def agent_loop(client, user_input, tools, model="gpt-6"):
    resp = client.responses.create(model=model, tools=tools, input=user_input)
    while True:
        calls = [o for o in resp.output if o.type == "function_call"]
        if not calls:
            return resp.output_text
        results = []
        for call in calls:
            args = json.loads(call.arguments)
            out = run_my_tool(call.name, args)   # 你的本地实现
            results.append({"type": "function_call_output",
                            "call_id": call.call_id, "output": json.dumps(out, ensure_ascii=False)})
        resp = client.responses.create(model=model, previous_response_id=resp.id, input=results)

print(agent_loop(client, "帮我把北京天气和上海天气对比一下", tools))
💡 加 parallel tool calls 时,模型一次可能请求多个函数,上面的循环天然支持——本地把多个结果一起回灌即可。生产环境再叠加重试、限流与日志,雏形就稳了。

常见问题速查

现象原因与处理
报「未知工具类型」SDK 版本与文档不一致,查官方确认 web_search / file_search 等内置工具当前类型名
模型不调用我的函数检查 description 是否写清触发场景;直接说「用 get_weather 查北京」更易触发
strict 模式报错参数 schema 必须设 additionalProperties: false 且 required 覆盖全部属性
多轮上下文丢失确认每轮都传了 previous_response_id,不要自己重建 messages 数组
← 返回教程中心