Claude Agent SDK 开发指南2 - 对话、工具调用、MCP以及如何让AI操纵你的浏览器
上篇文章中我们看到,如何用Claude Agent SDK快速搭建一个AI Agent
只用了几分钟时间,我们就快速搭建了一个可以自动修复Python代码的QuickStart
在本篇文章中我们继续来深入了解Claude Agent SDK的核心组件——query()函数和ClaudeSDKClient类
Claude Agent SDK的核心组件主要包括两个部分:query()函数和ClaudeSDKClient类
如何去选择使用query()函数还是ClaudeSDKClient类
快速对比
| 特性 | query()函数 | ClaudeSDKClient类 |
|---|---|---|
| 会话 | 每次创建一个新的会话 | 在整个对话过程中复用同一个会话 |
| 对话次数 | 适合单次对话场景 | 适合在同一个上下文中多次对话 |
| 连接管理 | 自动管理连接 | 需要手动控制连接 |
| 流式输入 | ✅ 支持 | ✅ 支持 |
| 中断 | ❌ 不支持 | ✅ 支持 |
| 钩子 | ❌ 不支持 | ✅ 支持 |
| 自定义工具 | ❌ 不支持 | ✅ 支持 |
| 持续对话 | ❌ 每次都是新会话 | ✅ 维护对话上下文 |
| 使用场景 | 适合一次性任务 | 适合持续对话和复杂交互 |
注意:自定义工具,只能在ClaudeSDKClient里面使用,这是很多新手容易忽略的点
何时使用 query()(每次都是新会话)
最适合:
- 一次性问题,不需要对话历史
- 不需要之前交换上下文的独立任务
- 简单的自动化脚本
- 当你每次都想要一个全新的开始
何时使用 ClaudeSDKClient(持续对话)
最适合:
- 继续对话 - 当你需要 Claude 记住上下文时
- 后续问题 - 基于之前的回答构建
- 交互式应用程序 - 聊天界面、REPL
- 响应驱动逻辑 - 当下一个操作取决于 Claude 的响应时
- 会话控制 - 显式管理对话生命周期
简单总结
以上是官方对query()和ClaudeSDKClient的对比介绍
说简单点,query()函数更适合一次性任务,而ClaudeSDKClient类更适合持续对话和复杂交互
如果你希望做一个AI对话机器人,那么ClaudeSDKClient类无疑是更好的选择
如果你只是想执行一个简单的任务,比如发送一个微信公众号消息,那么使用query()函数就足够了
query() 函数
我们看一下query()的核心定义
async def query(
*,
prompt: str | AsyncIterable[dict[str, Any]],
options: ClaudeAgentOptions | None = None
) -> AsyncIterator[Message]
query()函数接受两个核心参数:
prompt:可以是一个字符串,也可以是一个异步可迭代对象,对话的提示词options:可选的配置对象,默认为ClaudeAgentOptions()
query()函数返回一个异步迭代器AsyncIterator[Message],可以用来逐步获取Claude Agent的响应
代码示例
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
async def main():
options = ClaudeAgentOptions(
system_prompt="你是一个经验丰富的Python开发人员",
permission_mode='acceptEdits',
cwd="./2-1-query"
)
async for message in query(
prompt="创建一个Python的Web服务器示例代码",
options=options
):
print(message)
asyncio.run(main())
大概用时几十秒,可以看到AI输出的结果如下
并看到,我们指定目录下生成了相应的代码文件
AI 甚至贴心的给我们写了一份README文件,让我们能轻松的读懂代码

工具调用和Mcp
AI Agent的核心,还是可以利用各类工具,为我们完成复杂的任务
在上面的例子中,AI Agent就调用了Edit工具,帮我们创建了Python代码文件
我们首先来看tool注解(装饰器)的定义
def tool(
name: str,
description: str,
input_schema: type | dict[str, Any]
) -> Callable[[Callable[[Any], Awaitable[dict[str, Any]]]], SdkMcpTool[Any]]
可以看到,tool注解接受三个参数
| 参数 | 类型 | 描述 |
|---|---|---|
| name | str | 工具的唯一标识符 |
| description | str | 工具功能的人类可读描述 |
| input_schema | type | dict[str, Any] |
对于input_schema参数,有两种方式可以
- 简单模式
{"text": str, "count": int, "enabled": bool}
// 表示工具需要三个参数,text是字符串,count是整数,enabled是布尔值
- 复杂模式JSON Schema格式
{
"type": "object",
"properties": {
"text": {"type": "string"},
"count": {"type": "integer", "minimum": 0}
},
"required": ["text"]
}
以上json_schema表示json例子如下
{
"text": "Hello, World!", // 必填
"count": 42 // 非必填,最小是0
}
我们现在来自定义一个简单的工具,来让AI打招呼
from claude_agent_sdk import tool
from typing import Any
@tool("greet", "Greet a user", {"name": str})
async def greet(args: dict[str, Any]) -> dict[str, Any]:
return {
"content": [{
"type": "text",
"text": f"你好, {args['name']}!"
}]
}
我们再回顾一下tool的返回值
-> Callable[[Callable[[Any], Awaitable[dict[str, Any]]]], SdkMcpTool[Any]]
可以看到,在Claude Agent SDK中,如果想要使用一个工具,你需要把它注册到MCP服务器(MCP Server)里面才可以使用
my_mcp_server = create_sdk_mcp_server(
name="my_mcp_server",
version="2.0.0",
tools=[greet] # Pass decorated functions
)
async def main():
options = ClaudeAgentOptions(
mcp_servers={"my_mcp_server": my_mcp_server},
allowed_tools=["mcp__my_mcp_server__greet"]
)
async with ClaudeSDKClient(options=options) as client:
await client.query("你好,我叫东方赞,请使用greet工具")
async for message in client.receive_response():
print(message)
asyncio.run(main())
我们详细解释一下这里的代码
-
query()函数无法使用自定义工具,如果要调用工具,你需要使用ClaudeSDKClient,在这里官方文档没有特别强调这一点,会让很多新接触的研发人员感到困惑
-
allowed_tools=["mcp__my_mcp_server__greet"]约定了工具的命名格式,mcp__{server_name}__{tool_name}
在代码执行过程中,可以看到AI成功调用了我们自定义的greet工具的过程
如果我们注释掉allowed_tools参数,AI会向用户发起询问,是否允许使用该工具
我们还可以使用一个外部的mcp server来实现网页抓取的功能
我们可以到模搭社区去找一个免费的mcp server,比如Chrome浏览器工具
首先在本地安装这个mcp server
npx chrome-devtools-mcp@latest
如果你没有安装Node.js,可以先去Node.js官网下载安装
然后我们启动启动执行这个mcp server
import asyncio
from claude_agent_sdk import ClaudeAgentOptions, ResultMessage, ClaudeSDKClient
from claude_agent_sdk._errors import CLIConnectionError
async def main():
options = ClaudeAgentOptions(
mcp_servers={
"chrome-devtools": {
"command": "npx",
"args": ["chrome-devtools-mcp@latest"]
}
},
allowed_tools=["mcp__chrome-devtools__*"],
)
async with ClaudeSDKClient(options=options) as client:
await client.query("帮我打开一个新的标签页,进入谷歌官网,并搜索东方赞博客"
"找到你觉得最可能是的,进去之后看看 他最近写了哪些东西?")
async for message in client.receive_response():
print(message)
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)
asyncio.run(main())
你可以非常清晰的看到整个操作过程
- AI Agent使用Chrome DevTools打开了一个新的标签页
- 进入谷歌官网
- 搜索“东方赞博客”
- 找到最可能的结果,进入博客页面
- 查看最近的文章内容
- 完成总结
我把整个视频录制了一份,感兴趣的朋友可以看下整个过程
总结
本文我们深入介绍了Claude Agent SDK的核心组件——query()函数和ClaudeSDKClient类
我们详细对比了两者的区别和使用场景,并通过工具调用和MCP,来展示了如何利用Agent SDK来完成复杂的任务
下篇文章,我们会继续深入其他更多的特性,比如流式输入、中断、钩子函数等高级功能
感谢你看到这里,如果你对Claude Agent SDK有任何问题,欢迎在评论区留言讨论!
