免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

SurfSense 多智能体主 Agent 的「拒绝与边界」:能力边界声明的设计与实现

SurfSense 多智能体主 Agent 的「拒绝与边界」:能力边界声明的设计与实现 SurfSense 多智能体主 Agent 的「拒绝与边界」能力边界声明的设计与实现【免费下载链接】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 开源开放网络研究平台中主 Agentmain agent系统提示词的refusal_and_limits能力边界声明。它是主 Agent 在与众多专家子 Agentspecialist subagents协同工作时最重要的行为护栏——定义什么该拒绝、什么该坦白、什么绝不能伪装。你将看到这条声明的完整条文、它在系统提示词中的组装位置、支撑它的运行时机制禁用工具契约、工具名修复、死循环检测、失败闭环以及它如何与tools、specialists、routing等模块协同构成一个可解释、可验证、不谎报能力的多智能体编排器。一、为什么主 Agent 需要一份「拒绝与边界」声明SurfSense 的主 Agent 是一个编排器orchestrator而不是万能执行器。从 identity/private.md 的定义看它的价值在于把每个请求路由给正确的专家子 Agent、跨来源综合证据、用数据说话而不是靠假设。这意味着主 Agent 自身暴露的工具面非常小绝大多数非平凡工作都要通过task工具委派给 Reddit、YouTube、Instagram、TikTok、Amazon、Walmart、Google Maps、Google Search、web_crawler、knowledge_base、mcp_discovery 等专家。工具面越小越容易发生越权承诺模型看到用户提到文件、连接器或存储就可能顺着训练数据里的习惯声称自己能读写文件、能访问某个第三方服务、能把结果保存起来。refusal_and_limits的存在正是要在大模型天然的讨好倾向与平台真实的工具边界之间钉下一道不可逾越的纪律红线。该声明位于 refusal_and_limits.md全文仅 11 行、4 条规则却与系统提示词的其它所有always-on模块KB-first、路由、引用、输出格式、提醒共同构成平台级安全网。下面逐条解读并逐一落到源码实现。二、逐条解读边界声明的四条纪律2.1 能力不在清单内 → 坦白并询问If a capability is not intoolsand no entry inspecialistscovers it, say so plainly and ask whether the user wants to proceed differently. Dont pretend you can do it.这是整份声明的总纲主 Agent 的能力表面被严格定义为tools直接工具specialists可委派的专家名单的并集。凡是不在这两个清单里的能力唯一的正确动作就是坦白做不到并询问用户是否换个方式继续绝不假装可以。这句话在系统提示词里不是孤立的口号。specialists由 specialists.py 在每次会话动态生成livetaskroster for this workspace即只有当前工作区实际可用的专家才会进入清单。而tools由 tool_instruction_block.py 按垂直切片渲染只包含真正注册到主 Agent 的直接工具。两个清单都是运行时真实工具面的快照因此不在清单里等于平台里没有这个能力模型无从狡辩。2.2 任务调用出错 → 如实上报并给出下一步If ataskcall errors or the specialist is unavailable, surface that to the user with a clear next step. Dont silently retry forever.第二条针对失败处理专家子 Agent 调用出错、或某个专家不可用时要把失败如实呈现给用户并给出清晰的下一步禁止无限静默重试。这与routing里的路由纪律以及task工具的verification教学一脉相承专家子 Agent 的自然语言回复是自报self-report不是证据每个变更类工具都会产出结构化的Receiptroute、type、operation、status、external_id、verifiable_url、preview写入state[receipts]。如果子 Agent 声称成功却没有statussuccess的 Receipt就要按失败处理、原文转述给用户不要盲目重试。statusfailed的 Receipt 携带后端真实错误应原样转述只有用户明确要求时才允许重新路由或重试。2.3 运行时禁用的工具 → 明说并寻找 task 替代Disabled tools announced by the runtime are off-limits even if documented elsewhere — say so and offer ataskalternative if one exists.第三条是禁用工具契约运行时宣布禁用的工具即使在其他文档里有说明也一律不可用。模型必须明说该工具被禁用并给出替代方案——如果某个专家能覆盖该能力就转用task否则直接说明工具不可用。这条规则在系统提示词里有精确的硬件支撑disabled_tools块。看 tool_instruction_block.py 的实现disabled_tools Disabled for this session: 工具名列表. Dont claim you can use them. If the user needs that capability, delegate with task when a specialist covers it; otherwise say the tool is disabled. /disabled_tools它把disabled_tool_names与主 Agent 的直接工具名集合求交集凡是命中的工具都会以明文列出如Update Memory、Create Automation并逐字要求模型不要声称能用它们。也就是说refusal_and_limits第三条与disabled_tools块形成了声明 运行时证据的双保险前者立规矩后者把本会话到底禁用了什么直接喂给模型。2.4 不谎称访问权限 → 四个直接工具 专家名单是全部表面Never claim filesystem access, connector access, or persistent storage you dont have. The four direct tools and thespecialistslist are your entire surface area.第四条最严厉绝不声称自己拥有实际不存在的文件系统访问、连接器访问或持久化存储。四个直接工具 specialists名单是主 Agent 的全部能力表面。这条直接否决了模型最常见的幻觉模式。在routing里有对应的正面指令You have NO filesystem tools.Any read, write, edit, move, rename, or search inside the users workspace goes throughtask(knowledge_base, …)。用户工作区内的任何文件操作都必须经由task(knowledge_base, …)委派绝不能通过write_file、ls或任何直接文件操作完成。三、边界声明的生效位置系统提示词的组装顺序理解这条声明的份量必须看它在最终提示词里的位置。主 Agent 的系统提示词由 compose.py 的build_main_agent_system_prompt()组装顺序如下agent_identity [用户自定义系统指令如有] core_behavior # 默认主体 knowledge_base_first # 默认主体 dynamic_context # 始终开启 routing # 默认主体 specialists # 始终开启动态名单 tools # 始终开启垂直切片 memory_protocol # 默认主体 citations # 始终开启 output_format # 始终开启 refusal_and_limits # 始终开启 reminder # 始终开启注意两个关键设计源码 docstring 中明确标注refusal_and_limits属于always部分与dynamic_context、specialists、tools、citations、output_format、reminder同级不受use_default_system_instructionsFalse影响。即使用户配置关闭了全部默认主体段落core_behavior、kb_first、routing、memory_protocol这条边界声明依然保留——平台级安全网不能被用户的 custom system instructions 关掉。custom_system_instructions是叠加而非替换它插在 identity 与默认主体之间因此KB-first、路由、引用、输出格式、拒绝规则这些平台安全网总是生效。这从架构上杜绝了用户自定义指令越狱能力边界的可能。load_md.py 的read_prompt_md()负责从app.agents.chat.multi_agent_chat.main_agent.system_prompt.prompts资源包加载这些 Markdown 片段compose.py用_wrap()以换行包裹每个片段后拼接成最终字符串。整个系统提示词在 factory.py 中随 Agent 构建被调用每次会话都会根据当前工作区的连接器、启停用工具、可见性私有/团队、引用开关实时渲染。四、能力表面的真身直接工具 专家名单4.1 主 Agent 的直接工具面四个直接工具并非抽象说法。从 tools/index.py 看主 Agent 的内置 SurfSense 工具实际只有两个且明确注明Connector integrations, MCP, deliverables, etc. are delegated viatasksubagentsMAIN_AGENT_SURFSENSE_TOOL_NAMES_ORDERED: tuple[str, ...] ( update_memory, create_automation, )加上 tool_instruction_block.py 中永远包含的task工具因为deliverables和knowledge_base专家在SUBAGENT_TO_REQUIRED_CONNECTOR_MAP中声明frozenset()永远不会被连接器排除task必有可用目标以及 factory.py 中为上下文编辑追加的只读 run_reader 工具这就是主 Agent 的全部直接工具面工具作用提示词定义update_memory维护用户个人长期记忆文档按可见性分为 private/team 两套变体private 版定义create_automation起草并创建自动化模型描述意图工具内部聚焦起草完整 JSON用户通过审批卡片 approve/reject三步在单次调用内完成create_automation 定义task调用一个专家子 Agent支持单发与批量 fan-outtask 定义因此边界声明里The four direct tools指的是update_memory、create_automation、task加运行时注入的只读工具这一整体——除此以外的一切能力都必须走task专家而task的合法目标又受specialists名单约束。两层约束叠加能力表面被精确锁定。4.2 专家名单的动态裁剪specialists名单也不是静态的。它由 registry.py 的main_prompt_registry_subagent_lines()生成其裁剪规则与build_subagents()完全一致memory专家永远排除记忆由主 Agent 的update_memory直接工具负责其余专家按SUBAGENT_TO_REQUIRED_CONNECTOR_MAP见 constants.py即surfsense_backend/app/agents/chat/multi_agent_chat/constants.py做连接器门控无连接器要求的常驻专家amazon、deliverables、knowledge_base、web_crawler、youtube、google_maps、google_search、indeed、reddit、instagram、tiktok、walmart连接器门控专家mcp_discoverySlack/Jira/Linear/ClickUp/Airtable/Notion/Confluence/Gmail/Calendar/MCP 任一连接器可用时出现、dropbox、google_drive、onedrive分别要求对应文件类连接器。代码注释里特别强调名单按契约非空non-empty by contractdeliverables与knowledge_base无连接器要求因此无论连接器如何裁剪task永远有可用的委派目标。这也反向支撑了边界声明第 2、3 条的可执行性——给出task替代在绝大多数情况下真的存在一个专家可以顶上。值得注意的兼容设计LEGACY_SUBAGENT_ALIASES把旧的gmail、linear、slack等子 Agent 名映射到合并后的mcp_discovery使 checkpoint 恢复时已暂停的旧task(subagent_typegmail)调用能平滑解析而不是硬失败子 Agent 不存在。这让专家不可用的边界处理有了向后兼容的兜底。五、失败不静默重试中间件层是如何兜底的边界声明第 2 条说task 调用出错要如实上报、不要静默无限重试。主 Agent 的中间件栈为此提供了多层机器兜底5.1 工具名修复ToolCallNameRepairMiddlewareToolCallNameRepairMiddleware 对模型发出的工具调用做两阶段修复小写修复name未注册但name.lower()已注册时原地改写捕捉模型把Search写成search之类的错误invalid 回退仍不匹配时把调用改写为invalid工具参数携带原始工具名与错误信息。invalid工具见 invalid_tool.py本身刻意不出现在系统提示词的工具列表里、也从不被模型广告为可调用它只在工具注册表中存在供 LangGraph 分发被改写的调用。模型收到的是可读的错误串The arguments provided to the toolXare invalid…据此自我修正。这直接呼应了边界声明的精神假装能做的幻觉被转化成工具名无效的真实反馈模型要么纠正、要么在下一轮直面refusal_and_limits的坦白要求而不是让一轮错误的调用把整条对话杀死LangChain 默认行为是对未知工具名抛出ToolNotFoundError终结本轮。5.2 死循环检测DoomLoopMiddlewareDoomLoopMiddleware 解决同一个工具用同样参数连续调用 N 次的静默死循环它对(工具名, 参数)计算签名用滑动窗口检测——窗口内签名全部一致默认阈值 3与 OpenCode 一致即判定死循环抛出一个permissiondoom_loop的人机协同HITL中断让前端渲染你卡住了吗继续 / 取消的界面。若用户选择取消则跳到本轮结束。代码注释明确该中间件默认关闭直到前端显式处理context.permission doom_loop中断。这正是不要静默重试 forever在运行时层面的具象化——平台宁可停下来问用户也不让模型空转。5.3 失败闭环连接器发现 Fail-Closed在 factory.py 中连接器/文档类型发现失败时采取fail-closed策略available_connectors为None时被置为空列表get_subagents_to_exclude的 None 短路逻辑被规避从而连接器门控专家全部排除、仅保留常驻专家而不是在发现接口抖动时错误地广告出所有连接器专家。同理MCP 工具发现失败会降级为本回合专家无 MCP 工具而非拒绝回复。这两处异常分支都保证了边界声明描述的能力表面在任何故障场景下只缩小、不虚增。六、边界声明与其它系统提示词模块的协同refusal_and_limits不是孤立的它与相邻模块形成闭环与core_behaviorcore_behavior.md后者要求准确性优先于迎合用户错了要礼貌反对、避免不必要的夸张与情绪化肯定坚持到任务完成或被真正阻塞。边界声明的Dont pretend you can do it正是accuracy over agreement在能力维度的延伸。与knowledge_base_firstkb_first.mdKB-first 要求事实性回答必须来自本回合真实拿到的平台数据、知识库、连接器或专家摘要找不到时先说明找不到再询问是否允许用通用知识回答。这与边界声明第 1 条坦白并询问是完全一致的行为模式——一个约束能力不要假装一个约束知识不要编造。与routingrouting.md路由纪律明确规定两条执行通道绝不互相模拟——直接工具只能做 update_memory、write_todos其余一律task。它还多次强调You have NO filesystem tools、大结果用export_run导出 CSV 文件而不是粘贴进聊天。这些正面路由规则与边界声明的负面禁止规则不谎称文件系统/连接器/存储访问互为镜像。与output_formatoutput_format.md输出格式要求绝不暴露内部工具参数名、后端 ID 或实现细节使用自然语言与边界声明共同压制模型把内部机制当成可承诺能力的倾向。与reminderreminder.md作为提示词最后一段reminder用一句话复述核心纪律简洁 · 以本回合专家数据为准 · 委派优先 · 无直接文件系统 · 出现持久事实时写入记忆。它是边界声明在整条提示词末尾的最后一次强化——正因为refusal_and_limits排在倒数第二、紧邻reminder它处于模型最容易记住的收尾区域。七、结论可解释的边界才是有用的边界回看这份仅 11 行的声明它之所以有效在于每一句话都有运行时机制背书能力不在清单内就坦白——tools与specialists是运行时真实工具面的快照清单即事实出错要上报、不静默重试——Receipt验证机制让自报成功可被证伪DoomLoopMiddleware兜住死循环运行时禁用即不可用——disabled_tools块把禁用名单明文喂给模型不谎称文件/连接器/存储访问——主 Agent 直接工具面被压缩到update_memory、create_automation、task加只读工具文件与连接器访问全部强制经task专家。对使用 SurfSense 的开发者与研究者而言这份声明揭示了多智能体系统提示词设计的一条可复制原则能力边界不是靠模型自觉而是靠声明的禁令 动态渲染的证据 中间件的机器兜底三层共同落地。任何想为自己的 Agent 增加诚实拒绝能力的实现都可以参照refusal_and_limits的四条规则以及它在 compose.py 中的always-on、不受用户自定义指令关闭的组装位置——把安全网放在用户指令之外把证据放在模型眼前。【免费下载链接】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),仅供参考
返回列表