前面用的 query() 是"一锤子买卖"——发一个任务,等 AI 做完。但 DevOps 场景经常需要来回交流:

第 6 课:交互式会话——ClaudeSDKClient


query() vs ClaudeSDKClient

前面用的 query() 是"一锤子买卖"——发一个任务,等 AI 做完。但 DevOps 场景经常需要来回交流

code
query()(一次性):
  你: "跑测试"
  AI: [测试结果]
  结束。

ClaudeSDKClient(多轮对话):
  你: "看看日志"
  AI: [日志分析结果]
  你: "第 42 行那个错误是什么原因?"
  AI: [分析错误原因]
  你: "帮我修一下"
  AI: [修改代码]
  你: "再跑一次测试"
  AI: [测试通过!]

ClaudeSDKClient 就是为这种"聊天式"工作流设计的。

基本用法

bash
import anyio
from claude_agent_sdk import (
    ClaudeSDKClient, ClaudeAgentOptions,
    AssistantMessage, ResultMessage, TextBlock
)

async def main():
    options = ClaudeAgentOptions(
        system_prompt="你是 DevOps 助手,帮我管理服务器和代码。",
        allowed_tools=["Bash", "Read", "Write"],
    )

    # async with 确保资源正确清理
    async with ClaudeSDKClient(options=options) as client:

        # 第一轮对话
        await client.query("看看当前目录有什么文件")
        async for msg in client.receive_response():
            if isinstance(msg, AssistantMessage):
                for block in msg.content:
                    if isinstance(block, TextBlock):
                        print(f"AI: {block.text}")

        # 第二轮对话(AI 记得上一轮的内容)
        await client.query("刚才看到的 py 文件,帮我检查一下代码质量")
        async for msg in client.receive_response():
            if isinstance(msg, AssistantMessage):
                for block in msg.content:
                    if isinstance(block, TextBlock):
                        print(f"AI: {block.text}")

anyio.run(main)

关键区别: - query() 每次调用都是独立的 - ClaudeSDKClient 的多次 client.query() 共享对话历史

交互式命令行

做一个真正的"对话式 DevOps 助手":

bash
import anyio
from claude_agent_sdk import (
    ClaudeSDKClient, ClaudeAgentOptions,
    AssistantMessage, ResultMessage, TextBlock, ToolUseBlock
)

async def devops_chat():
    options = ClaudeAgentOptions(
        system_prompt="""你是 DevOps 助手。你能帮用户:
- 执行命令和检查系统状态
- 分析日志和代码
- 管理 Git 和部署
请用中文回复。""",
        allowed_tools=["Bash", "Read", "Write", "Grep"],
    )

    print("🤖 DevOps 助手已启动!输入 'quit' 退出。\n")

    async with ClaudeSDKClient(options=options) as client:
        while True:
            user_input = input("你: ").strip()
            if user_input.lower() in ['quit', 'exit', 'q']:
                print("👋 再见!")
                break
            if not user_input:
                continue

            await client.query(user_input)

            async for msg in client.receive_response():
                if isinstance(msg, AssistantMessage):
                    for block in msg.content:
                        if isinstance(block, TextBlock):
                            print(f"\n🤖 {block.text}")
                        elif isinstance(block, ToolUseBlock):
                            print(f"  🔧 {block.name}")
                elif isinstance(msg, ResultMessage):
                    if msg.total_cost_usd and msg.total_cost_usd > 0:
                        print(f"  💰 ${msg.total_cost_usd:.4f}")
            print()

anyio.run(devops_chat)

高级功能

动态切换权限

code
async with ClaudeSDKClient(options=options) as client:
    # 分析阶段:只读权限
    await client.set_permission_mode("default")
    await client.query("分析一下这个错误日志")
    async for msg in client.receive_response():
        pass

    # 修复阶段:开放编辑权限
    await client.set_permission_mode("acceptEdits")
    await client.query("帮我修复刚才分析出的问题")
    async for msg in client.receive_response():
        pass

这在 DevOps 中很有用:先让 AI 分析(只读),确认没问题后再让它修改(读写)。

动态切换模型

python
async with ClaudeSDKClient(options=options) as client:
    # 简单任务用便宜模型
    await client.set_model("haiku")
    await client.query("列出所有 Python 文件")
    async for msg in client.receive_response():
        pass

    # 复杂任务用强力模型
    await client.set_model("sonnet")
    await client.query("深入分析这些文件的架构设计")
    async for msg in client.receive_response():
        pass

文件检查点和回滚

code
async with ClaudeSDKClient(options=options) as client:
    # AI 做了一些修改
    await client.query("重构这个函数")
    async for msg in client.receive_response():
        # 记住这条消息的 ID
        if isinstance(msg, AssistantMessage):
            checkpoint_id = msg.uuid
            pass

    # 发现改坏了?回滚!
    await client.rewind_files(checkpoint_id)
    print("文件已回滚到修改前的状态")

rewind_files() 是 DevOps 场景的救命稻草——AI 改坏了文件,一键恢复。

中断正在执行的任务

code
async with ClaudeSDKClient(options=options) as client:
    await client.query("跑一个很长的测试")

    # AI 正在执行...
    # 你发现它在做错误的事情

    await client.interrupt()  # 紧急中断!
    print("已中断 AI 的操作")

检查 MCP 服务器状态

code
async with ClaudeSDKClient(options=options) as client:
    status = await client.get_mcp_status()
    print(f"MCP 服务器状态: {status}")
    # 确认你的自定义工具是否正常运行

Client 的完整 API 一览

code
async with ClaudeSDKClient(options=options) as client:
    # 核心对话
    await client.query("你的问题")              # 发送消息
    async for msg in client.receive_response():  # 接收回复
        pass

    # 控制
    await client.interrupt()                     # 中断执行
    await client.set_permission_mode("mode")     # 切换权限
    await client.set_model("model")              # 切换模型

    # 状态管理
    await client.rewind_files(msg_id)            # 回滚文件
    status = await client.get_mcp_status()       # MCP 状态

本课小结

  • ClaudeSDKClient 支持多轮对话,适合交互式 DevOps 工作
  • async with 确保资源正确清理
  • 动态切换权限:先分析(只读)→ 再修改(读写)
  • 动态切换模型:简单任务用便宜模型,复杂任务用强模型
  • rewind_files() 回滚文件,interrupt() 紧急中断

课后练习

  1. 跑一下上面的交互式命令行 DevOps 助手
  2. 试试 set_permission_mode() 在 "default" 和 "acceptEdits" 之间切换
  3. 让 AI 修改一个文件,然后用 rewind_files() 回滚,验证文件恢复了

沿着当前专题继续,或返回课程目录重新整理阅读顺序。

返回课程目录