跳到主要内容

Claude Agent SDK 开发指南2 - 对话、工具调用、MCP以及如何让AI操纵你的浏览器

· 阅读需 10 分钟
东方赞
程序员/注册会计师

上篇文章中我们看到,如何用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注解接受三个参数

参数类型描述
namestr工具的唯一标识符
descriptionstr工具功能的人类可读描述
input_schematypedict[str, Any]

对于input_schema参数,有两种方式可以

  1. 简单模式
{"text": str, "count": int, "enabled": bool}
// 表示工具需要三个参数,text是字符串,count是整数,enabled是布尔值
  1. 复杂模式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())

我们详细解释一下这里的代码

  1. query()函数无法使用自定义工具,如果要调用工具,你需要使用ClaudeSDKClient,在这里官方文档没有特别强调这一点,会让很多新接触的研发人员感到困惑

  2. 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())

你可以非常清晰的看到整个操作过程

  1. AI Agent使用Chrome DevTools打开了一个新的标签页
  2. 进入谷歌官网
  3. 搜索“东方赞博客”
  4. 找到最可能的结果,进入博客页面
  5. 查看最近的文章内容
  6. 完成总结

我把整个视频录制了一份,感兴趣的朋友可以看下整个过程

总结

本文我们深入介绍了Claude Agent SDK的核心组件——query()函数和ClaudeSDKClient

我们详细对比了两者的区别和使用场景,并通过工具调用和MCP,来展示了如何利用Agent SDK来完成复杂的任务

下篇文章,我们会继续深入其他更多的特性,比如流式输入、中断、钩子函数等高级功能

感谢你看到这里,如果你对Claude Agent SDK有任何问题,欢迎在评论区留言讨论!