SurfSense 多代理编排核心解析task 工具协议、专家子代理路由与 Receipt 验证机制【免费下载链接】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导读本文以 SurfSense 主代理main agent系统提示词中的task工具协议文档为主体深入剖析这个开源 NotebookLM 替代方案如何通过专家子代理specialist subagent完成知识库操作与第三方服务Slack、Notion、Jira、Gmail 等编排。读者将掌握task的单模式与批量模式调用规范、routing路由决策规则、以及基于Receipt的两路地面真值验证机制并看到这些协议在 task 工具实现 与 Receipt 契约 中的源码级落地。一、task工具在多代理架构中的定位SurfSense 的主代理supervisor遵循单一职责 委派原则主代理自身只暴露极小的工具面。从 主代理工具注册表 可以看到_MAIN_AGENT_TOOL_FACTORIES中只有create_automation与update_memory两个直接工具连接器集成、MCP 调用、内容交付报告、播客、视频演示等全部通过task委派给子代理完成。这正是 task 工具说明文档 的第一条定义task用于调用一个专家子代理specialist subagent专家子代理拥有工作区知识库knowledge-base操作以及已连接的第三方服务Slack、Notion、Jira、Gmail 等的专属工具每个子代理在隔离环境中运行拥有独立的工具栈与上下文并返回单个综合后的结果。从 系统提示词组装器 的注释可以看到最终系统提示词按固定顺序包含routing、specialists动态名册、tools垂直切片等区块而 工具指令块构建器 保证task工具始终被注入——因为deliverables与knowledge_base两个专家在连接器排除逻辑中永不缺席specialists名册非空是硬性契约。二、单模式single mode调用规范task的单模式只接受两个参数全部必须显式提供参数含义关键要求subagent_type要调用的专家名称必须匹配specialists名册中的条目见下文名册description完整任务提示词专家看不到当前线程必须把全部上下文、约束以及你期望拿回的内容写进去专家会用自己的输出格式回复不要替它规定格式description是全量自包含的任务提示词这是整个协议最重要的心智模型子代理与父线程之间不存在共享上下文任何依赖线程历史的信息如果不写进description专家就无从得知。单模式的标准用法示例来自 example.mduser: Save these meeting notes to my KB: … → task(subagent_typeknowledge_base, descriptionSave the notes below to a new document under /documents/notes/. Pick a sensible title and folder; tell me the path you used.\n\nnotes…/notes)user: What did Maya say about the Q2 roadmap in Slack last week? → task(subagent_typemcp_discovery, descriptionIn Slack, find messages from Maya about the Q2 roadmap from the past week. Return the most relevant quotes with channel and timestamp.)注意第二个示例Slack 查询同样以纯文本description下发并明确要求返回带 channel 和时间戳的引用这就是专家用自己的格式回复的体现。三、批量模式batch mode多路并发扇出当单个用户请求会展开为 3 个或更多相互独立的专家调用时例如根据这份列表创建五个 issue应使用批量形状task(tasks[ {subagent_type: mcp_discovery, description: …child 1…}, {subagent_type: mcp_discovery, description: …child 2…}, … ])批量模式的协议约束来自 task 工具说明文档 与 路由规则tasks是{description, subagent_type}对象的数组与单模式参数互斥运行时在小型并发上限semaphore内并发执行子任务每个子任务对应一个ToolMessage块并以[task index]前缀标识父代理需逐个读取核对批量子任务不支持人类介入human-in-the-loop中断——某个子任务需要审批时会冒出错此时必须把该任务重新以非批量的task(...)调用单独派发1–2 个独立调用不需要批量形状直接发出两条并行task(...)调用即可。从 checkpointed_subagent_middleware 常量 可以看到批量扇出的运行时上限由环境变量控制环境变量默认值含义SURFSENSE_TASK_BATCH_CONCURRENCY3批量子任务并行度asyncio.gatherSemaphore设为1可等效串行SURFSENSE_TASK_BATCH_MAX_SIZE8单次批量task的最大子任务数作为防注入/失控循环的硬上限SURFSENSE_SUBAGENT_INVOKE_TIMEOUT_SECONDS300单个task调用的墙钟预算超时抛出SubagentInvokeTimeoutError0关闭SURFSENSE_SUBAGENT_BILLABLE_THRESHOLD15单轮累计调用软阈值超过后运行时注入一次性警示 ToolMessage 让编排器收尾0关闭批量扇出的完整示例来自 routing.mduser: Create issues in Linear for each of these five bugs: list → task(tasks[ {subagent_type: mcp_discovery, description: In Linear, create an issue titled bug 1 … Return the issue URL.}, {subagent_type: mcp_discovery, description: In Linear, create an issue titled bug 2 … Return the issue URL.}, … ]) Read back the [task 0]…[task 4] blocks in the combined ToolMessage and verify each via its Receipts verifiable_url per the verification teaching before confirming to the user.四、路由规则何时委派、如何并行、如何串行task的具体调用时机、频率与作用域规则统一存放在routing区块即 routing.md。主代理有两条执行通道必须选择真正拥有该工作的那条绝不能用一条通道去模拟另一条。4.1 直接工具自己调用update_memory维护持久记忆write_todos当一轮任务跨越多个专家或步骤时维护结构化计划在每个task调用之前标记in_progress、返回后标记completed单步请求跳过。4.2task路由决策要点一个专家一个task调用单个调用只针对一个专家该专家只拥有自己领域的工具超出领域的任务不会被执行并行化独立工作两条task调用互不引用对方输出且指向不同专家或同一专家但范围不重叠如读取两个不相关路径时应作为并行调用发出依赖工作跨轮次串行一个专家的输出必须作为另一个专家输入时如先在 KB 找到路线图再邮件给 Maya在连续轮次中调用先把第一个结果烘焙进第二个的提示词并用write_todos跨轮次维持计划同一专家内捆绑步骤读 写 总结应放进同一个任务提示词完整指令放任务提示词内专家看不到线程不要假装知道专家数据源内容调用专家并使用它返回的结果。4.3 领域分工经验法则routing还沉淀了若干领域分工规则Search 负责发现crawler 负责阅读搜索结果只是指针而非来源答案在页面本体时少量已知 URL 用task(web_crawler, …)maxCrawlDepth0抓取整站/大量页面则带更高深度抓取公开事实能被工具检索就必须检索后回答并引用而不是甩一个 URL受众情绪去平台找社区讨论找 Reddit、视频内容找 YouTube、短视频趋势找 TikTok、实体店评论找 Google Maps、零售产品评价找 Amazon/Walmart——平台专家返回的是结构化的对话本身线下实体找 Maps开放网络找 Search无实体门店的实体纯线上公司、软件厂商、出版物用 SearchN 列表按独立实体计数同一品牌/母组织的多个分支、门店、子页面只算一个实体网站域名是所有权信号不足 N 时诚实扩量不够就交付更短列表并附一行说明——诚实的 10 条胜过注水的 15 条完整数据集落成文件而非聊天几百行数据用 web_crawler 的export_runCSV 工具保存回报工作区路径与行数主代理没有文件系统工具工作区内任何读写、编辑、移动、搜索都走task(knowledge_base, …)。五、专家名册specialists动态生成的实时阵容task的subagent_type必须匹配specialists名册。名册是动态生成的从 子代理注册表 中的SUBAGENT_BUILDERS_BY_NAMEL91-L109读取每个专家的description.md摘要并经 specialists 区块构建器 渲染为specialists块。当前名册共 17 个专家可分为四类类别专家说明内置内容交付deliverables报告、播客、视频演示、简历、图片生成Celery 后端知识库knowledge_base工作区 KB 的读写检索与文档操作主代理的唯一文件通道开放网络检索web_crawler、google_search、google_maps、youtube、reddit、instagram、tiktok、amazon、walmart、indeed对应各数据源的结构化抓取与检索连接的应用mcp_discovery托管 MCP 路由Slack、Jira、Linear、ClickUp、Airtable、Notion、Confluence、Gmail、Calendar 等文件连接器google_drive、dropbox、onedrive云盘文件操作丰富知识库记忆memory记忆维护构建时默认排除在task名册之外从 连接器映射常量 可看到两个关键机制SUBAGENT_TO_REQUIRED_CONNECTOR_MAPL31-L61每个专家声明其所需的连接器 tokenamazon/deliverables/knowledge_base/web_crawler等声明frozenset()永不因连接器缺失被排除而mcp_discovery采用 any-of 门控——工作区至少连接一个受支持应用时才出现在名册中LEGACY_SUBAGENT_ALIASESL67-L80旧的按连接器命名的子代理gmail、slack、jira等在 MCP 整合后保留为mcp_discovery的别名使旧 checkpoint 恢复时不至于硬失败。六、验证机制把自我报告当作假设而非事实这是task协议中最重要的安全设计。task 工具说明文档 的verification区块开宗明义子代理的自然语言回复是一种自我报告self-report不是证据。专家可能声称 Slack 消息已发布、Jira issue 已创建、报告已生成即便底层工具调用静默失败或被限流。要把 Done、Posted to #general、Created ENG-42 这类成功措辞当作假设而不是事实。6.1 两路地面真值信号信号一state[receipts]结构化回执每个变更类mutating工具都会向一个 append-only 列表发出结构化的Receipt。父代理supervisor不直接看到原始列表但每个子代理的output_contract会把匹配的 Receipt 放在evidence.receipts下回传。若子代理报告成功却没有一条statussuccess的匹配 Receipt则该操作没有发生——必须按失败处理并原样呈现给用户不要盲目重试异步交付物如播客/视频则为pending。Receipt的字段契约定义在 receipt.pyL74-L120make_receipt工厂L123-L154只保留非None字段字段含义示例route发出该回执的子代理deliverables、knowledge_base、mcp_discovery等type路由内的产物类型report/podcast/video_presentation/resume/imagepagemessageoperation操作动词generate、create/update/delete、send/post、write_file/edit_file/rm等statussuccess/pending/failed验证教学的关键字段external_id后端标识符报告行 id、Notionpage_id、Slackts、Gmailmessage_id、KBvirtualPathverifiable_url可供外部验证的 URLSlack permalink、Jira issue URL、Linear identifier URLGmail/KB 无公开 URL 时为Nonepreview产物摘要约 200 字符报告 markdown 开头、播客转写开头、图片缩略图 URLerror仅failed时填充后端返回的纯文本错误原因信号二task(web_crawler, …)外部确认当 Receipt 携带verifiable_url时主代理可以调用task(web_crawler, …)抓取该 URL在系统外部确认操作真实发生。适用于两类场景用户明确点名的高价值变更如给整个团队发启动邮件子代理自我报告与用户预期相互矛盾时。6.2 Receipt 状态语义务必逐条细读statussuccess变更已在后端提交。若存在verifiable_url且请求是高价值的可经task(web_crawler, …)外部确认否则信任 Receipt 并告知用户已完成。Celery 支撑的交付物播客、视频演示也落在这里——子代理已等待 worker 完成success意味着产物确实已保存。statusfailed该 Receipt 的error字段携带后端错误逐字呈现给用户只有在用户明确要求时才重路由或重试。statuspending目前罕见——当前变更类工具都会等待后端返回。若遇到告知用户工作已启动引用external_id/preview便于日后查找不要抓取、也不要重新派发同一个task(...)调用指望这次能完成。Receipt 状态是Literal[success, pending, failed]receipt.py L71验证教学依赖该字段做决策分支。6.3 验证机制的一个完整实战走查来自 routing.md 的发布启动公告到 #general示例This turn: task(mcp_discovery, In Slack, post launch announcement text to #general. Return the message permalink.) Next turn (with the receipts verifiable_url in hand): task(web_crawler, Crawl verifiable_url from the receipt and confirm the post is live; return what you find.) → confirm the post is live, then tell the user its up with the URL. If the reply has NO Receipt with statussuccess, treat it as a silent failure: surface the error verbatim, do not retry.同理example.md 中批量创建五个 Linear issue 后也要求Read back the[task 0]…[task 4]blocks in the combined ToolMessage and verify each via its Receiptsverifiable_url——先验证再向用户确认。七、底层实现task 工具的运行时骨架协议的运行时载体是 task_tool.py它是父代理与子代理在运行时的唯一会面点读取父代理暂存的 resume 值决定下发全新状态还是定向Command(resume...)并把子代理新的待处理中断重新抛回父代理。几个值得注意的实现事实墙钟超时预算_ainvoke_with_timeout对subagent.ainvoke施加SURFSENSE_SUBAGENT_INVOKE_TIMEOUT_SECONDS默认 300 秒的预算超时抛出SubagentInvokeTimeoutError并被合成成一个带statuserror语义的 ToolMessage提示以更窄的范围或不同专家重新路由——这与deliverables视频渲染等待渲染完成属有意为之而非卡死的区分相互印证HITL 桥接批量子任务不支持人类介入中断单任务则通过GraphInterrupt重新抛出待处理的中断给父代理由共享的 权限/ask 中间件 决策链路承接KB 写路径的唯一例外KB 文件工具调用会先发出statuspending的临时 Receipt真正的 DB 写入发生在回合结束时的KnowledgeBasePersistenceMiddleware随后把状态翻转为success或failed见 receipt.py 模块 docstring——这正是验证机制能覆盖 KB 写操作的原因。八、小结task是 SurfSense 多代理编排的枢纽协议通过单专家单调用、独立工作并行、依赖工作跨轮串行、3 路以上独立调用走批量扇出的路由纪律把知识库与第三方服务的操作安全地委派给隔离运行的专家子代理再通过Receipt双信号验证机制把子代理说了什么与系统实际发生了什么严格分离确保任何成功声明都有可审计的结构化证据支撑。理解这套协议就等于理解了 SurfSense 主代理如何在保持自身工具面极小的同时可靠地驾驭 17 个专家、数十个连接器与复杂的异步交付物。进一步阅读建议协议全文task 说明文档、task 示例、路由规则契约与注册Receipt 定义、子代理注册表、连接器映射常量运行时实现task 工具、并发/超时常量、系统提示词组装【免费下载链接】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),仅供参考