第一步:一个 agent,三把工具,你全权指挥
对应清单 4.1
这一版就是第三章的自然延伸:一个 agent 同时连三个 MCP server。 注意提示词里那句「先…然后…最后…」——执行顺序是你用大白话写死的。
import asyncio
import os
from pathlib import Path
from agents import Agent, Runner, set_default_openai_api, set_tracing_disabled
from agents.mcp import MCPServerStdio, MCPServerStdioParams
from dotenv import load_dotenv
# 仓库原文没有这三行,是为了接第三方模型加的
load_dotenv()
set_default_openai_api("chat_completions")
set_tracing_disabled(True)
SANDBOX = os.path.dirname(os.path.abspath(__file__))
SCRIPT = Path(__file__).with_name("01_research_tools_mcp_server.py").resolve()
async def main():
# 先把三个 server 都实例化出来……
servers = [
MCPServerStdio(
name="Research Tools",
params=MCPServerStdioParams(
command="mcp",
args=["run", str(SCRIPT)],
),
),
MCPServerStdio(
name="sequential-thinking",
params={
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-sequential-thinking"],
},
),
MCPServerStdio(
name="filesystem",
params={
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", SANDBOX],
},
),
]
instructions = """
你是一个研究助手,可以用工具来做研究和规划。
给你一个研究目标后,先用研究工具找到研究来源。
然后用 sequential thinking 工具来规划研究。
最后用文件系统工具把研究计划写成一个文本文件。
"""
# ……然后一次性把它们全打开
async with (
servers[0] as research_srv,
servers[1] as thinking_srv,
servers[2] as fs_srv,
):
agent = Agent(
name="Assistant",
instructions=instructions,
mcp_servers=[research_srv, thinking_srv, fs_srv],
)
goal = """
做一份研究计划,用来找到《银河系漫游指南》这本书
"""
print("运行中……", goal)
result = await Runner.run(agent, goal)
print(result.final_output)
if __name__ == "__main__":
asyncio.run(main())
async with (a as x, b as y, c as z) 这个写法是 Python 3.10+ 的括号版
多上下文管理器——三个子进程一起开、一起关。这也是为什么这本书要求 3.11+。
一个 agent 拿着三个 server 的全部工具,意味着它的工具清单很长、提示词要交代所有步骤。 工具一多,模型挑错的概率就上升;提示词一长,它就开始漏步骤。 这就是为什么下一步要拆。