首页
/ Claude Cookbooks 研究型 Agent 架构解析:基于 Claude Agent SDK 的 WebSearch 与 Read 自主研究循环

Claude Cookbooks 研究型 Agent 架构解析:基于 Claude Agent SDK 的 WebSearch 与 Read 自主研究循环

2026-09-07 17:54:32作者:范靓好Udolf

本篇文章围绕 claude-cookbooks 仓库中 research_agent/architecture_diagram.md 记录的架构与通信流程展开,结合同一目录下的 agent.py 实现与配套教程 notebook,逐层拆解一个基于 Claude Agent SDK 构建的自主研究型 Agent:它如何通过 WebSearchRead 两个内置工具,在"思考—调用工具—获得结果"的循环中自主完成信息搜集与多模态分析。读完本文,你将掌握该 Agent 的组件划分、运行时消息流向、关键配置参数的含义,以及如何把示例原型演进为可复用的生产模块。

为什么研究型 Agent 需要一张架构图

研究型任务是典型的"答案不在输入里"的 Agent 场景:用户只抛出一个问题,真正的答案需要 Agent 主动与外部系统(搜索引擎、文档、图表、PDF)交互才能获得。更重要的是,搜索路径无法预先编排——是先查公司财报还是先看监管文件,取决于调查过程中不断涌现的新信息。这与固定步骤的工作流自动化有本质区别。

正因如此,在 claude-cookbooks 中,research_agent 目录专门用一份 architecture_diagram.md 来固化这套系统的两大视图:静态组件架构(系统由哪些角色和工具组成)与动态通信流程(一次问答如何在各组件间流转)。理解这两张图,就等于拿到了阅读 agent.py 源码与 00_The_one_liner_research_agent.ipynb 教程的导航图。

一、组件架构:User → Agent → Tools 的三层结构

architecture_diagram.md 用 mermaid 的 graph TD 记录了系统的顶层结构,原文如下:

graph TD
    User[User] --> Agent[Research Agent]
    Agent --> Tools[Tools]

    Tools --> WebSearch[WebSearch]
    Tools --> Read[Read Files/Images]

    style Agent fill:#f9f,stroke:#333,stroke-width:3px
    style Tools fill:#bbf,stroke:#333,stroke-width:2px

这张图划分出三层角色,可以在源码中找到一一对应:

图中节点 架构职责 仓库中的对应实现
User 研究需求的发起者,提出 Query、接收最终 Answer Notebook 中的调用方,如教程中的 send_query("What is the Claude Code SDK? ...")
Agent(Research Agent) 持有系统提示词与上下文,负责规划、决策与综合 agent.py 中由 ClaudeSDKClient 驱动的研究 Agent
Tools Agent 与外部世界交互的接口层,按需调度下方具体工具 agent.py 中的 allowed_tools=["WebSearch", "Read"]
WebSearch 联网搜索,负责信息采集 Claude Agent SDK 内置 WebSearch 工具
Read(Read Files/Images) 读取本地文件与图片等非文本内容,负责多模态分析 教程中用它分析 projects_claude.png 图表

图中用加粗描边高亮 AgentTools,意在强调:这是整套系统中唯一真正参与"运行时决策"的两部分,工具层把模型能力与外部信息源解耦——Agent 只负责"想清楚下一步做什么",工具负责"把事做成"。

Agent 组件的源码化理解

图中的 Research Agent 节点,在源码里体现为一次完整的 ClaudeSDKClient 会话。从 agent.py 可以看到其核心配置:

options = ClaudeAgentOptions(
    model=model,
    allowed_tools=["WebSearch", "Read"],
    continue_conversation=continue_conversation,
    system_prompt=RESEARCH_SYSTEM_PROMPT,
    max_buffer_size=10 * 1024 * 1024,  # 10MB buffer for handling images and large responses
)

async with ClaudeSDKClient(options=options) as agent:
    await agent.query(prompt=prompt)
    async for msg in agent.receive_response():
        # ...逐条消费消息流

对照 architecture_diagram.md 中 Agent --> Tools 这条边,它落在代码里就是 allowed_tools 这个白名单——它划定了图中 Tools 节点实际包含哪些具体能力,也决定了 Agent 的自主程度边界。

模型与提示词:塑造 Agent 的专业行为

agent.py 默认选用 claude-opus-4-6 作为研究主力模型,同时通过系统提示词注入"研究纪律":

RESEARCH_SYSTEM_PROMPT = """You are a research agent specialized in AI.

When providing research findings:
- Always include source URLs as citations
- Format citations as markdown links: Source Title
- Group sources in a "Sources:" section at the end of your response"""

这一段提示词在架构图中的位置是"Agent 节点内部的行为约束":它不改变组件连接关系,但决定了 Agent 输出质量——强制附带来源 URL、统一引用为 markdown 链接、在回答末尾汇总 Sources: 区块,保证研究结果可溯源、可验证。

二、通信流程:Think → Search/Read → Results 的循环直到完成

architecture_diagram.md 的第二张图用 sequenceDiagram 刻画了一次问答的动态过程:

sequenceDiagram
    participant User
    participant Agent
    participant Tools

    User->>Agent: Query

    loop Until Complete
        Agent->>Agent: Think
        Agent->>Tools: Search/Read
        Tools-->>Agent: Results
    end

    Agent-->>User: Answer

这是理解研究 Agent 运行机制最关键的一张图,它揭示了三个要点:

  1. Research 是循环而非单次调用loop Until Complete 意味着 Agent 不是"一次搜索、一次回答"的线性流水线,而是自主决定"何时搜索、搜索什么、是否已有足够信息收尾"。
  2. 决策完全在 Agent 内部发生Agent->>Agent: Think):模型依据已有上下文判断下一步动作,工作流不在代码中写死。
  3. User 只在头尾出现:用户发起 Query、接收最终 Answer,中间的工具调用与思考环节对用户不可见(或通过活动流可视化展示)。

运行时如何观察到这条消息流

在 Claude Agent SDK 中,这条时序图对应的是 receive_response() 产生的消息流。教程 00_The_one_liner_research_agent.ipynb 里给出了一次真实运行的观察结果:

🤖 Using: WebSearch()
🤖 Using: WebSearch()
🤖 Using: WebSearch()
✓ Tool completed
✓ Tool completed
✓ Tool completed
🤖 Thinking...

User -> Agent: Query 对应调用 agent.query(prompt=...)Agent->>Tools 对应流中携带工具调用块的 Assistant 消息;Tools-->>Agent: Results 对应携带 tool_result 的 User 消息;Agent->>Agent: Think 对应没有工具调用的纯思考消息。loop Until Complete 的终止条件对应流末尾的 ResultMessage(含 result 字段与回合数、耗时、成本等统计信息)。

循环的可视化基础设施

为了让"循环中的每一步"可被人类感知,research_agent 复用了 utils/agent_visualizer.py 提供的一组可视化 API:

  • print_activity(msg):实时打印每个消息块对应的活动,如 🤖 Using: WebSearch()✓ Tool completed,按消息类型(Assistant/User)分流处理;
  • visualize_conversation(messages):把完整消息列表渲染成对话时间线——Jupyter 环境输出带分类配色的 HTML,终端环境自动回退为纯文本表格字符风格(box-drawing);
  • display_agent_response(messages):把最终回答渲染成样式化的 HTML 卡片,末尾的统计栏会给出 Turns、Tokens、Cost、Duration;
  • reset_activity_context():每个新会话开始前清理全局活动上下文。

其中 visualize_conversation 在 Jupyter 与终端间的自动切换,通过探测 ZMQInteractiveShell 判断是否运行于 Notebook 环境。终端回退视图还会针对 SystemMessage(回显 session_id)、AssistantMessage(区分文本块与工具调用块)、ResultMessage(聚合回合数、token、成本、耗时)分别排版。

三、两个核心工具的能力边界与使用规则

architecture_diagram.md 在 Tools 节点下挂出 WebSearchRead 两个工具,这是本架构中 Agent 能力的全部来源。

WebSearch:自主信息采集

WebSearch 让 Agent 无需预先批准即可联网搜索。它适合图论中描述的那种"信息不自洽"的任务:问题本身不含答案,必须经由外部搜索引擎补全。在首次演示中,Agent 面对"研究 AI agents 的最新趋势"这类开放问题时,会自主发起多次搜索(run 记录里连续出现三次 WebSearch),覆盖不同关键词角度后再综合成带引用的摘要。

Read:文件与图像的多模态分析

Read 把研究能力从纯文本扩展到图表、文档等视觉内容。Notebook 中演示了完整链路:Agent 先用 Glob 定位图表文件 projects_claude.png,再用 Read 读取图片完成"哑铃图"解读——逐条提取个人项目、创业工作、企业工作、教育学习等类别在 Claude.ai 与 Claude Code 两个平台上的占比差异,再自动发起多轮 WebSearch 验证这些数据点与行业报道、Anthropic 官方报告的一致性,最后输出带 Sources 区块的验证结论。这恰好是时序图中 loop Until Complete 的完整复现:Read 结果又触发新的搜索,新的搜索又驱动更深层的综合。

工具权限模型:allowed_tools 决定自主程度

从 Notebook 中对权限模型的解释可以看出,allowed_tools=["WebSearch", "Read"] 的语义并非简单的"能用哪些工具":

  • allowed_tools 中的工具——Agent 可自由使用、无需请求批准,这是自主研究的前提;
  • 其他可用工具——默认需要批准才能调用;
  • 只读类工具(如 Read)——默认放行;
  • disallowed_tools——彻底移出模型上下文,连"提出使用请求"的机会都没有。

配置越窄、Agent 越受约束;配置越宽、Agent 越自主。研究型场景正是利用这一机制让模型在"搜索—思考—再搜索"的开放循环中自行决策。

四、从无状态到有状态:架构图中的会话演进

architecture_diagram.md 描述的组件关系在不同会话模式下都成立,但 research_agent 的实际用法覆盖了两种会话语义,值得区分:

无状态 query():一次性研究

教程中的"一行研究 Agent"使用 query()

from claude_agent_sdk import ClaudeAgentOptions, query

messages = []
async for msg in query(
    prompt="Research the latest trends in AI agents and give me a brief summary and relevant citations links.",
    options=ClaudeAgentOptions(model=MODEL, allowed_tools=["WebSearch"]),
):
    print_activity(msg)
    messages.append(msg)

query() 每次调用相互独立、无会话记忆。适合单发研究问题、并行处理互不相关的任务、需要全新上下文的场景。它的局限在于无法承接"先查 A,再基于 A 查 B"的递进式调查。

有状态 ClaudeSDKClient:多轮上下文继承

演进后的研究 Agent 改用 ClaudeSDKClient,通过 context manager 维护跨查询的会话状态:

from claude_agent_sdk import ClaudeSDKClient

messages = []
async with ClaudeSDKClient(
    options=ClaudeAgentOptions(
        model=MODEL,
        cwd="research_agent",
        system_prompt=RESEARCH_SYSTEM_PROMPT,
        allowed_tools=["WebSearch", "Read"],
        max_buffer_size=10 * 1024 * 1024,  # Increase to 10MB for image handling
    )
) as research_agent:
    # 第一次查询:用 Read 分析图表
    await research_agent.query("Analyze the chart in research_agent/projects_claude.png")
    async for msg in research_agent.receive_response():
        print_activity(msg)
        messages.append(msg)

    # 第二次查询:用 WebSearch 验证图表结论
    await research_agent.query(
        "Based on the chart analysis, search for recent news or data that validates or provides context for these findings. Include source URLs."
    )
    async for msg in research_agent.receive_response():
        print_activity(msg)
        messages.append(msg)

这里的关键是架构图中的 Agent 节点现在具备了"记忆":第二次查询能继承第一次读图得到的图表结论,从而提出真正有依据的验证请求——这正是 stateless 查询做不到的。第二次查询的运行记录里可以看到它在没有搜索指令的前提下自动发起四条 WebSearch,印证了"研究路径在探索中涌现"的设计意图。

五、生产化封装:send_query 与消息解析

统一入口 send_query

架构图中 Agent 节点对应的可复用逻辑,被封装在 agent.pysend_query() 中。它把整套会话编排收敛为一个异步函数,对外暴露四个可控参数:

参数 作用 默认值
prompt 要发送的研究问题 必填
activity_handler 活动回调,可替换为自定义实现(如日志、WebSocket 推送) print_activity
continue_conversation 置为 True 时继续上一段对话,而不是开启新会话 False
model 指定模型 claude-opus-4-6
display_result 完成后是否渲染最终结果卡片;程序化集成时置为 False 只取文本 True

关于 activity_handler,源码注释明确说明同时支持同步与异步两种回调:同步处理器(如 print_activity)适合简单控制台输出,异步处理器适合需要 WebSocket/网络 I/O 的 Web 应用,实际项目中按需二选一。

消息解析辅助函数 get_activity_text

对于想要自定义监控的用户,agent.py 提供 get_activity_text(msg):按消息类名判断属于 Assistant 还是 User,前者提取首个内容块的工具名(输出 🤖 Using: WebSearch()),无内容块则返回"Thinking...",后者标记工具完成。若消息类型不适配则安全返回 None,异常被捕获后静默降级。

多轮延续与结果控制

模块化之后,多轮对话只需重复调用 send_query 并打开 continue_conversation

result1 = await send_query("What is Anthropic? Only do one websearch and be concise")

# 继续同一段对话,追问更细
result2 = await send_query(
    "What are some of their products?",
    continue_conversation=True,
)

第二次回答直接引用了第一次搜索结果中 Anthropic 的定位信息来列举其产品线——continue_conversation=True 让 Agent 记住"我们刚才聊过什么"。display_result=False 则用于纯程序化集成,此时只返回文本结果而跳过 HTML 渲染,便于把 agent 嵌进其他应用。

六、实践中的注意事项:上下文窗口与缓冲区

architecture_diagram.md 不会画出的"隐藏细节",恰恰是运行中最常踩的坑。当研究涉及图片或超大输出时,会触发如下错误:

Fatal error in message reader: Failed to decode JSON: JSON message exceeded maximum buffer size of 1048576 bytes

原因是 max_buffer_size 默认仅 1 MB(1,048,576 字节),而图片在消息中会以 base64 编码传输,体积显著膨胀:约 200KB 的磁盘图片编码后可达 270KB 以上,叠加消息开销便容易击穿默认上限。因此 research_agent 将 max_buffer_size 提到 10 MB。经验法则:典型多模态工作取 10MB;处理大型文档时可继续调高;如果单张图片并非必需,用文字描述或缩略图替代更节省。

七、在仓库中完整跑通这套架构

环境准备

claude_agent_sdk/README.md 的指引准备环境(对应本仓库的 Python 侧目录):

cd claude_agent_sdk
uv sync
uv run python -m ipykernel install --user --name="cc-sdk-tutorial" --display-name "Python (cc-sdk-tutorial)"

同时在 .env 中配置 ANTHROPIC_API_KEY=your_key_here。依赖与 Python 版本约束记录在 pyproject.toml(要求 Python ≥ 3.11 且 < 3.13,依赖 claude-agent-sdk>=0.1.51python-dotenv 等)。

三种运行形态对应架构图的三层视角

若要在 Notebook 之外独立导入该模块,README 建议从 claude_agent_sdk/ 目录运行,或执行 uv pip install -e . 以可编辑模式安装。

总结:架构图与源码的相互印证

回顾 architecture_diagram.md 的两张图,可以总结出这套研究 Agent 架构的三个核心设计取舍:

  • 能力收敛:工具面收敛为 WebSearch + Read,一个管联网信息、一个管本地多模态内容,恰好覆盖研究任务的两大信息源;
  • 决策自主loop Until Complete 明确表达"探索路径不可预编程"——何时搜索、搜几次、何时收尾,全部交由模型基于上下文判断,通过 allowed_tools 白名单放权、通过系统提示词约束输出(强制引用与 Sources 区块);
  • 会话可选:同一组件架构同时支持无状态 query() 与有状态 ClaudeSDKClient,前者用于独立快速问答,后者用于依赖前序发现的递进式调研。

理解了这份架构文档,再回头读 agent.py 与配套教程,代码中的每个配置项(modelallowed_toolssystem_promptmax_buffer_sizecontinue_conversation)就都回到了它在架构图上的位置。这套"研究型 Agent"打下的基础,也是 claude-cookbooks 后续进阶方向(chief of staff 多 Agent 编排、observability 外部系统接入、site reliability 读写修复等,见 claude_agent_sdk/README.md 的教程总览)共同的起点。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388