第3课:第一次对话 —— 学会 query()
本课目标
学会用 query() 给 Claude 发消息、收回复。这是最基础的操作,就像学开车先学踩油门。
最简代码
"""
03_basic_query.py
最简单的一问一答
"""
import anyio
from claude_agent_sdk import query
async def main():
async for message in query(prompt="什么是人工智能?用3句话解释"):
print(message)
anyio.run(main)
运行:uv run python 03_basic_query.py
就这么几行,你已经在调用 Claude 了。
等一下,这代码在干嘛?
一行一行拆:
import anyio # 异步运行库(Claude SDK 是异步的)
from claude_agent_sdk import query # 导入 query 函数
async def main(): # 异步函数,SDK 要求必须是异步的
async for message in query(prompt="你的问题"):
# ↑ query() 返回的是一个"异步迭代器"
# 意思是:消息不是一次性全给你的,而是一条一条蹦出来的
print(message)
anyio.run(main) # 启动异步事件循环
关键概念:异步(async)
为什么非要用 async?因为调用 Claude API 需要等网络响应,异步能让你的程序在等待时不卡死。你暂时不用完全理解 async,只要记住:凡是调 SDK 的代码,都包在 async def 里,用 anyio.run() 启动。
消息类型:Claude 回的到底是什么?
上面的代码把 message 直接 print 了,看起来乱七八糟的。让我们解析一下:
"""
03_parse_messages.py
解析消息类型
"""
import anyio
from claude_agent_sdk import query, AssistantMessage, ResultMessage, TextBlock
async def main():
async for message in query(prompt="Python 和 JavaScript 哪个更适合初学者?"):
# Claude 的回复
if isinstance(message, AssistantMessage):
print("【Claude 说】")
for block in message.content:
if isinstance(block, TextBlock):
print(block.text)
# 最终结果(包含花费信息等)
elif isinstance(message, ResultMessage):
print(f"\n--- 对话结束 ---")
print(f"会话ID: {message.session_id}")
# 如果有花费信息,可以在这里看到
anyio.run(main)
SDK 返回的消息有几种类型:
| 类型 | 是什么 | 你什么时候会遇到 |
|---|---|---|
AssistantMessage |
Claude 的回复 | 最常见,里面有文字内容 |
UserMessage |
用户消息的回显 | 偶尔出现 |
SystemMessage |
系统消息 | 初始化时可能出现 |
ResultMessage |
对话结束的总结 | 每次对话结束时 |
而 AssistantMessage 里面的内容(content)也分几种 Block:
| Block 类型 | 是什么 |
|---|---|
TextBlock |
普通文字回复(最常见) |
ToolUseBlock |
Claude 想要调用工具 |
ThinkingBlock |
Claude 的思考过程 |
现在只需要关注 TextBlock,其他的后面会用到。
给 Claude 加设定:system_prompt
光问问题有点无聊,我们给 Claude 设定一个角色:
"""
03_system_prompt.py
给 Claude 设定角色
"""
import anyio
from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, TextBlock
async def main():
options = ClaudeAgentOptions(
system_prompt="你是一个资深的科技行业分析师,擅长用数据说话,回答简洁有力。",
max_turns=1 # 只跑一轮(问一次答一次)
)
async for message in query(
prompt="分析一下 2025 年 AI 芯片市场的竞争格局",
options=options
):
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(block.text)
anyio.run(main)
ClaudeAgentOptions 是一个配置对象,相当于"设置面板"。这里我们用了两个设置:
- system_prompt — 告诉 Claude "你是谁",决定它的回答风格
- max_turns — 最多跑几轮对话。设成 1 就是一问一答
控制对话的长度和花费
在正式项目里,你肯定不想 Claude 无限制地跑下去。几个有用的参数:
options = ClaudeAgentOptions(
system_prompt="你是一个研究助手",
max_turns=3, # 最多 3 轮对话
max_budget_usd=0.50, # 最多花 0.5 美元
)
max_budget_usd 特别重要——设个上限,防止 Claude 跑飞了把你的余额烧光。
选模型
Claude 有不同的模型,能力和价格不同:
options = ClaudeAgentOptions(
model="haiku", # 快又便宜,适合简单任务
# model="sonnet", # 中等水平,性价比高(默认)
# model="opus", # 最强但最贵,适合复杂推理
)
做研究平台时,组长可以用 sonnet,搜索员用 haiku(便宜快速),这样省钱。
本课小结
这节课你学到了:
query(prompt="...")— 给 Claude 发消息的基本姿势- 消息类型 —
AssistantMessage里的TextBlock是你最常用的 ClaudeAgentOptions— 配置面板,控制角色、轮次、预算、模型- 异步写法 — 记住
async def+anyio.run()的套路就行
query() 适合"一锤子买卖"——问一个问题,拿到答案就走。但如果你想跟 Claude 来回聊天呢?那就需要下一课的 ClaudeSDKClient。
课后练习
- 修改 system_prompt,让 Claude 扮演一个美食博主,问它推荐菜谱
- 试试不同的 model 参数(haiku / sonnet),对比回答质量和速度
- 设置
max_budget_usd=0.01,看看 Claude 在极低预算下还能不能正常回答