GPT-6 Astra 发布后,旧项目最容易做的改动是把原来的模型名替换成 gpt-6-astra。普通问答也许还能正常返回,但只要流程里有函数调用,这一步就远远不够。
OpenAI 在 2026 年 9 月 3 日的更新日志中写明,Astra 的工具调用必须使用 Responses API,同时不支持 none reasoning effort、自定义 temperature、top_p 和 logprobs。这意味着迁移不只是换一个模型 ID,请求入口、参数、返回对象和工具结果的关联方式都要一起调整。

图:GPT-6 Astra 官方主视觉,来源 @OpenAIDevs。

图:OpenAI 于 2026 年 9 月 3 日发布的 API 更新说明。来源:OpenAI API Changelog。
动手前,先定位四处必改内容
第一处是请求入口。原来发往 /v1/chat/completions 的工具请求,需要改到 /v1/responses。Astra 虽然仍可处理部分 Chat Completions 请求,但工具调用不在这个范围内。
第二处是参数。检查公共封装、中间件和默认配置,删除 reasoning.effort: "none"、自定义 temperature、top_p 与 logprobs。这些字段有时不在业务代码里,而是由统一客户端自动补上,因此不能只看调用函数本身。
第三处是对象结构。发送端从 messages 转到 input,读取端也不能再只找 choices[0].message.content。Responses API 会在 response.output 中返回不同类型的 Item,包括 message、reasoning 和 function_call。只需要最终文本时可以读取 SDK 提供的 output_text,涉及工具调用时则必须按 type 遍历。
第四处是工具结果关联。模型发出的 function_call 带有一个 call_id,应用执行函数后,要把结果包装成 function_call_output,再用原来的 call_id 回传。函数名相同不代表是同一次调用,不能用工具名代替这个关联标识。
实际排查时,最好从最终发出的请求和响应解析分支往回查,不要只搜索某个业务文件。兼容问题经常藏在公共封装里:业务代码没有设置 temperature,统一客户端却按旧模型的默认值补上了;响应已经变成 Items,下游仍在按 message 读取。把这两端都确认清楚,再开始改代码。

图:messages 到 typed Items 的官方映射。来源:Migrate to the Responses API。
先迁普通请求,确认新对象能被项目正确读取
可以先用一条不带工具的请求检查基础结构。旧代码通常从 choices 里取文本:
from openai import OpenAI
client = OpenAI()
completion = client.chat.completions.create(
model="your-current-model",
messages=[{"role": "user", "content": "概括这段报错信息"}],
)
print(completion.choices[0].message.content)
迁移后,请求和读取方式改成下面这样:
from openai import OpenAI
client = OpenAI() # 默认从 OPENAI_API_KEY 读取密钥
response = client.responses.create(
model="gpt-6-astra",
reasoning={"effort": "medium"},
input="概括这段报错信息",
)
print(response.output_text)
这一步通过,只能说明请求已经进入 Responses API,项目也能读取最终文本。若业务存在多轮对话,还要明确采用哪种状态管理方式:使用 previous_response_id 接续前一轮、手动回传所需 Items,或使用 Conversations API。不要把旧的 messages 数组原样累加,再假设 reasoning 与工具 Item 会自动保留下来。
再跑通工具调用闭环,这是迁移的核心
下面用一个本地订单查询函数演示完整流程。它没有数据库和外部服务依赖,便于把注意力放在 call_id 上。代码依据 OpenAI 的 Function calling 文档整理,是可执行模板,不代表任意账号或 API 服务已经完成实测。
import json
from openai import OpenAI
client = OpenAI()
def get_order_status(order_id: str) –> dict:
demo_orders = {
"A10086": {"status": "已发货", "carrier": "顺丰", "eta": "明天"}
}
return demo_orders.get(order_id, {"status": "未找到"})
tools = [
{
"type": "function",
"name": "get_order_status",
"description": "根据订单号查询订单状态",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "需要查询的订单号",
}
},
"required": ["order_id"],
"additionalProperties": False,
},
"strict": True,
}
]
# 1. 让模型发起工具调用
response = client.responses.create(
model="gpt-6-astra",
reasoning={"effort": "medium"},
input="请查询订单 A10086,并告诉我当前状态。",
tools=tools,
tool_choice={"type": "function", "name": "get_order_status"},
)
# 2. 从 typed Items 中找到 function_call
tool_calls = [
item for item in response.output if item.type == "function_call"
]
if len(tool_calls) != 1:
raise RuntimeError(f"预期 1 次工具调用,实际得到 {len(tool_calls)} 次")
tool_call = tool_calls[0]
if not tool_call.call_id:
raise RuntimeError("工具调用缺少 call_id")
if tool_call.name != "get_order_status":
raise RuntimeError(f"未知工具:{tool_call.name}")
arguments = json.loads(tool_call.arguments)
tool_result = get_order_status(arguments["order_id"])
# 3. 用原始 call_id 回传工具结果,并接续同一轮上下文
final_response = client.responses.create(
model="gpt-6-astra",
previous_response_id=response.id,
input=[
{
"type": "function_call_output",
"call_id": tool_call.call_id,
"output": json.dumps(tool_result, ensure_ascii=False),
}
],
)
print(final_response.output_text)
应用负责真正执行 get_order_status,API 负责把模型的调用意图和执行结果接进同一段上下文。模板的预期结果也很明确:第一轮 output 中出现一次 function_call;应用只执行一次本地函数;第二轮沿用原 call_id;最终文本包含“已发货”等工具返回的信息。普通文本能出来,但中间缺了任何一环,都不能算工具迁移成功。
长任务控制,等基础闭环跑通后再加
Astra 同时带来了几项面向长任务的控制能力,但它们不是基础迁移的必选项。
如果工具运行时间较长,而且模型等待期间还有别的工作可做,可以在函数或自定义工具定义中加入 async: true:
async_tool = {
"type": "function",
"name": "run_long_job",
"description": "执行耗时任务",
"parameters": {"type": "object", "properties": {}},
"async": True,
}
应用仍然负责执行工具,任务完成后仍需使用原始 call_id 回传结果。异步只改变等待方式,不会替应用自动完成函数。
任务执行中确实需要追加或修改要求时,可以通过 WebSocket 使用 mid-turn steering。这里要额外保存尚未处理的指令,因为排队中的 steering 输入只存在于当前连接,断线后不能假设它们还在。若不同阶段需要不同推理强度,则在后续输入中加入 configuration_update:
configuration_update = {
"type": "configuration_update",
"reasoning": {"effort": "high"},
}
两个 configuration_update 不能在对话历史中紧挨着,否则请求会被拒绝。具体接入方式可分别查阅 Async tool calling、Mid-turn steering 和 Change reasoning mid-conversation。
最小验收,要看四个连续结果
验收时不要只看最后有没有一段文字。先确认请求中已经移除 Astra 不支持的参数,并且普通响应能从 output_text 或 output 中正确解析。随后固定一个必须调用函数的问题,检查返回对象里是否出现预期工具名、可解析参数和非空 call_id。
本地函数应当只执行一次。回传时使用同一个 call_id,模型还要能基于工具结果继续回答。为了排除项目代码“吞掉错误”的情况,可以故意删除或替换一次 call_id,确认异常请求不会被记录成成功;如果旧参数导致请求被拒绝,也应直接找到并删除对应配置,不能靠重试掩盖兼容问题。
只有文本返回、工具触发、结果关联和最终续答四项连续成立,这条工具链路才算完成迁移。项目没有使用异步工具、steering 或动态 reasoning 时,不必为了追新功能把它们塞进验收范围。
迁移完成后,还要检查实际使用的 API 服务
GPT-6 Astra 的工具调用迁移,可以收束成四件事:换到 /v1/responses,清理不兼容参数,按 typed Items 处理返回对象,再用原始 call_id 接回工具结果。前两项让请求符合新协议,后两项决定工具链路能否真正闭合。
代码按官方规则改完,解决的是客户端与协议的兼容问题。如果项目使用的并非官方直连接口,还要继续确认具体 API 服务是否支持 Responses API、typed Items、函数结果回传,以及业务真正需要的长任务控制。页面上能看到模型名称,和这几项能力已经完整适配,是两回事。
需要筛选具体服务时,可以先查看同一模型下的 API 服务信息,再用本文的最小闭环逐项验收。这样得到的结论才足够明确:哪条服务只是能接收请求,哪条已经能承载完整的工具调用。

图:OkenAI平台 GPT-6 Astra 价格列表




