当前位置: 首页 > news >正文

AI Agent-Manus 构建经验解读(下)

前言​

        Manus 官网博客文章《Context Engineering for AI Agents: Lessons from Building Manus》为我们带来了 AI 智能体上下文工程领域的深度实践总结。该文浓缩了 Manus 团队在技术攻坚中的核心经验与深刻洞察,系统性梳理了智能体系统设计面临的关键问题及解决方案,其中涵盖 KV 缓存优化、动态动作空间管理、基于文件系统的上下文扩展等核心技术方向。​

        对于有 AI Agent 系统开发经验的从业者而言,阅读此文堪称 “句句切中痛点”。文中探讨的每一项技术细节,几乎都精准映射了实际开发中曾遭遇的 “技术陷阱”。尤为珍贵的是,文章不仅以实践印证了这些挑战的行业普遍性,更针对性地提供了经过验证的精妙解决方案 —— 这些思路恰恰是许多开发者此前未触及或仍在艰难探索的方向,为实际项目的优化升级提供了清晰指引。

        基于此,本文将对该博文展开深入解读,助力读者精准把握核心技术要点,全面理解文中的实践经验与技术逻辑。

动态工具处理策略

问题概述

        随着AI 智能体能力的提升,其动作空间(action space)会变得愈发复杂,工具数量也会呈爆炸式增长。最近MCP 的流行更是加剧了这一问题。如果允许用户配置工具,总会有人将大量来历不明的工具塞入精心设计的动作空间中,导致模型更容易选错行动或采取低效路径,从而使AI 智能体变得迟钝。

        一种自然的想法是设计一个动态的动作空间,按需动态加载工具,在Manus中也尝试过这种方法。但实验表明,除非绝对必要,否则应避免在迭代中途动态增删工具,原因主要有以下两点:

  1. 在大多数模型中,工具定义在序列化后通常位于上下文的靠前位置,通常在系统提示词之前或之后。因此,任何更改都会导致后续所有动作和观测的KV 缓存失效。

  2. 当此前的动作和观测仍然引用着当前上下文中不再定义的工具时,模型会感到困惑。如果没有约束解码(constrained decoding),这通常会导致模式违规或产生幻觉动作。

处理策略

        为平衡动作空间优化与上下文稳定性,Manus 采用上下文感知状态机精准管理工具可用性,同时集成推理框架的响应预填充功能 —— 基于状态机输出动态生成部分响应文本(如函数调用前缀)以锚定解码起点,再在模型解码阶段通过遮蔽非目标 token 的 logits 实现动作选择的动态约束。

 1. 定义上下文感知状态机
  • 状态机角色:状态机基于代理的当前上下文(如用户输入、上一步动作结果)决定工具可用性。状态示例:

    • IDLE:用户刚提供输入,代理必须立即回复文本,不得调用任何工具。

    • TOOL_REQUIRED:代理必须调用一个工具,但具体工具不限。

    • TOOL_SPECIFIED:代理必须从特定工具组调用(如只允许浏览器工具)。

  • 状态转换:状态机根据事件(如用户消息或工具执行结果)更新状态。例如:

    • 用户发送新消息 → 状态转为IDLE(代理应优先回复)。

    • 代理决定执行工具 → 状态转为TOOL_REQUIREDTOOL_SPECIFIED

  • 输出:状态机输出一个“遮蔽规则”,例如:

    • IDLE状态:遮蔽所有工具调用token(只允许文本响应)。

    • TOOL_SPECIFIED状态:只允许以browser_开头的工具名称。

2. 集成响应预填充

        利用推理框架的响应预填充功能,根据状态机输出预先生成部分响应,限制模型的解码起点。以 NousResearch 的 Hermes 格式为例,函数调用约束可通过三种模式实现:

  • 自动模式(Auto):状态为“可选工具调用”,预填充至<|im_start|>assistant。模型可自由选择文本回复或工具调用(不应用遮蔽)。

  • 必须模式(Required):状态为“必须调用工具”,预填充至<|im_start|>assistant<tool_call>。模型必须生成一个工具调用,但工具名称不受限(遮蔽只用于排除无效工具)。

  • 指定模式(Specified):状态为“必须调用特定工具组”,预填充至函数名前缀,例如<|im_start|>assistant<tool_call>{"name": "browser_。模型只能完成以browser_开头的名称(如browser_search),遮蔽其他所有选项。

        预填充固定了响应的起始部分,减少了模型的决策空间,logits遮蔽在此基础上进一步约束。

 3. 应用Logits遮蔽 
  • 遮蔽机制:在模型解码时,logits处理器动态修改token logits:

    • 对于不被允许的token(如特定工具名称),将其logits设为负无穷(或极低值),使模型无法生成这些token。

    • 遮蔽范围:基于状态机输出的规则:

      • IDLE状态:遮蔽所有工具调用相关token(如<tool_call>和所有工具名称),只允许文本token。

      • TOOL_SPECIFIED状态:遮蔽所有不以指定前缀(如browser_)开头的工具名称token。

    • 实现方式

      • 使用推理框架的API(如Hugging Face的LogitsProcessor类)在生成过程中注入遮蔽逻辑。

      • 在编写工具名称的时候,带上结构化前缀(如browser_shell_)。由于工具名称有结构化前缀,遮蔽可以高效实现:只需检查token是否匹配前缀,无需维护复杂状态。

      • 示例代码逻辑:

        class ToolMaskLogitsProcessor(LogitsProcessor):def __init__(self, allowed_prefix):self.allowed_prefix = allowed_prefix  # e.g., "browser_"def __call__(self, input_ids, scores):# 遮蔽所有不以allowed_prefix开头的工具名称tokenfor token_id in token_vocab:token_str = tokenizer.decode(token_id)if token_str.startswith("tool_name:") and not token_str.startswith(f"tool_name:{self.allowed_prefix}"):scores[token_id] = -float('inf')  # 遮蔽return scores
  • 无状态设计:遮蔽仅基于当前解码步骤的token,不依赖历史上下文,因此不会引入有状态复杂性。

        这种 “遮蔽而非移除” 的策略确保了 Manus 代理循环的稳定性:既维护了上下文的一致性以保障 KV 缓存有效性,又通过动态 logits 掩码灵活优化动作选择,在模型驱动架构下实现了高效且可控的智能体交互。

上下文状态机工作流程总结

  1. 输入处理:用户发送消息,代理进入新状态。

  2. 状态机评估:状态机基于上下文(如消息内容)更新状态(例如,转为IDLE)。

  3. 预填充生成:根据状态,预填充响应前缀(例如,在IDLE状态,预填充至<|im_start|>assistant)。

  4. 解码与遮蔽:模型开始解码;logits处理器应用遮蔽规则(例如,在IDLE状态,遮蔽所有工具token)。

  5. 输出生成:模型生成响应,仅限允许的动作(如纯文本或指定工具调用)。

上下文状态机场景处理示例

        假设用户向Manus代理发送消息:“查一下今天的新闻。” 代理状态机处理如下:

  • 上下文:用户新输入,代理应优先回复确认,而不是立即执行工具。

  • 状态机决策:状态转为IDLE(必须立即回复文本)。

  • 预填充:响应预填充至<|im_start|>assistant(自动模式,但遮蔽将强制文本回复)。

  • Logits遮蔽

    • 遮蔽规则:所有工具调用token(如<tool_call>browser_searchshell_exec等)的logits被设为负无穷。

    • 结果:模型只能生成文本token,例如输出:“好的,我将为您搜索新闻。请稍等...”,而无法生成任何工具调用。

  • 后续动作:如果代理决定执行工具(如状态转为TOOL_SPECIFIED for 浏览器工具),状态机更新:

    • 预填充至<|im_start|>assistant<tool_call>{"name": "browser_

    • 遮蔽规则:只允许以browser_开头的工具(如browser_search),遮蔽其他工具(如shell_ls)。

    • 模型输出:<tool_call>{"name": "browser_search", "parameters": {"query": "今日新闻"}}

使用文件系统作为上下文

问题概述

        现代前沿大语言模型(LLM)已能支持 128K 令牌甚至更长的上下文窗口,但在真实世界的智能体场景中,这样的容量往往仍显不足,甚至可能成为性能负担。这一矛盾主要体现在三个核心痛点:

  • 容量瓶颈:当智能体与网页、PDF 等非结构化数据交互时,观察结果会急剧膨胀,极易突破即使是 128K 的上下文限制,迫使系统不得不舍弃部分关键信息。

  • 性能衰减:研究表明当输入长度超过临界值(通常远低于模型理论支持的窗口大小)后,模型的理解能力与逻辑连贯性会显著下降

  • 成本控制:即便采用前缀缓存等优化技术,长输入的传输成本与预填充计算开销仍随序列长度线性增长,导致在高频交互场景中花费巨大

        为了解决这些问题,许多智能体系统选择采用上下文截断或压缩策略,但过度激进的压缩必然导致信息丢失。这一问题是根本性的:智能体的决策本质上依赖于对所有先前状态的完整感知,而我们无法提前预判哪些观察结果会在后续步骤中成为关键依据。从逻辑层面看,任何不可逆的压缩操作都潜藏着破坏决策链连贯性的风险。

处理策略

采用文件系统

        基于这些考量,Manus 创新性地将文件系统重构为智能体的无限记忆层。其核心突破在于:

  • 无限容量:文件系统天然支持TB级存储,解除上下文长度枷锁;

  • 持久化状态:所有观察结果按需持久存储,规避模型内存限制;

  • 结构化操作:智能体通过读写API直接操作文件,实现状态精准存取。

        在这种架构下,模型能够自主学会按需读写文件,将文件系统不仅作为存储介质,更转化为结构化的外部记忆模块。​

可恢复性压缩策略

        我们的压缩策略始终设计为可恢复的:

  • 网页内容可从上下文中移除,只需保留 URL 作为重新爬取的索引;

  • 文档正文可暂时省略,通过沙盒中保留的文件路径即可实时加载原始内容。

        这种设计实现了上下文长度的有效缩短,同时确保所有被移除的原始数据都能通过元数据(URL、文件路径)完整重建,从根本上避免了信息的永久丢失。

对于未来智能体架构的展望

        在这一方案的探索过程中,Manus团队意外发现了它对状态空间模型(SSM)在智能体领域应用的特殊价值。文件系统方案意外地为状态空间模型(SSM) 开辟了新可能:

  • 弥补SSM缺陷:SSM因缺乏全局注意力机制,难以处理长程依赖。而文件系统提供的精准外部记忆,可替代性地解决状态回溯问题;

  • 释放效率潜能:SSM的线性复杂度结合文件系统的无限记忆,有望实现超长决策链的低成本推理。

        与 Transformer 架构不同,SSM 因缺乏全局注意力机制,在处理长距离后向依赖关系时存在天然短板。但如果能让 SSM 掌握基于文件系统的外部记忆管理能力 —— 将长期状态存储于外部文件而非上下文窗口中,其线性计算复杂度带来的速度与效率优势将得到充分释放,有望催生一类全新的高效智能体系统。从这个角度看,融合文件系统记忆的 SSM 智能体,或将可能成为神经图灵机理念的真正实现路径。

通过复述操控LLM注意力

       如果你使用过 Manus,可能会注意到一个有趣的现象:在处理复杂任务时,它会主动创建一个todo.md文件,并在任务推进过程中持续更新内容 —— 通过勾选已完成项目、补充新任务项等方式动态维护列表。这一看似简单的行为,实则是 Manus 为操控大语言模型(LLM)注意力而设计的核心机制。

        当 Manus 智能体在任务中创建并更新 todo.md 时,其本质是在对抗 LLM 固有的注意力熵增定律。这种定律带来的挑战在长任务场景中尤为突出:​

  • 目标权重衰减:实验数据显示,在超过 20 步的决策链中,原始任务目标在 KV 缓存中的注意力权重衰减幅度超过 70%,导致模型对核心目标的感知能力显著弱化。​

  • 局部最优陷阱:模型容易陷入高频工具调用的循环(如反复执行搜索操作),这些局部动作会逐渐淹没全局任务意图,使智能体偏离预设路径。​

  • 传统方案失效:此前常见的 “在系统提示中重复目标” 策略难以奏效,由于提示文本位于上下文前端,会被后续大量中间状态信息干扰稀释,无法持续发挥引导作用。

        Manus 处理的典型任务平均需要约 50 次工具调用,这意味着决策循环会经历较长的上下文积累过程。由于智能体的决策完全依赖 LLM 的推理能力,在长上下文或高复杂度任务中,极易出现主题偏离或早期目标遗忘的问题。​

        为解决这一痛点,Manus 通过持续重写待办事项列表 todo.md的方式,将核心目标与当前进度主动复述到上下文的末尾位置。这种设计能将全局计划精准推入模型的近期注意力范围,有效避免任务目标 “丢失在中间状态” 的问题,显著减少决策过程中的目标不一致现象。

        值得注意的是,这一机制完全通过自然语言交互实现注意力偏向引导,无需对模型架构进行特殊改造,既保持了系统的轻量化特性,又实现了对 LLM 注意力的精准调控。

注意力锚点

层级实现方式认知作用
结构锚创建/plan/todo.md建立专用的待办列表-记忆文件
时间锚每3步更新todo.md,同步处理进度防止注意力漂移
语义锚用相同句式描述所有任务项降低模式识别负荷

保留错误

问题概述

        在智能体执行任务的过程中,错误的出现并非技术缺陷,而是现实场景的必然产物。语言模型可能生成幻觉内容,外部环境可能返回错误数据,工具调用可能出现异常行为,各类意外的边缘情况更是随时可能发生。在多步骤任务中,失败绝非偶然现象,而是智能体决策循环中不可分割的组成部分。​

        面对错误时,一种常见的处理方式是刻意隐藏这些 “不完美”:

        清理错误痕迹、直接重试操作,或是重置模型状态并依赖温度参数等随机性来规避问题。

        这种做法看似能营造更安全可控的交互体验,实则需要付出沉重代价 —— 错误证据的丢失,意味着LLM失去了关键的学习素材。缺乏这些具象化的失败案例,智能体便无法形成有效的经验积累,自然难以实现行为模式的适应性优化。​

处理策略

        根据Manus团队实践的经验,改善智能体行为最有效的策略其实异常简单:将错误尝试完整保留在上下文中。当模型能够直接观察到失败的行动轨迹,以及由此产生的观测结果或堆栈跟踪信息时,其内部信念系统会进行隐性更新。这种基于真实反馈的学习过程,会动态调整模型的决策先验,显著降低重复相同错误的概率,推动智能体在试错中实现自我迭代。​

        事实上,错误恢复能力应当被视为真正智能体行为的核心标志之一。然而目前在大多数学术研究与公共基准测试中,这一关键维度仍未得到充分体现 —— 现有评估体系往往聚焦于理想条件下的任务成功率,却忽视了真实场景中错误处理与恢复能力的重要价值。这种评估偏差可能导致智能体技术在实验室环境中表现优异,却在复杂现实场景中难以发挥实效。​

保持少样本学习的多样性

问题概述

        在大语言模型(LLM)应用中,通过少样本学习引导LLM正确输出格式是减少大模型幻觉的常用技术。但在智能体系统中,这种策略可能在某些情况下产生相反的效果。​

        语言模型本质上是优秀的模式模仿者,它们会无意识地复刻上下文中的行为模式。当上下文长期充斥着相似的行动 - 观察对序列时,模型会倾向于遵循既定模式,即便该模式已不再适用于当前任务需求。这种模式依赖在重复决策类任务中尤为危险:例如在使用 Manus 审查 20 份简历的场景中,智能体常陷入机械性重复 —— 仅仅因为上下文历史中存在类似行动记录,就持续复现相同操作流程,最终导致任务偏离目标、过度泛化需求,甚至产生无依据的幻觉输出。​

处理策略

        破解这一困境的核心在于增加少样本学习案例的上下文多样性。Manus 通过在行动与观察数据中引入可控的结构化变化实现这一目标:

        采用不同的序列化模板呈现信息,使用替代性措辞描述相似操作,在内容顺序或格式上注入微小差异。

        这种受控随机性能够有效打破模型对单一模式的依赖,重新校准其注意力分配,使其更关注当前任务的具体需求而非历史模式惯性。​

        这一实践揭示了智能体设计的重要原则:避免LLM陷入某些固定结构的思维定式。上下文的同质化程度越高,智能体的适应性就越弱,面对新场景时的鲁棒性也越差。通过主动构建多样化的上下文环境,才能让智能体在复杂任务中保持灵活性与判断力。

参考文献

Context Engineering for AI Agents: Lessons from Building Manus

http://www.dtcms.com/a/291666.html

相关文章:

  • powerquery如何实现表的拼接主键
  • mybatis多对一一对多的关联及拼接操作以及缓存处理
  • Java 与 Android 回收机制深度解析
  • 行业出海研究报告
  • Apache Ignite 中的 SQL 模式(Schema)管理机制
  • Qt字符串处理与正则表达式应用
  • MCP vs 传统集成方案:REST API、GraphQL、gRPC的终极对比
  • 使用vue-pdf-embed发现某些文件不显示内容
  • Jenkins接口自动化测试(构建)平台搭建
  • Jenkins 多架构并发构建实战
  • 计算机网络:连接世界的数字脉络
  • Python爬虫实战:研究pymorphy2库相关技术
  • JVM:工具
  • 字节跳动视觉算法面试30问全景精解
  • Python爬虫实战:研究PyPLN库相关技术
  • PCIe之P2P应用
  • 从ZooKeeper到KRaft:Kafka架构演进与无ZooKeeper部署指南
  • Android perfetto 工具使用
  • 【前端】ikun-pptx编辑器前瞻问题二: pptx的压缩包结构,以及xml正文树及对应元素介绍
  • 从重复劳动到自动化:火语言 RPA 的实践与思考
  • python办自动化--读取邮箱中特定的邮件,并下载特定的附件
  • 物联网_TDengine_EMQX_性能测试
  • RabbitMQ-交换机(Exchange)
  • 【无标题】buuctf-re3
  • 解决pip指令超时问题
  • MCU中的总线桥是什么?
  • Windows PE文件内未用空间学习
  • Collection接口的详细介绍以及底层原理——包括数据结构红黑树、二叉树等,从0到彻底掌握Collection只需这篇文章
  • wed前端简单解析
  • wangEditor5添加键盘事件/实现定时保存功能