Python調用OpenAI?Agents?SDK打造一個多智能體系統(tǒng)

引言
2025年初,OpenAI發(fā)布了 Agents SDK(openai-agents),一個專為Python開發(fā)者設計的多智能體框架。與LangGraph的圖抽象、CrewAI的角色編排不同,Agents SDK走了一條更直覺的路線:純Python、零DSL、開箱即用。
截至目前,該SDK在GitHub上已獲得超過 23,000 Stars,版本迭代至 v0.14.2,成為2026年增長最快的Agent框架之一。
本文將帶你從零開始,用Agents SDK構建一個完整的智能購物助手——包含路由分診、專家協(xié)作、安全護欄、運行追蹤等完整功能。
一、核心架構概覽
Agents SDK 的九大核心概念
在開始編碼之前,先理解SDK的設計哲學。Agents SDK圍繞9個核心概念構建:

三種多智能體編排模式
SDK提供了三種編排多Agent的模式,適用于不同場景:

| 模式 | 適用場景 | 特點 | 控制權 |
|---|---|---|---|
| Manager | 需要匯總多個Agent結果 | 中心化協(xié)調 | Manager持有 |
| Handoff | 專家應直接面對用戶 | 去中心化交接 | 轉移給專家 |
| Code Orchestration | 確定性流程控制 | Python代碼編排 | 開發(fā)者控制 |
二、環(huán)境搭建
安裝SDK
# 創(chuàng)建虛擬環(huán)境 python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate # 安裝 Agents SDK pip install openai-agents # 驗證安裝 python -c "import agents; print(agents.__version__)" # 輸出: 0.14.2
配置API Key
import os # 方式1: 環(huán)境變量 os.environ["OPENAI_API_KEY"] = "sk-your-api-key-here" # 方式2: .env 文件(推薦) # 在項目根目錄創(chuàng)建 .env 文件: # OPENAI_API_KEY=sk-your-api-key-here
最簡示例:Hello Agent
在深入復雜場景之前,先跑通最簡單的例子:
import asyncio
from agents import Agent, Runner
async def main():
# 創(chuàng)建一個Agent —— 就這么簡單
agent = Agent(
name="Haiku Master",
instructions="你只使用俳句格式回答問題。俳句是5-7-5音節(jié)的三行詩。",
)
# 運行Agent
result = await Runner.run(agent, "用Python寫遞歸是什么感覺?")
print(result.final_output)
# 輸出:
# 函數(shù)調自身,
# 分解問題為小塊,
# 無盡由設計。
if __name__ == "__main__":
asyncio.run(main)
Agent執(zhí)行循環(huán):Runner.run() 啟動后,SDK會執(zhí)行一個循環(huán)——調用LLM、處理工具調用、處理交接,直到LLM產(chǎn)生最終輸出或達到最大輪次。
三、實戰(zhàn):構建智能購物助手
現(xiàn)在進入正題。我們將構建一個包含以下功能的智能購物助手:

Step 1: 定義共享上下文
所有Agent共享同一個上下文對象,用于傳遞狀態(tài):
from pydantic import BaseModel
class ShoppingContext(BaseModel):
"""購物助手的共享上下文"""
customer_id: str | None = None
customer_name: str | None = None
order_id: str | None = None
cart_items: list[str] = []
is_premium_user: bool = False
Step 2: 定義工具(Tools)
工具是Agent的"手"——讓它能與外部世界交互:
import random
from agents import RunContextWrapper, function_tool
# ===== 商品相關工具 =====
@function_tool
async def search_products(query: str) -> str:
"""搜索商品。query是搜索關鍵詞。"""
# 實際項目中這里連接搜索引擎或數(shù)據(jù)庫
mock_products = {
"手機": "iPhone 16 Pro (¥8,999), Samsung S26 (¥6,999), Xiaomi 16 (¥3,499)",
"筆記本": "MacBook Pro M5 (¥14,999), ThinkPad X1 (¥9,999), Surface Laptop (¥8,999)",
"耳機": "AirPods Pro 3 (¥1,899), Sony WH-1000XM6 (¥2,499), Bose QC Ultra (¥2,299)",
}
for keyword, products in mock_products.items():
if keyword in query:
return f"找到以下商品: {products}"
return f"未找到與 '{query}' 相關的商品,試試其他關鍵詞?"
@function_tool
async def get_product_detail(product_name: str) -> str:
"""獲取商品詳情。product_name是商品名稱。"""
details = {
"iPhone 16 Pro": "A20芯片 | 6.3英寸 | 4800萬像素 | 256GB起 | 電池續(xù)航30小時",
"MacBook Pro M5": "M5芯片 | 16英寸 | 36GB內存 | 512GB SSD | 續(xù)航24小時",
}
return details.get(product_name, f"商品 '{product_name}' 詳情: 評分4.8 | 月銷10000+ | 好評率98%")
@function_tool
async def add_to_cart(
context: RunContextWrapper[ShoppingContext],
product_name: str,
quantity: int = 1
) -> str:
"""將商品加入購物車。"""
context.context.cart_items.append(f"{product_name} x{quantity}")
return (f"已將 {product_name} x{quantity} 加入購物車。"
f"當前購物車: {', '.join(context.context.cart_items)}")
# ===== 訂單相關工具 =====
@function_tool
async def check_order_status(
context: RunContextWrapper[ShoppingContext],
order_id: str
) -> str:
"""查詢訂單狀態(tài)。order_id是訂單號。"""
context.context.order_id = order_id
statuses = ["已發(fā)貨", "運輸中", "派送中", "已簽收"]
status = random.choice(statuses)
return f"訂單 {order_id} 狀態(tài): {status}。預計到達: 明天下午。"
@function_tool
async def process_refund(
context: RunContextWrapper[ShoppingContext],
order_id: str,
reason: str
) -> str:
"""處理退款。order_id是訂單號,reason是退款原因。"""
if context.context.is_premium_user:
return f"VIP用戶優(yōu)先退款已提交!訂單 {order_id},原因: {reason}。退款將在1-2個工作日內到賬。"
return f"退款已提交!訂單 {order_id},原因: {reason}。退款將在3-5個工作日內到賬。"
@function_tool
async def track_package(order_id: str) -> str:
"""追蹤包裹物流。"""
locations = ["北京分揀中心", "上海轉運站", "杭州配送站", "客戶所在城市"]
location = random.choice(locations)
return f"訂單 {order_id} 最新位置: {location}。更新時間: 10分鐘前。"
Step 3: 定義安全護欄(Guardrails)
護欄是Agent的"安全帶"——防止越界行為:
from pydantic import BaseModel, Field
from agents import (
GuardrailFunctionOutput, InputGuardrailTripwireTriggered,
RunContextWrapper, TResponseInputItem, Agent, Runner,
input_guardrail,
)
# ===== 輸入護欄: 檢查是否為購物相關問題 =====
class RelevanceCheck(BaseModel):
is_shopping_related: bool = Field(description="是否與購物/商品/訂單相關")
reasoning: str = Field(description="判斷理由")
guardrail_agent = Agent(
name="Relevance Guard",
instructions="""判斷用戶輸入是否與以下領域相關:
- 商品搜索與推薦
- 訂單查詢與物流
- 退款與售后
- 購物咨詢
如果完全無關,標記為不相關。""",
output_type=RelevanceCheck,
)
@input_guardrail
async def shopping_relevance_guardrail(
ctx: RunContextWrapper[None],
agent: Agent,
input: str | list[TResponseInputItem]
) -> GuardrailFunctionOutput:
"""確保Agent只處理購物相關問題"""
result = await Runner.run(guardrail_agent, input, context=ctx.context)
check = result.final_output_as(RelevanceCheck)
return GuardrailFunctionOutput(
output_info=check.model_dump(),
tripwire_triggered=not check.is_shopping_related,
)
Step 4: 創(chuàng)建三個核心Agent
from agents import Agent, handoff
from agents.extensions.handoff_prompt import RECOMMENDED_PROMPT_PREFIX
# ===== Agent 1: 商品專家 =====
product_agent = Agent[ShoppingContext](
name="Product Specialist",
handoff_description="處理商品搜索、推薦、詳情查詢和加購。",
instructions=f"""{RECOMMENDED_PROMPT_PREFIX}
你是一個熱情的商品專家,名叫小商。
## 你的職責
- 幫助用戶搜索和推薦商品
- 提供商品詳細信息
- 協(xié)助用戶將商品加入購物車
## 工作流程
1. 理解用戶的購物需求
2. 使用 search_products 搜索相關商品
3. 如果用戶想了解某個商品,使用 get_product_detail
4. 如果用戶決定購買,使用 add_to_cart
## 規(guī)則
- 推薦時優(yōu)先考慮性價比
- 如果用戶的需求超出了商品范圍(如查訂單、退款),交接給訂單專家
- 保持友好專業(yè)的語氣
""",
tools=[search_products, get_product_detail, add_to_cart],
)
# ===== Agent 2: 訂單專家 =====
order_agent = Agent[ShoppingContext](
name="Order Specialist",
handoff_description="處理訂單查詢、物流追蹤和退款處理。",
instructions=f"""{RECOMMENDED_PROMPT_PREFIX}
你是一個耐心的訂單專家,名叫小單。
## 你的職責
- 查詢訂單狀態(tài)
- 追蹤包裹物流
- 處理退款請求
## 工作流程
1. 確認用戶的訂單號(如果沒有,先詢問)
2. 根據(jù)需求使用對應工具:
- 查狀態(tài) → check_order_status
- 查物流 → track_package
- 退款 → process_refund
## 規(guī)則
- 處理退款時務必確認訂單號和退款原因
- VIP用戶享有優(yōu)先退款
- 如果用戶想繼續(xù)購物,交接給商品專家
- 保持耐心和同理心
""",
tools=[check_order_status, track_package, process_refund],
)
# ===== Agent 3: 分診路由 =====
triage_agent = Agent[ShoppingContext](
name="Shopping Triage",
instructions=f"""{RECOMMENDED_PROMPT_PREFIX}
你是一個智能購物助手的接待員。
## 你的職責
判斷用戶的需求類型,將其路由到正確的專家:
- 商品搜索/推薦/購買 → 商品專家 (Product Specialist)
- 訂單查詢/物流/退款 → 訂單專家 (Order Specialist)
## 規(guī)則
- 簡單打招呼由你自己回復
- 無法判斷時,優(yōu)先交給商品專家
- 用一句話簡單介紹自己后立即路由
""",
input_guardrails=[shopping_relevance_guardrail],
handoffs=[
handoff(agent=product_agent),
handoff(agent=order_agent),
],
)
# 允許專家之間互相交接
product_agent.handoffs.append(handoff(agent=order_agent))
order_agent.handoffs.append(handoff(agent=product_agent))
# 允許專家回到分診
product_agent.handoffs.append(handoff(agent=triage_agent))
order_agent.handoffs.append(handoff(agent=triage_agent))
Step 5: 主循環(huán) + 運行追蹤
import uuid
from agents import (
Runner, trace, HandoffOutputItem, ItemHelpers,
MessageOutputItem, ToolCallItem, ToolCallOutputItem,
)
async def main():
current_agent = triage_agent
input_items: list = []
context = ShoppingContext(is_premium_user=True) # 模擬VIP用戶
conversation_id = uuid.uuid4().hex[:16]
print("=" * 60)
print(" 歡迎使用智能購物助手!")
print(" 輸入 'quit' / 'exit' / 'bye' 退出")
print("=" * 60)
while True:
user_input = input("\n?? 你: ").strip()
if not user_input:
continue
if user_input.lower() in ("quit", "exit", "bye"):
print("?? 感謝使用,再見!")
break
input_items.append({"content": user_input, "role": "user"})
try:
with trace("Shopping Assistant", group_id=conversation_id):
result = await Runner.run(
current_agent,
input_items,
context=context,
)
# 打印詳細的執(zhí)行過程
for new_item in result.new_items:
agent_name = new_item.agent.name
if isinstance(new_item, MessageOutputItem):
text = ItemHelpers.text_message_output(new_item)
if text:
print(f"\n?? [{agent_name}]: {text}")
elif isinstance(new_item, HandoffOutputItem):
print(f" ?? [交接] {new_item.source_agent.name} "
f"→ {new_item.target_agent.name}")
elif isinstance(new_item, ToolCallItem):
print(f" ?? [{agent_name}]: 正在調用工具...")
elif isinstance(new_item, ToolCallOutputItem):
print(f" ?? [工具結果]: {str(new_item.output)[:100]}...")
input_items = result.to_input_list()
current_agent = result.last_agent
except InputGuardrailTripwireTriggered as e:
message = "抱歉,我只能幫助處理購物相關問題(商品、訂單、退款等)。請換個問題試試?"
print(f"\n??? [護欄觸發(fā)]: {message}")
input_items.append({"role": "assistant", "content": message})
if __name__ == "__main__":
asyncio.run(main())
運行效果演示
============================================================ 歡迎使用智能購物助手! 輸入 'quit' / 'exit' / 'bye' 退出 ============================================================ ?? 你: 你好,我想買個手機 ?? [Shopping Triage]: 你好!我是智能購物助手,馬上為你找商品專家! ?? [交接] Shopping Triage → Product Specialist ?? [Product Specialist]: 你好!我是商品專家小商 ?? 來幫你挑手機! ?? [Product Specialist]: 正在調用工具... ?? [工具結果]: 找到以下商品: iPhone 16 Pro (¥8,999), Samsung S26 (¥6,999), Xiaomi 16 (¥3,499)... ?? [Product Specialist]: 我為你找到了幾款熱門手機: - iPhone 16 Pro - ¥8,999 - Samsung S26 - ¥6,999 - Xiaomi 16 - ¥3,499 你預算大概多少?我可以進一步推薦! ?? 你: iPhone 16 Pro 怎么樣? ?? [Product Specialist]: 正在調用工具... ?? [工具結果]: A20芯片 | 6.3英寸 | 4800萬像素 | 256GB起 | 電池續(xù)航30小時 ?? [Product Specialist]: iPhone 16 Pro 是今年的旗艦款,配置非常強: - A20芯片,性能提升40% - 4800萬像素主攝 - 電池續(xù)航長達30小時 要加入購物車嗎? ?? 你: 好的,加一輛 ?? [Product Specialist]: 正在調用工具... ?? [工具結果]: 已將 iPhone 16 Pro x1 加入購物車... ?? [Product Specialist]: 已加入購物車!還需要別的嗎?或者我可以幫你查一下訂單? ?? 你: 幫我查一下我之前的訂單 20260315001 ?? [交接] Product Specialist → Order Specialist ?? [Order Specialist]: 正在調用工具... ?? [工具結果]: 訂單 20260315001 狀態(tài): 運輸中。預計到達: 明天下午。 ?? [Order Specialist]: 你的訂單 20260315001 正在運輸中,預計明天下午就能收到啦! ?? 你: 天氣怎么樣? ??? [護欄觸發(fā)]: 抱歉,我只能幫助處理購物相關問題(商品、訂單、退款等)。請換個問題試試?
四、深入理解:Agent執(zhí)行流程
Runner的執(zhí)行循環(huán)
當你調用 Runner.run() 時,SDK內部執(zhí)行如下循環(huán):

護欄的執(zhí)行時機
護欄不是在所有Agent上都運行,而是有明確的邊界:

| 護欄類型 | 執(zhí)行時機 | 觸發(fā)效果 |
|---|---|---|
| Input Guardrail | 鏈中首個Agent收到輸入時 | 拋出異常,阻止執(zhí)行 |
| Output Guardrail | 最終Agent產(chǎn)生輸出時 | 拋出異常,阻止輸出 |
| Tool Guardrail | 每次函數(shù)工具調用時 | 拒絕內容或拋出異常 |
五、進階:Agents as Tools 模式
Handoff模式適合"接力賽"場景,但當你需要一個Agent匯總多個Agent的結果時,應該使用 Agents as Tools 模式:
# ===== Agents as Tools 模式 =====
# 場景: 內容創(chuàng)作流水線 —— 一個Manager Agent協(xié)調調研、寫作、審核
from agents import Agent, Runner, trace
# 專家Agent
researcher = Agent(
name="Researcher",
instructions="你是一個調研專家。對給定主題進行深度調研,輸出結構化的調研報告。",
)
writer = Agent(
name="Writer",
instructions="你是一個資深技術寫手?;谡{研報告撰寫高質量的技術文章。",
)
reviewer = Agent(
name="Reviewer",
instructions="""你是一個嚴格的審核編輯。從以下維度審核文章:
1. 技術準確性 (0-10)
2. 可讀性 (0-10)
3. 完整性 (0-10)
輸出JSON格式的評分和修改建議。""",
output_type=dict, # 結構化輸出
)
# Manager Agent —— 把專家當作工具使用
manager = Agent(
name="Content Manager",
instructions="""你是一個內容管理Agent,負責協(xié)調一篇文章的創(chuàng)作。
工作流程:
1. 先用 research 工具調研主題
2. 再用 write 工具基于調研結果撰寫文章
3. 最后用 review 工具審核文章質量
4. 如果評分低于8分,根據(jù)意見修改后重新審核
""",
tools=[
researcher.as_tool(
tool_name="research",
tool_description="對指定主題進行深度調研,返回調研報告"
),
writer.as_tool(
tool_name="write",
tool_description="基于調研報告撰寫技術文章"
),
reviewer.as_tool(
tool_name="review",
tool_description="審核文章質量,返回評分和修改建議"
),
],
)
async def create_article(topic: str) -> str:
with trace("Content Creation Pipeline"):
result = await Runner.run(
manager,
f"請創(chuàng)作一篇關于 '{topic}' 的技術文章"
)
return result.final_output
兩種模式的對比

| 特性 | Handoff | Agents as Tools |
|---|---|---|
| 用戶交互 | 專家直接面對用戶 | 只與Manager交互 |
| 上下文 | 完整傳遞 | 工具輸入/輸出 |
| 適合場景 | 客服、路由 | 內容創(chuàng)作、分析 |
| 復雜度 | 低 | 中 |
六、Tracing:調試與監(jiān)控
SDK內置了完整的Tracing系統(tǒng),可以追蹤每一次Agent運行、工具調用、交接和護欄檢查:
from agents import Agent, Runner, trace
# 方式1: 自動Tracing(默認開啟)
result = await Runner.run(agent, "Hello")
# 自動在 OpenAI Dashboard 中創(chuàng)建 trace
# 方式2: 手動創(chuàng)建 trace(跨多個 run)
with trace("復雜工作流", group_id="session-123"):
result1 = await Runner.run(agent1, "步驟1")
result2 = await Runner.run(agent2, f"基于上一步: {result1.final_output}")
result3 = await Runner.run(agent3, f"最終處理: {result2.final_output}")
# 方式3: 關閉 Tracing
from agents import set_tracing_disabled
set_tracing_disabled(True)
集成外部監(jiān)控
# 集成 LangSmith / Weights & Biases / MLflow 等 from agents import add_trace_processor # 方式1: 添加自定義處理器(保留OpenAI后端) add_trace_processor(my_custom_processor) # 方式2: 完全替換處理器 from agents import set_trace_processors set_trace_processors([langsmith_processor, wandb_processor])
長時間運行的任務
from agents import Runner, trace, flush_traces
async def background_agent_task(prompt: str):
try:
with trace("background_task"):
result = await Runner.run(agent, prompt)
return result.final_output
finally:
# 確保在Celery/FastAPI等場景中刷新trace
flush_traces()
七、與其他框架的對比

| 維度 | OpenAI Agents SDK | LangGraph | CrewAI |
|---|---|---|---|
| 學習曲線 | 低(純Python) | 中-高(圖抽象) | 低-中 |
| 護欄 | 內置三重護欄 | 手動實現(xiàn) | 有限 |
| Tracing | 免費內置 | 需LangSmith | 有限 |
| Human-in-the-Loop | 內置 | 通過圖中斷 | 基本 |
| LLM支持 | OpenAI原生,也支持100+ | 任意LLM | 任意LLM |
| MCP支持 | 內置 | 需集成 | 有限 |
| 語音Agent | 支持 | 不支持 | 不支持 |
| 沙盒Agent | 支持(Docker) | 不支持 | 不支持 |
| 適用場景 | 快速多Agent應用 | 復雜有狀態(tài)工作流 | 快速原型 |
選擇建議

八、最佳實踐總結
DO ?
| 實踐 | 說明 |
|---|---|
使用 RECOMMENDED_PROMPT_PREFIX | 官方推薦的交接提示前綴,能顯著提升交接質量 |
| 每個Agent職責單一 | "一個Agent只做一件事"比"全能Agent"效果好得多 |
| 使用結構化輸出 | 用Pydantic模型定義 output_type,提高結果可靠性 |
| 啟用護欄 | 即使是Demo,也加上輸入護欄,養(yǎng)成習慣 |
| 使用Tracing | 調試多Agent系統(tǒng)沒有Tracing等于盲人摸象 |
| 動態(tài)指令 | 用回調函數(shù)代替靜態(tài)字符串,實現(xiàn)上下文感知的指令 |
DON’T ?
| 反模式 | 原因 |
|---|---|
| 給Agent太多工具 | 5個以上的工具會降低LLM選擇準確率 |
| 過深的交接鏈 | 超過3層交接會導致上下文丟失 |
忽略 max_turns | 必須設置上限防止無限循環(huán) |
| 在護欄中使用強模型 | 護欄用 gpt-4o-mini 即可,省錢且夠用 |
| 不處理護欄異常 | GuardrailTripwireTriggered 必須被優(yōu)雅處理 |
結語
OpenAI Agents SDK用最Pythonic的方式解決了多智能體系統(tǒng)的構建問題——沒有DSL,沒有復雜的圖抽象,只有你熟悉的Python代碼。
它的核心設計哲學可以概括為三點:
- Agent即配置:一個字典式的配置對象就是一個Agent
- Handoff即工具:交接對LLM來說就是一個特殊的工具調用
- Guardrails即安全網(wǎng):三重護欄讓Agent行為可預測
2026年,AI Agent不再是實驗室的玩具。選擇合適的框架,從第一個多智能體系統(tǒng)開始,這是每個Python開發(fā)者的必修課。
以上就是Python調用OpenAI Agents SDK打造一個多智能體系統(tǒng)的詳細內容,更多關于Python Agents SDK多智能體系統(tǒng)的資料請關注腳本之家其它相關文章!
相關文章
Python?pywin32實現(xiàn)word與Excel的處理
這篇文章主要介紹了Python?pywin32實現(xiàn)word與Excel的處理,pywin32處理Word大多數(shù)用于格式轉換,因為一般讀寫操作都可以借助python-docx實現(xiàn),除非真的有特殊要求,但大部分企業(yè)對Wrod操作不會有太多復雜需求2022-08-08
Python Opencv提取圖片中某種顏色組成的圖形的方法
這篇文章主要介紹了Python Opencv提取圖片中某種顏色組成的圖形的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-09-09
python+mongodb數(shù)據(jù)抓取詳細介紹
這篇文章主要介紹了python+mongodb數(shù)據(jù)抓取詳細介紹,具有一定參考價值,需要的朋友可以了解下。2017-10-10
使用Python開發(fā)一個Ditto剪貼板數(shù)據(jù)導出工具
在日常工作中,我們經(jīng)常需要處理大量的剪貼板數(shù)據(jù),下面將介紹如何使用Python的wxPython庫開發(fā)一個圖形化工具,實現(xiàn)從Ditto數(shù)據(jù)庫中讀取、選擇和導出剪貼板歷史記錄的功能2025-08-08
Python實現(xiàn)輕松處理兩行表頭Excel并可視化分析(附完整代碼)
在日常的數(shù)據(jù)處理中,我們經(jīng)常會遇到多級表頭的 Excel 文件,本文通過一個實際案例,帶你完整了解讀取 Excel ,整理多級表頭 ,提取庫存,銷量的數(shù)據(jù) ,繪圖可視化的完整步驟吧2025-11-11

