SurfSense Walmart 子代理解析:多代理架构下的商品数据采集与评论挖掘实战
【免费下载链接】SurfSenseOpen-source NotebookLM alternative. Research the open web with live data(Reddit, YT, IG, TikTok, Indeed, Google Search, Maps etc) through one platform, API or MCP server. Join our Discord: https://discord.gg/ejRNvftDp9项目地址: https://gitcode.com/GitHub_Trending/su/SurfSense
导读
Walmart 是美国最大的零售电商平台之一,其商品详情、价格、库存与海量用户评论是产品调研、竞品分析和价格追踪的重要数据源。SurfSense 以多代理(multi-agent)架构组织智能体系统:一个 supervisor 代理负责拆解用户问题,再把具体任务委派给按数据源划分的专业子代理。本文围绕 walmart/system_prompt.md 展开,完整讲解 Walmart 子代理的职责边界、可用工具(walmart_scrape与walmart_reviews)、执行剧本、输出契约与失败策略,并结合作品仓库中的能力注册、输入/输出 Schema 与执行器源码,从参数到计费逐层剖析其底层实现。读完本文,你将掌握 SurfSense 中 Walmart 数据采集子代理的完整工作原理,以及如何配置walmart_scrape、walmart_reviews实现商品发现、详情抓取与深度评论挖掘。
一、子代理定位:专业化的数据源分工
1.1 从 supervisor 到专业子代理的委派模型
在 SurfSense 的多代理聊天架构中,Walmart 子代理位于 subagents/builtins/walmart/ 目录。根据 system_prompt.md 第 1-2 行的定义:
You are the SurfSense Walmart sub-agent. You receive delegated instructions from a supervisor agent and return structured results for supervisor synthesis.
即:Walmart 子代理不直接面向终端用户,而是接收 supervisor 代理委派的指令,完成数据采集后把结构化结果交还给 supervisor 做最终综合。这种"一个 supervisor + 多个数据源专业子代理"的分工,保证了商品数据、搜索结果、社媒内容等不同来源的采集逻辑彼此隔离、各自专注。
与 Walmart 子代理并列的还有 amazon、google_search、reddit、indeed、youtube、tiktok、instagram、google_maps、web_crawler 等子代理,Walmart 子代理只是其中专注于美国 Walmart 公开数据的那个。
1.2 子代理的组装方式
agent.py 中build_subagent()展示了子代理如何被组装:
- 通过
read_md_file(__package__, "system_prompt")读取本目录下的 system_prompt.md 作为系统提示词; - 通过
read_md_file(__package__, "description")读取 description.md 作为子代理路由描述; - 通过
load_tools()装配walmart_scrape与walmart_reviews两个能力工具; - 最后调用
pack_subagent(...)打包为SurfSenseSubagentSpec,交给 deepagents 运行时调度。
从源码结构看,每个 builtin 子代理都遵循完全相同的目录约定(agent.py+description.md+system_prompt.md+tools/),因此 system_prompt 是子代理行为定义的核心载体,而 description.md 则决定了 supervisor 在什么场景下把任务路由给这个子代理(例如"find X on Walmart"、"Walmart price of X"、"reviews for this Walmart product"等触发语)。
1.3 职责边界(out_of_scope)
system_prompt.md 用<out_of_scope>明确划定了边界:
- 不做通用网页搜索——那是 Google Search 专业子代理的职责;
- 不读取或提取任意非 Walmart 页面——这类 URL 应返回给 web crawling 专业子代理;
- 不生成交付物、不做 connector 变更——子代理只返回 findings,由 supervisor 决定后续动作;
- 只处理 Walmart 公开匿名数据——绝不接触需要登录或卖家账户的内容。
这条边界是理解整个多代理体系的关键:每个子代理都是"单数据源专家",跨源需求必须回到 supervisor 层面协调。
二、可用工具:两个 verb 一个读者
2.1 工具清单
system_prompt.md 的<available_tools>声明了三个工具:
| 工具 | 用途 |
|---|---|
walmart_scrape | 商品详情与搜索/类目列表抓取 |
walmart_reviews | 针对单个商品的分页深度评论抓取 |
read_run/search_run | 免费读取已存储的抓取输出 |
前两个工具来自 tools/index.py:它把WALMART_SCRAPE与WALMART_REVIEWS两个能力(_CI_VERBS)通过build_capability_tools()包装成 LangChain 工具暴露给模型,并定义NAME = "walmart"与一个空的RULESET。也就是说,子代理可用的核心动词完全由 capabilities 层的注册表驱动,而不是在子代理代码里硬编码。
2.2 工具使用策略(playbook)
<playbook>提供了具体的操作剧本:
- 商品发现:调用
walmart_scrape并传入search_terms,例如["air fryer"]; - 指定商品:在
urls中传入 Walmart 商品 URL(/ip/...)或搜索/类目/浏览 URL; - 加速列表抓取:设置
include_details=false只返回卡片级结果,不逐个打开商品详情页; - 采样评论:
walmart_scrape默认携带页面上的小规模评论样本(include_reviews_sample=true);评论无关时可关闭; - 深度评论挖掘:使用
walmart_reviews传入商品urls或数字item_ids(usItemId),按需调高max_reviews并设置sort_by(most-recent、most-helpful、rating-high、rating-low); - 批量合并:把多个 URL 或搜索词合并到一次调用,而不是发起多次单源调用;
- 结果读取:大结果被截断时用
read_run/search_run分页读取(见<include snippet="run_reader"/>); - 对比请求:结合会话中已有的历史工具结果,报告具体 delta(价格涨跌、评分变化、库存变化)。
2.3 存储结果的分页读取(run_reader)
run_reader.md 被以<include snippet="run_reader"/>的方式注入系统提示词,其要点是:
- 大型工具结果会被完整存储,只向模型展示以
run_<uuid>结尾的预览; - 禁止重复调用工具来查看更多内容,而应使用
read_run(ref, offset, limit)分页读取(每行是一个 JSON 结果项),或用search_run(ref, pattern)做正则检索; - 若单个结果项本身超出响应长度,用
char_offset在该行内部继续偏移读取(截断提示会给出下一个值)。
这套机制既控制了上下文窗口的消耗,又保证了结果的完整性——对包含数百条商品/评论的抓取尤其重要。
三、能力注册与输入契约:walmart_scrape 详解
3.1 能力注册
Walmart 的抓取能力在 capabilities/walmart/scrape/definition.py 中注册为名为walmart.scrape的Capability:
- name:
walmart.scrape - description:抓取公开的 Walmart 商品详情、搜索/类目列表、价格、卖家、变体、库存与页面评论样本
- billing_unit:
BillingUnit.WALMART_PRODUCT(按商品计费) - docs_url:
/docs/connectors/native/walmart
能力注册后即可被子代理通过build_capability_tools()复用,这也是 tools/index.py 能直接引用WALMART_SCRAPE的原因。
3.2 输入参数(ScrapeInput)
scrape/schemas.py 用 Pydantic 定义了ScrapeInput,各字段如下:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
urls | list[HttpUrlStr] | [] | Walmart 商品/搜索/类目/浏览 URL,最多 20 个 |
search_terms | list[str] | [] | 搜索词,最多 20 个,例如"air fryer" |
max_items | int | 10 | 每个来源最多返回的商品数,范围 1-100 |
include_details | bool | True | 是否打开每个商品页抓详情;设为False只返回卡片级结果 |
include_reviews_sample | bool | True | 是否附带页面上的评论样本;评论无关时关闭 |
关键校验规则(_require_source,第 27-35 行):
urls与search_terms至少提供一个,否则抛错 "Provide at least one URL or search term.";- 两者数量之和不得超过
MAX_WALMART_SOURCES = 20。
底层实现方面,start_urls()方法会把每个搜索词构造成https://www.walmart.com/search?q=<quote_plus(term)>搜索 URL,与直接传入的urls合并后作为抓取起点;estimated_units则按search_products + direct_products计算最坏情况下的商品量,并封顶在MAX_WALMART_RESULTS = 1000。
3.3 输出与计费(ScrapeOutput)
ScrapeOutput包含一个items: list[ProductItem]列表。根据 description.md,ProductItem携带的结构化字段包括:标题、item id(usItemId)、品牌、价格与划线价、星级评分与评论数、库存、图片、特性(features)、卖家与商品变体。
计费上,billable_units属性只统计成功的商品条目——带有error标记的条目不计费(第 58-65 行)。同时ScrapeOutput中的错误会以结构化 per-input 的形式返回,便于子代理定位失败来源。
四、深度评论挖掘:walmart_reviews 详解
4.1 能力注册与计费模式
capabilities/walmart/reviews/definition.py 注册了walmart.reviews:
- billing_unit:
BillingUnit.WALMART_REVIEW——按条评论计费,对应配置项WALMART_MICROS_PER_REVIEW(定义文件第 1-2 行注释明确说明); - description:抓取深度分页的公开 Walmart 商品评论,包含评分、正文、作者、已验证购买标记、图片与卖家回复。
4.2 输入参数(ReviewsInput)
reviews/schemas.py 定义的ReviewsInput:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
urls | list[HttpUrlStr] | [] | 商品 URL(/ip/...)或评论页 URL,最多 20 个 |
item_ids | list[str] | [] | 数字型商品 id(usItemId),最多 20 个 |
max_reviews | int | 200 | 每商品最多返回的评论数,范围 1-5000(每页 10 条) |
sort_by | Literal | most-recent | 排序:most-recent/most-helpful/rating-high/rating-low |
校验规则:urls与item_ids至少提供一个。两种输入最终都会解析为评论页所依赖的usItemId(见sources()方法,第 50-52 行)。
estimated_units的计算是(urls 数量 + item_ids 数量) × max_reviews,这正好印证了 system_prompt 中"Reviews are billed per review, so keepmax_reviewsto what the task actually requires"的告诫——max_reviews直接线性放大计费量,代理应只按任务实际需要设置。
4.3 输出与计费(ReviewsOutput)
ReviewsOutput.items直接复用抓取层的ReviewItem(评论正文、评分、作者、验证购买标记、图片、卖家回复),按抓取器的发射顺序排列。billable_units同样每条成功返回的评论 = 一个计费单位,错误条目不计费。
五、工具策略与失败处理
5.1 工具使用策略(tool_policy)
system_prompt.md 的<tool_policy>强调三点:
- 只用
<available_tools>中声明的工具; - 只报告工具输出中真实存在的结果——严禁虚构标题、item id、价格、评分或评论;
- 参数合法性约束:
walmart_scrape至少提供urls或search_terms之一;walmart_reviews至少提供urls或item_ids之一——这两条约束与前述 Pydantic 校验一一对应。
5.2 失败策略(failure_policy)
| 场景 | 返回 |
|---|---|
| 请求信息不足(无可用搜索词、URL 或 item id) | status=blocked+missing_fields指明缺失字段 |
| 工具调用失败 | status=error+ 简明的恢复建议next_step |
| 无有效证据 | status=blocked+ 更窄的查询建议或仍需要的范围 |
5.3 安全要求(safety)
- 证据不完整或相互矛盾时,明确报告不确定性;
- 绝不把未经证实的说法当作事实陈述。
六、输出契约:结构化 JSON 交付
6.1 返回格式
<output_contract>要求子代理只返回一个 JSON 对象,禁止输出 Markdown 或散文:
{ "status": "success" | "partial" | "blocked" | "error", "action_summary": "string", "evidence": { "findings": "string[]", "sources": "string[]", "confidence": "high" | "medium" | "low" }, "next_step": "string | null", "missing_fields": "string[] | null", "assumptions": "string[] | null" }6.2 路由专属规则
evidence.findings:最多 10 条,每条必须是描述一个独立商品、评论主题或差异(delta)的单句;不得粘贴原始抓取载荷;evidence.sources:最多 10 个 URL,每条 finding 对应一个(如适用),且每个 URL 只列出一次。
6.3 通用契约(output_contract_base)
output_contract_base.md 定义了所有子代理通用的状态机规则:
status=success→next_step=null、missing_fields=null;status=partial|blocked|error→next_step必须非空;next_step只能用于你自己无法完成的动作——如果下一步是自己工具的调用(如用read_run/search_run分页读取存储结果、或调整参数重跑),应立即执行并返回改进后的结果,而不是返回partial;status=blocked且因缺失必要输入 →missing_fields必须非空;assumptions:记录你对用户意图的推断;无推断时为null;- 从抓取运行中引用 finding 时,应把该运行标注的
[n](工具结果中的 "Cite this scraper run as [n]")原样附加到 finding 文本,保证引用在最终答案中可追溯;不得伪造标签。
这套契约的价值在于:它把子代理的产出从"自由文本"规约为机器可解析的结构,supervisor 可以直接消费findings/sources/confidence进行综合,也能根据status/next_step/missing_fields决定重试、追问或转入其他子代理,是多代理协作稳定性的关键保障。
七、应用场景与最佳实践
综合 description.md 与上述机制,Walmart 子代理典型应用于:
- 产品调研:按搜索词发现商品,抓取标题、价格、评分、卖家与变体;
- 价格追踪:对同一商品在会话中多次抓取,报告价格涨跌 delta;
- 目录富化:通过
item_id(usItemId)对已有目录条目补充详情; - 评论挖掘:用
walmart_reviews拉取大量评论,分析口碑主题。
最佳实践建议:
- 优先把多个搜索词/URL合并为单次调用,减少往返;
- 只需列表时设置
include_details=false,只需商品时关闭include_reviews_sample,控制成本与噪声; - 按任务实际需要设置
max_reviews,避免按条计费被线性放大; - 大结果用
read_run/search_run分页,不要重复触发抓取工具; - 对比类任务依赖会话内已有结果计算 delta,而非重新抓取。
八、总结
SurfSense 的 Walmart 子代理是一个典型的"单数据源专业子代理"实现:system_prompt.md 定义了职责、工具、剧本与输出契约;capabilities/walmart/ 下的 definition/schemas 提供了walmart.scrape与walmart.reviews两个可复用能力,包含严格的输入校验、批量上限(20 个来源、max_items1-100、max_reviews1-5000)与透明的按商品/按评论计费模型;tools/index.py 则把能力注册表无缝接入 deepagents 的工具体系。理解这套"提示词 + 能力注册 + Schema 契约"的组装方式,也就理解了 SurfSense 整个多代理平台可扩展的专业子代理架构。
【免费下载链接】SurfSenseOpen-source NotebookLM alternative. Research the open web with live data(Reddit, YT, IG, TikTok, Indeed, Google Search, Maps etc) through one platform, API or MCP server. Join our Discord: https://discord.gg/ejRNvftDp9项目地址: https://gitcode.com/GitHub_Trending/su/SurfSense
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考