直接开写。这篇笔记不绕弯子,聊的是我最近几个月在搞 Agent 过程中,被问得最多、踩得最深的三块东西:多模态输入、Harness 结构,以及 MCP 接入。如果你正打算从一个“只会调 API 的试用者”往“能设计 Agent 骨架的开发者”迈一步,这篇文章应该能帮你省掉不少试错的成本。
我先把话放在前面:大模型能力再强,边界也卡在“信息的输入形式”和“行动的约束范围”这两堵墙上。多模态解决的是第一堵墙,MCP 解决的是第二堵墙,而 Harness 是你在两堵墙之间搭的脚手架。三样东西分开看不新鲜,但放进一个真实可用的 Agent 里,环环相扣的问题才会暴露出来。
1. 多模态接入:让 Agent 从“听懂话”进化到“看得懂活”
从纯文本对话转向多模态输入,不是一个“把图片塞进去就行”的简单操作。我在这块反复折腾了大半个月,过程中逐渐梳理清楚了几个必须决策的层面。
1.1 纯文本 Agent 的真实瓶颈:不是模型笨,是信息被过滤了
很多开发者在初期习惯性忽略一个问题:用户的问题往往不只是“文字”,而是携带着大量的上下文信息。比如用户发来一张截图说“这个页面的登录逻辑有问题”,如果你只把这句话丢给模型,模型能做的只有猜测和反复追问;但如果能把截图内容准确抽取、识别出弹窗文案、校验按钮位置、报错提示的层级关系,模型给出的判断就会从“泛泛而谈”变成“可以直接执行”。
我试过直接把截图用 base64 塞给支持视觉的模型,效果确实有提升,但工程上马上遇到两个麻烦:第一是 token 消耗急剧上升,一张普通截图动辄占几百个 token,复杂界面可能要上千;第二是模型的“注意力”会被无关内容分散,截图上的一块装饰性配图、一段水印,都可能把规划器带偏。
所以多模态接入的第一个原则就是:不要盲目追求“模型自己看全图”,而是先做视觉信息的结构化提取。这里的“结构化提取”不是说必须接入专门的 OCR 服务,而是说在图像进入模型之前,先做一些针对性的预处理:裁剪无关区域、放大关键区域、压缩色彩层次。实测下来,把一张 1920x1080 的截图先按逻辑区块切分成几个 512x512 的局部图,再配合标注好的区块顺序,让模型按区块读取,理解和规划的准确率比一次性全图输入高了不止一个档次。
1.2 视觉语言模型(VLM)与工具管线的分工
现在市面上的主流 VLM 大体分两类:一类是 Gemini、GPT-4o、Qwen-VL 这类“端到端图文理解”模型,另一类是纯粹的视觉模型,比如专门做 OCR、目标识别、图像分割的专用模型。在 Agent 架构里,两者的角色完全不同。
我个人的分工习惯是:理解类任务交给 VLM,提取类任务交给专用模型。比如用户上传了一张系统的部署架构图,VLM 负责理解“这是一个前后端分离的结构,前端有三个模块”,但具体的“这张图里有多少个节点、每个节点叫什么名字”,我会先调用 OCR 模型把文字提取出来,再结合结构信息让 VLM 做归纳。这样的拆分带来了一个额外的好处:当工程出问题时,你能更快定位到底是“文字没提取出来”还是“模型理解错了”,而不是面对一整块黑盒不知所措。
这里有一个我踩过的坑:早期图省事,把一切视觉任务都交给一个 VLM 处理,结果在协议理解类的任务上表现还行,一到细节提取的任务就频繁出现“幻觉”,模型会把不存在的文字内容补充进去,而且一本正经地给你加粗说明。后来把任务拆开之后,小节失效的比率才降下来。如果让我给一个建议:任何视觉任务都不建议跳过预处理直接抛给大模型,哪怕只是一个简单的基础框标注。
1.3 动态帧采样:多模态在视频场景下的工程化路径
视频输入是另一个常见的坑。把视频直接丢给多模态大模型,无论是转成帧序列还是抽帧,token 消耗都会爆炸,而且效果往往并不理性。我尝试过几种方案,最后找到一个比较平衡的路径:先按秒级切帧,然后把相邻帧做差异分析,相似的帧丢弃,只保留关键帧;随后关键帧进入 VLM 做场景描述,最后把描述结果打包成一个“场景流”,交给后续的文本模型做整体推理。
这套方案看起来多走了一步,但在处理真实业务场景时非常值得。比如用户上传了一段操作录屏,问“这里面哪里点错了”,按秒切帧会产生几百张图,直接喂模型会让上下文迅速膨胀,且模型容易丢失前后因果;做了关键帧抽选之后,输入的图压缩到二三十张,模型反而能把“点击顺序-界面变化-报错出现”的因果链串起来。
1.4 多模态 Prompt 设计的特殊技巧:空间位置描述法
还有一处容易忽略的细节:多模态模型的“提示词”和纯文本模型的提示词,写法逻辑不完全一样。纯文本模型的提示词偏向描述目标和约束;而多模态模型的提示词需要额外加入空间关系的锚定。
直接在提示词里写“图里左边区域的那个输入框”是一种写法,但这种写法对模型的输出稳定性不高。实践中更稳的方式是先用预处理步骤把图片做九宫格分区(左上、中上、右上、左中、中心……),然后在提示词里明确写“请重点观察中下区域,该区域包含目标操作按钮”。这个小小的调整,能显著减少模型因为“看偏了”而产生的答非所问。本质上,多模态模型的注意力机制虽然强大,但依然有明显的偏置,我们可以用空间锚定去主动牵引它。
2. Harness:Agent 的骨骼,而不是简单地“调模型”
聊完模型接入,接下来是更工程化的部分:Harness。这个词现在有不少解释,但在我的语境里,它就是构建 Agent 时用于约束、编排、追踪大模型调用链路的那个框架层。如果说模型是 Agent 的大脑,Harness 就是连接大脑与身体动作的神经系统,它决定了模型的输出如何转成可执行的实际步骤。
2.1 为什么不能只靠“一个 while 循环”
很多人初写 Agent 时最大的幻觉,是以为只需要一个循环:调模型、拿输出、执行工具、把结果再接回去。表面上这个过程能跑通 demo,但它会在三个点上彻底失灵:状态丢失、工具权限失控、无法定位失败链路。
举个我曾经跌进去的例子:Agent 在交互过程中需要分三步完成一个任务,第一步调用 A 工具拿到一个临时凭证,第二步拿着凭证去调用 B 工具,第三步依赖前两步的结果组装一份报告。如果用裸循环实现,第二步一旦失败,就需要重跑整个任务,且第一步生成的凭证已经失效,整个链路就卡死了。而 Harness 提供的核心价值是:明确的状态管理、确定性的工具调度顺序、以及可观察的调用日志。
Harness 的核心职责在我看来有四个:维护会话级状态(session state)、约束工具调用边界(permission boundary)、调度步骤级执行顺序(orchestration)、提供完整的调用观测(observability)。这四个职责缺一不可。否则你就是在用“胶带纸”粘一个随时可能散架的机器人。
2.2 会话状态与会话长度:Harness 中状态管理的实操设计
状态管理是 Harness 里最容易被忽略、但绝对是最核心的模块。纯写代码的人容易把状态直接存在全局变量里,这种做法在临时脚本里没有大碍,一旦接入真实业务,多用户并发、多轮对话、中途断连重连,全局变量马上成为灾难。
我最终采用了比较传统的方案:把会话状态持久化到独立的存储层(基于 JSON 文档结构),每次模型调用之前,从存储中加载完整上下文;每次工具执行完成之后,立刻把变更写回存储。这个模式的优点是可以随意横向扩展,不依赖单机内存;但代价是 IO 次数增加。为了缓解这部分开销,我做了两层优化:一是在内存中维护一份热数据缓存,读写时优先操作缓存,仅在关键节点强制落盘;二是把会话中的大字段(如图像的 base64、长文档全文)拆分到单独的对象引用中,会话状态自身只保存引用路径,避免每次会话恢复时的反序列化开销。
一个经验性的建议:所有会话状态必须设计成可序列化结构,不要在状态对象里塞函数、塞活跃连接、塞临时文件句柄。我遇到过 Agent 崩溃后恢复时,状态对象里存了一个打开的文件读写器,反序列化直接失败,整个任务只能从零开始。现在我的规则很粗暴:会话状态里只允许出现 JSON 原生类型。
2.3 工具调度顺序:看似自由的 Agent 也需要步骤确认
第二道关键关卡是工具调用的顺序控制。大模型在生成行动计划时,本质上是在做概率选择,它可能漏掉一个必要步骤,也可能跳过中间校验。Harness 的作用是要在“模型的自由度”和“流程的确定性”之间做平衡。
我通常把工具调用方式分成两类:一类是必然步骤(required step),无论模型怎么规划,都必须按照预设顺序执行,比如登录凭证校验、权限确认、输入参数格式校验;另一类是可生成步骤(generated step),模型可以按任务需求自主选择。这个分离极其重要。如果所有步骤都强制使用“自由工具调用”(function calling),模型可能因为一些微小的原因跳过关键技术,导致下游执行出现奇怪的错误。
在实践中,我用了一个很简单的策略:把整个 Agent 的执行编排定义为一个“步骤声明表”,在表中声明每个步骤是 required 还是 optional,并标明前置依赖。模型只负责在 optional 步骤中进行规划,required 步骤由 Harness 在执行流中强制插入。这看起来牺牲了一点“智能感”,但换来的是任务成功率的显著提升。让 Agent 完全自由地决定执行路径,在一个真正复杂的工作流里几乎等于失控。
2.4 Harness 的可观测性:没有日志追踪的 Agent 就像黑盒子
第三个常被新手忽略的是 Harness 的可观测性。很多人在开发 Agent 的时候,最容易烦躁的就是:模型到底为什么调用了这个工具?这个工具的返回数据为什么和预想的不一致?如果 Harness 层不记录完整的调用链,排查这类问题只能靠猜。
我在 Harness 内部固定记录三类日志:模型决策日志(模型为什么选择这个方法,目标的原始输入是什么)、工具输入输出日志(进入工具之前的完整参数,以及工具返回的原始结果)、状态变更日志(每一步执行完,会话状态增加了什么、修改了什么)。这三类日志拼接起来之后,整个 Agent 的行为逻辑就完全可回溯了。每次 Agent 执行结果与预期不符,第一件事永远是拉日志,看清是决策错、执行错还是预期本身错。
3. MCP:把“接工具”从“写胶水代码”变成“定义协议”
多模态和 Harness 解决的是 Agent 的“输入”和“执行框架”,MCP 解决的则是“Agent 怎么跟外部世界握手”。没有接触过 MCP 的人第一次听到它,容易觉得这又是一个新框架,其实它的核心思想特别朴素:定义一套统一的标准,让任何 Agent 都能通过同一种方式调用不同的外部服务。
3.1 没有 MCP 之前,接一个工具要付出多少代价
我先回忆一下没有 MCP 时接一个工具的过程。假设要让 Agent 能查询某个业务系统的订单数据,传统做法是写一个自定义的 Function Calling 描述,把接口参数解释成 JSON Schema,再写一段代码负责把模型的输出映射成 HTTP 请求,然后处理鉴权、超时、错误重试。一个工具一套写法,十个工具十套写法。更头疼的是,换一个模型提供商,这套映射逻辑可能完全失效,因为不同模型对函数定义格式的支持存在差异。
MCP 出现后,把这一整套逻辑统一了。MCP 的核心概念非常简单:Agent 侧安装一个 MCP Client,工具提供方实现一个 MCP Server,两者通过标准化的 JSON-RPC 协议通信。工具的定义、调用、结果返回、错误处理,全部走同一种格式。Agent 再也不需要知道工具背后的实现细节,只需要知道“这个 MCP Server 提供了哪些工具”,就能一键对接。
用一个生活化的类比:MCP 之前的对接方式就像给每种电器都配一个专用插座,电压不同、接口不同、正负极也不同;MCP 之后的对接方式就像统一了 USB-C 接口,只要产品支持标准,任何充电器都能给任何设备供电,最多是功率大小有差别,但协议层完全统一。
3.2 Agent 消费 MCP 的接入步骤:一个可复制的实操路径
在实际接入中,Agent 消费 MCP Server 的路径可以拆成几个环节:
第一步,通过工具发现(Tools/List)接口拿到 Server 提供的工具清单。这个清单不仅包含工具名称,还包含完整的输入参数描述。值得注意的坑是:不同 Server 对参数描述的详细程度差异很大。有的 Server 把参数描述写得非常仔细,Agent 能直接根据描述生成合理参数;有的 Server 则只写了参数名,没有给出具体约束规则,Agent 就只能靠猜。所以在选型外部 MCP Server 时,参数描述的信息密度是一个关键考量指标。
第二步,根据任务目标构造工具调用请求(Tools/Call),把参数按照 JSON Schema 组织好发送出去。这里有一个工程细节:不要在同一个上下文中堆叠太多工具描述信息。如果把 20 个工具的完整定义全部塞进提示词,模型在工具选择时的判断力会显著下降。建议的方式是做“工具分组”,根据任务类型提前预选一组相关工具,只把这组工具的定义提供给模型。
第三步,处理结果集(Tools/Result)。MCP 返回的结果通常是标准化的 content 块,里面既可以有纯文本,也可以有图片或结构化数据。Agent 需要根据参数判断这段返回应该直接展示给用户,还是作为中间过程转给下一个工具。一个容易被忽略的点是:MCP 的结果并不保证是“人类可读”的,有些 Server 返回的是原始内部结构,需要 Agent 提前在其描述里明确自己对结果的解读要求。
3.3 MCP 配置中的三类典型工程问题与解决记录
配置 MCP 的过程中,我遇到过的典型问题大体分三类:
第一类是并发安全。多个 Agent 实例同时使用同一个 MCP Server 的连接时,如果 Server 端没有做连接管理,会出现消息串号的情况。表现是一个 Agent 的请求结果被另一个 Agent 接收,导致上下文混乱。解决方案是为 Agent 会话绑定独立的 Client 实例,或者引入更简单的串行队列,确保一个连接同一时间只处理一个请求。实测并发请求数在个位数级别时,不做锁处理也能跑通,但一旦上升到并发任务调度,必须加状态隔离。
第二类是模型对工具参数的命名猜测。有的工具定义不够清晰,模型会自行脑补参数名,结果工具调用时报参数不存在。这个问题的根源在于 Server 的工具描述不完整,不完全是模型的问题。解决的方法是先用一个小模型跑一次工具发现,把发现的工具定义“翻译”成更详细的自然语言描述,再把它作为 Agent 的上下文提示,让模型在调用前拥有充分的参数理解。
第三类是Server 超时或无响应。如果某个 MCP Server 依赖外部网络,而外部网络有延迟,整个 Agent 的执行就会被卡住。我的处理方式是在 Harness 层为每个 MCP 调用设置独立的超时控制,并配套降级策略。如果工具调用失败,Agent 不是直接中断,而是自动尝试两次重试,重试仍失败则跳过该步骤并在总结中明确标注“该环节未能执行”,把决策权交还给用户或上级编排逻辑。
4. 三者协同:一次完整的多模态 + Harness + MCP 全链路复现
分开讲完三个技术点,我们再把它全部拼到一个真实场景中。假设现在要做一个 Agent,任务目标:用户上传一张界面截图,Agent 通过理解截图内容,调用某个外部 MCP Server 上的工具,把界面中的报错信息替换成修改建议并生成一份报告。这个场景用到了上面提到的所有知识点,我来完整拆一遍执行链路。
4.1 全链路流程的事件时间线
用户上传图片后,Agent 的事件时间线大致是这样的:
事件一(多模态预处理阶段):Harness 接收图片,执行图片切割、关键区域放大、OCR 文字提取。提取到的文字先存储为结构化对象,与图像切片共同组成一个多模态输入包。
事件二(视觉理解阶段):Harness 调用 VLM,输入设计好的空间锚定提示词,输出对截图的语义描述。模型识别出这是一个“登录失败的报错界面”,并定位到具体报错文案的所在区域。
事件三(规划阶段):Harness 将视觉理解的输出与任务目标一起交给文本模型,生成行动计划。模型根据需求判断需要调用“查询错误码字典”这个外部工具,而这个工具正是通过 MCP Server 暴露的。
事件四(工具调用阶段):Harness 检查计划中的步骤,确认查询错误码是“必然步骤”,插入到执行序列中。随后通过 MCP Client 向 Server 发送工具调用请求,传参为从截图中提取到的错误码字符串。
事件五(结果处理阶段):MCP Server 返回错误码对应的解释与修改建议。Harness 把它存储在会话状态中,并作为上下文再交给模型,让模型基于建议生成面向用户的最终报告。
事件六(状态落盘与日志记录):整个任务完成,会话状态更新,调用链日志写入存储。用户不仅拿到了报告,还能清楚看到 Agent 每一步的执行依据和中间结果。
4.2 关键执行配置:一份结构化的会话与调用配置参考
因为不同团队的技术栈不同,我这里不附具体代码,而是给出一个通用的 JSON 配置结构设计。凡是实现过类似系统的开发者,应该能很快映射到自己的代码里。
{ "session": { "id": "sess_2025_xxxx", "status": "running", "storage_ref": "path/to/storage", "state_snapshot": { "extracted_blocks": ["block_a", "block_b"], "current_step": "tool_calling", "pending_plan": ["ocr_extract", "visual_understand", "call_error_code_service", "generate_report"] } }, "harness_policy": { "required_steps": ["ocr_extract", "error_code_validate"], "allowed_tools": ["query_error_code", "search_solution"], "permission_model": "confirm_on_unknown", "timeout_ms": 15000 }, "mcp_config": { "server_endpoint": "https://mock-server/mcp", "transport": "streamable-http", "selected_tools": ["query_error_code", "search_solution"], "retry_policy": { "max_retries": 2, "backoff_ms": 1000 } }, "multimodal_config": { "image_preprocess": "block_split", "anchor_mode": "grid_9", "vlm_model": "vision_model_name", "max_input_tokens": 4096 } }这份配置里最核心的设计点是:
required_steps区分“模型可自由编排”和“必须由 Harness 强制插入”的步骤,避免模型因为上下文理解偏差而漏掉关键动作。permission_model: "confirm_on_unknown"表示当模型请求调用一个不在allowed_tools列表内的工具时,Harness 不直接放行,而是暂停执行并提示用户确认。这个设置对生产环境至关重要。image_preprocess: "block_split"表示图像必须经过区块化处理再进入模型,就算后续想换成实时视频流,也只是扩展预处理模块的问题,不触发架构级改动。mcp_config下的selected_tools限定当前会话只能使用一组固定工具,这个限制有效避免了模型在大量工具定义之间“挑花眼”的情况。
4.3 逐阶段检视:三个层面如何衔接不脱节
整个流程看起来顺滑,但实际落地时,三个层面最容易脱节的位置依次是:
一层脱节:多模态识别结果与规划器的衔接。OCR 提取出错误码“E12345”,但这个错误码以什么字段名传给规划器?如果字段名不明确,规划器可能把它当作普通文本而不是可查询的键值。我的做法是在多模态输出阶段就规范为“结构化数据包”,规定必须包含error_code: string字段,规划器直接消费该字段,不依赖自然语言描述。
二层脱节:规划器的计划标注与 Harness 步骤声明的对应。模型生成的计划可能叫“查询错误消息”,但 Harness 步骤表里声明的是“error_code_validate”。这需要在规划器和 Harness 之间做一层术语映射,否则 Harness 无法判断模型是否在尝试执行流程内步骤。我的建议是提前做一个“别名映射表”,把模型可能的描述方式映射到统一的步骤 ID。
三层脱节:MCP 工具返回值对模型可读性的转译。有些工具返回内部状态码,模型并不认识;有些返回大段 JSON,会干扰模型对后续步骤的判断。可以在 MCP Client 层加一个“转译器”,把原始返回格式转换成自然语言摘要,再喂给模型。这个转译器本身不复杂,但能显著提升下一轮决策的准确度。
这三层脱节表面上是技术细节,但本质上对应了同一个原则:Agent 不是“一个大模型包打天下”,而是多个模块拼接出来的系统,模块之间的接口契约必须显式化。
5. 常见问题与排查技巧实录:来自一线调试的速查笔记
最后一部分,整理我在实际调试中遇到频率最高的几个问题。这些问题网上资料往往只讲理论,我想把现场排查的亲历感受写出来,方便大家遇到类似问题时能快速锁定原因。
5.1 多模态 Token 爆炸:一次无意识的冗余输入教训
场景:某次调试中,Agent 在读取用户上传的长截图时,直接把原始大图塞给了 VLM,导致单次请求 token 消耗接近 3 万。排查时发现,除了图片本身大,系统还把多张相似切片重复送入上下文,模型在推理时需要反复“翻看”重复内容,响应时间直接翻倍。
解决思路很直接:在预处理阶段增加相似度去重。具体做法是计算相邻切片的感知哈希,相似度超过阈值的切片直接丢弃,只保留变化最大的关键帧。这个技巧对长图和多图场景效果尤其明显。实操建议是给多模态模块加一个“token 预算上限”,如果预处理后的输入仍然超出预算,先按清晰度降级压缩,而不是直接报错。
5.2 Harness 崩溃恢复:会话状态里的“函数指针陷阱”
场景:Agent 在长任务执行中途,进程因为外部资源不足崩溃。重启后从存储恢复会话状态,结果反序列化失败。原因查找过程发现:状态对象里存了一个函数引用,导致 JSON 序列化/反序列化流程中断。
这是个典型错误,但非常隐蔽。我的排查思路后来总结成三步:先检查状态对象里的所有字段类型是否都是纯 JSON 类型;再检查是否引用了无法持久化的资源(打开的文件句柄、数据库连接、临时文件路径);最后检查反序列化后的对象是否还带有原有的上下文标识。永远不要相信“内存里能跑”的对象就是“可恢复”的对象。
5.3 MCP 调用超时:上游慢、下游卡、Agent 跟着堆
场景:Agent 调用某个 MCP Server 上的“查询天气”工具,偶尔出现长时间无响应,整个任务被卡住。排查时发现,Server 端依赖了一个缓慢的第三方数据源,在数据源延迟时,Server 本身也不设置响应超时,于是 Agent 侧就无限等待。
我的处理分两层:在 MCP Client 侧设置硬性超时(我一般用 10 秒起步,根据业务验证调整),超时后记录错误日志并按重试策略处理;在 Server 侧,如果是自己实现的服务,建议在工具实现里也设置内部任务超时,负责兜底。一个更防御性的做法是:在工具定义里明确声明timeout_hint字段,让 Agent 在选择调用前就知道这个工具可能较慢,然后决定是同步等待还是异步轮询。
5.4 工具调用权限误判:当 Agent 想做“计划外”的事
场景:模型在生成计划时,决定调用一个并不在预选工具列表里的工具。如果 Harness 直接拦截并报错,Agent 任务会失败;如果 Harness 直接放行,又可能引入未预期的行为。
我最终采用的是“分级策略”:不在白名单中的工具,分为“可自动批准”“需用户确认”“完全禁止”三档。对低风险、幂等性强的工具(如查询类),可自动批准;对能改变状态的工具(如创建订单、删除资源),一律要求人工确认;对涉及敏感数据的工具,直接禁止放行。这个分级策略可以通过 Harness 的配置轻松调整,是最能平衡“智能性”与“安全性”的实践方案。
5.5 排查问题的最优顺序:一个固定的排错路径
在多次踩坑后,我沉淀了一个固定的排查顺序,分享给大家:
先看 Harness 日志,确认模型的每一步决策依据是什么,这一步能确定“是不是模型选错了工具,或者漏掉了一个步骤”;再看工具输入输出日志,确认进入工具的数据是否符合预期,这一步能确定“是不是参数传错了,或者工具返回了异常结果”;最后再查会话状态快照,确认状态在哪个环节发生了偏差。如果状态在预期内,那大概率是模型决策质量的问题,需要调整提示词或增加约束;如果状态本身与预期不符,那就是 Harness 编排逻辑的问题,需要检查调度代码或状态更新时机。
这套顺序救了我很多次,至少比一头扎进代码里漫无目的地找要高效得多。
写在最后:一点实操体会
这三块东西如果分开看,每一个都能找到现成的库和文档,但真正决定 Agent 好用不好用的,是它们之间的“接缝”处理得是否精细。我个人在实际开发中的体会是:与其花大量时间去追新模型、新特性,不如先把现有链路里的每一段接缝打磨好。多模态的预处理干净了,Harness 的状态不丢不乱,MCP 的工具边界清楚,纵然模型能力原地踏步,Agent 的整体表现都会明显上一个台阶。
最后再分享一个经验:刚开始搞 Agent 的开发者,总想把所有能力都装进去,模型选最强的,工具接最多的,流程整最复杂的,结果一个都跑不稳。我现在的习惯是先“做窄再拓宽”,拿一两个高频率场景切入,把完整链路跑通跑稳,再考虑扩展。这个内容后续扩展的方向其实也清晰:像多模态可以加实时音视频输入,Harness 可以做成支持多 Agent 协作的调度中枢,MCP 可以多接几类企业级服务,但底层的接缝处理好,才能有拓展的余地。