☰
端侧Agent工程化实战:从架构分层到安全收口的关键路径
2026/10/7 13:38:51 网站建设 项目流程

做端侧 Agent 的朋友应该都有同感:Demo 阶段怎么跑怎么顺,一到工程化就翻车。前两篇聊了端侧 Agent 为什么值得做、基础架构长什么样,今天这篇就讲讲把 Agent 从“能跑”推到“能上线”中间那段最难走的路,也就是 Agent 工程化。这篇先啃硬骨头:架构怎么分层、harness 到底是什么、框架怎么选、工具调用和记忆怎么做工程化、并发怎么扛、安全怎么收口。调试、评测、监控那些相对独立的内容,我放到“下”篇详细说。

之所以把工程化单独拎出来写,是因为端侧 Agent 和云端 Agent 的工程化完全是两码事。云端资源可以堆,失败可以重试,内存不够可以扩容;端侧不行,内存、功耗、算力、存储都是紧巴巴的,还要面对弱网、离线、多端同步这些破事。你可以在云端把 LangChain 全家桶装上慢慢调,但到了手机、平板、车机、手表上,一丁点多余的开销都会直接反映到卡顿和发热上。所以端侧 Agent 工程化的核心就一句话:在资源预算内,把智能体的可靠性、可控性、可观测性做出来。

1. 工程化之前,先想清楚你的 Agent 到底要解决什么问题

很多团队一上来就选框架、写代码,结果做了一半发现连问题都没定义清楚。工程化不是把功能实现出来,而是把功能以可复制、可运维、可演进的方式实现出来。在动手之前,我建议你先回答三个问题:你的 Agent 跑在什么硬件上?它有什么权限?它的失败代价是什么?

1.1 端侧 Agent 和云端 Agent 的本质差异

端侧 Agent 最大的卖点是三个:隐私不出设备、离线可用、端到端延迟低。但这三个卖点每一个都是工程上的紧箍咒。隐私不出设备意味着你不能把用户数据丢到云端做兜底;离线可用意味着模型和知识库都得本地存;低延迟意味着推理必须快,而端侧芯片的算力天花板就摆在那里。

云端 Agent 工程化讲究的是弹性、高可用、多租户隔离、API 网关、限流熔断,这些词到了端侧全都变了味。端侧要面对的是:应用被杀、系统回收内存、屏幕熄灭进入低功耗状态、弱网环境下同步超时、用户手动清缓存把自己家的向量库清没了。这些不是极端情况,是每天都在发生的常态。

端侧 Agent 的并发模型也和云端不同。云端一个 Agent 服务可以同时服务成千上万个用户请求,靠的是水平扩展;端侧一个 Agent 实例基本只服务一个用户,但同一个用户的多个 Agent 可能同时跑——一个前台助手在回答用户问题,一个后台 Agent 在整理相册,还有一个定时 Agent 在跑日报总结。所以端侧“扛并发”的本质是:在单机资源内,让多个 Agent 实例并发跑起来不互相踩踏。

1.2 “能跑通”和“能上线”之间隔着的四道坎

从个人 Demo 到产品级端侧 Agent,我总结下来至少有四道坎,每一道都卡掉过不少人。

第一道坎是可控性。模型是概率系统,同样的输入今天给这个结果明天给那个结果。工程化要做的就是用约束把概率关进笼子里:输出格式不对就重试,工具参数不合规就拦截,Agent 跑飞了就强制终止。最基础的做法是给模型加 system prompt 约束,但工程上必须做结构化的校验和兜底,不能指望提示词百分百听话。

第二道坎是可观测性。Agent 是黑盒里的黑盒——你不知道它下一步要干嘛,不知道它为什么调那个工具,不知道它哪一步开始跑偏。没有日志、追踪、回放机制的 Agent 项目,出问题只能靠猜。我在实际项目中吃过一次大亏:Agent 在用户手机上半夜自动执行了一个清理任务,把用户的重要文件标记成了可删除,等用户第二天发现的时候已经晚了。事后排查时我发现整个执行过程几乎没有日志,根本定位不了是哪一步决策出了问题。

第三道坎是可演进性。模型版本要升级、工具列表要增加、技能要迭代,如果 Agent 的架构是写死的,每一次改动都是一次大手术。好的工程化应该让 Agent 的能力像搭积木一样可插拔,而不是牵一发动全身。

第四道坎是安全性。端侧 Agent 是离用户数据最近的软件,它有访问通讯录、短信、相册、定位的能力,一旦被滥用就是灾难。这里的安全不止是“防黑客”,更核心的是“防住 Agent 自己”——权限最小化、操作可撤销、敏感行为要二次确认。

2. 架构选型:harness、运行时与编排到底怎么搭

网上关于 Agent 框架的讨论特别多,概念也特别多——agent、harness、framework、runtime、orchestration,很多人被这些词绕晕了。这篇我先把最重要的两个概念掰扯清楚:Agent 和 Harness。

2.1 Harness 到底是什么,它和 Agent 有什么区别

我见过很多团队把 Agent 和 Harness 混为一谈,代码里写了一个类叫 Agent,其实干的是 Harness 的活。我的理解很简单:Agent 是你的“大脑”,负责推理和决策;Harness 是“身体和神经系统”,负责让大脑的想法变成现实行动,并且把行动的结果反馈给大脑。

具体来说,Harness 至少包含五大能力:一是调用底层模型并管理上下文窗口;二是管理工具注册表,决定 Agent 能调哪些工具、怎么调;三是执行工具调用并做参数校验、结果包装;四是维护循环控制,防止无限循环;五是做观测和中断,随时可以叫停 Agent。用工程一点的类比:Agent 是业务逻辑层,Harness 是基础设施层。

为什么要单独拆出 Harness?因为端侧 Agent 的模型可以换、工具可以换,但 Harness 的骨架是稳定的。今天你用的是 3B 模型,明天可能换成 7B 模型;今天挂了一个天气查询工具,明天可能挂一个支付工具。如果这些变化都和 Agent 的核心决策耦合在一起,改一次就要重新测一遍全链路。Harness 把变化的和不变的隔离开,这是工程化的第一步。

现在市面上的 Harness 形态已经很多了:OpenAI 的 Codex CLI 是跑在终端里的命令式编码 Agent;Google 的 ADK 是面向多 Agent 编排的 Agent Development Kit;还有 Spring AI 这类给 Java 开发者用的 Agent 基础件。这些产品各有侧重,但本质逻辑都是一样的——给 Agent 大脑配一台能走路、能说话、能拿东西的身子。我个人在做端侧项目时,还比较喜欢 Rust 系的轻量 harness 实现,内存占用小、体积可控、交叉编译方便,一套代码能覆盖手机、平板、嵌入式多个端,真正往 Agent Anywhere 方向走能省很多事。

2.2 主流框架的真实对比,端侧到底选哪个

说到 Agent 框架,绕不开 LangChain、LangGraph、CrewAI、Dify 这几个。我这几年基本都试过,也见过不同团队拿它们做端侧项目,说点真实感受。

LangChain 的生态最大,文档最多,什么问题都能搜到答案,但它的抽象层也最厚,运行时体积不小,而且版本迭代频繁,API 碎。在云端用问题不大,端侧塞这套东西,启动时间和内存都受不了。LangGraph 在编排上比 LangChain 清晰,适合有状态、有条件的流程,但对端侧来说依然偏重。

CrewAI 主打多角色协作,模拟一个团队里的不同 Agent 互相配合。这个思路很贴近真实业务,但多 Agent 之间的通信和协作开销在端侧是实打实的成本,而且每个 Agent 都要占上下文和推理资源,所以我的建议是端侧别轻易上多 Agent,能单 Agent 解决的问题不要拆。

Dify 是低代码友好的,RAG、工作流、知识库一套全包,做原型和内部工具效率很高。但它是典型的“重框架”,很多能力和数据库深度绑定,部署形态偏重,往端侧搬基本等于做一次重构。更适合的场景是:你用 Dify 快速验证产品逻辑,验证完再针对端侧做轻量化实现。

我最后给端侧项目的建议是:要么裸写一个轻量 harness,要么用极轻的运行时。我自己的项目里最终选择的是自研一个约两千行的核心 harness,外加模型服务、工具执行、记忆存储三个独立模块。这么做的好处是完全掌控资源占用,坏处是一切从零开始,工程量大。但是端侧项目最怕的就是框架绑架——框架决定了你的架构边界,而端侧的需求经常在边界之外。

2.3 一套可以直接抄作业的端侧 Agent 分层架构

我沉淀下来的一套分层架构,按职责分五层,每层只做好一件事:

第一层是交互层,负责语音、文本、事件等输入,把它们统一转换成内部消息格式。第二层是编排层,也就是 harness 的主体,负责上下文管理、工具调度、循环控制、中断恢复。第三层是技能层,把工具、提示词模板、技能脚本打包成一个个可加载的单元。第四层是记忆层,管理短期会话记忆、长期事实记忆、向量知识库。第五层是资源层,封装本地推理引擎、磁盘存储、网络同步能力。

这套架构的优点是每个层都可以单独替换。比如模型从 ONNX 换成 MNN,只动资源层的推理接口;加一个新能力,只动技能层;上下文溢出问题,只优化编排层的压缩策略。端侧系统最关键的就是这种“可替换性”,因为端侧软件的生命周期远比云端服务长,手机系统更新、芯片换代,你的 Agent 得跟着适应,不能架构上就锁死。

3. 核心能力工程化:工具调用、记忆与技能机制

Agent 的能力再花哨,落地端侧就绕不开三个基本盘:工具调用靠不靠谱、记不记得住上下文、能不能快速扩展新能力。这一节逐个聊。

3.1 工具调用不是“让模型调个函数”那么简单

很多初学者写 Agent 工具调用,在 prompt 里写“你可以调用以下工具”,然后模型返回一段 JSON,代码解析后执行,完事。这种实现到了真实场景必崩。真实场景里模型会返回非法的 JSON、参数类型不对、传超长字符串、调用一个根本没注册的工具,还会连环调用互相对喷。

工程化的工具调用至少要做四件事。第一,工具描述结构化:每个工具都要有标准的 JSON Schema 描述,包括参数名、类型、取值范围、必填项、描述,让模型好理解也方便校验。第二,参数严格校验:模型返回的参数在执行前必须过一套校验器,不合法就返回对应的错误提示给模型,让它重新生成。第三,执行超时兜底:每个工具调用都要有超时时间,超过就中断并通知模型,避免工具卡住整个 Agent 循环。第四,幂等控制:同一个工具可能被模型重复调用,必须有幂等机制,最典型的例子是支付类工具,重复扣款是无法接受的。

还有个细节容易被忽略:工具失败信息的反馈格式。模型需要知道工具为什么失败,才好重新决策。经验是尽量把失败原因结构化,比如错误码加一个简短的错误描述,而不要甩一整段堆栈给模型。模型看堆栈是看不懂的,它只会更晕。

3.2 记忆体系怎么在端侧落下来

记忆是 Agent 工程化里最容易被低估的一块。Demo 阶段你只需要把用户最近几轮对话扔给模型,但产品阶段你需要让 Agent 记住用户的偏好、上次没完成的任务、知识库里的最新内容,还得保证这些记忆不泄露隐私、不占用太多存储。

我个人推荐三层记忆架构。短期记忆是当前会话的上下文窗口,用环形缓冲管理,超出窗口就做摘要压缩。中期记忆存用户在当前交互周期内的任务状态和临时偏好,比如“用户正在规划周末旅行,偏好海边”,存在 SQLite 里,带过期时间。长期记忆是用户画像和持久知识,比如用户的工作、家庭、常用地点,存在嵌入向量库或结构化表里,更新要走用户确认。

端侧记忆工程化的难点在于存储空间和检索效率的平衡。一个四五百万条的向量库,索引建起来轻松几百 MB,手机存储根本吃不消。实际做法是分层存储:高频记忆存内存或极速存储,低频记忆用压缩结构存磁盘,最老的记忆定期清理出系统。记忆不等于永久保存,端侧的记忆必须有生命周期,这个观念要一开始就建立,否则后面数据膨胀到不可收拾。

记忆还有一个大坑:多端同步。手机上有记忆,平板上没有,用户就会觉得 Agent“换一个设备就失忆”。工程上这是个分布式一致性问题,简单方案是增量同步加冲突处理,复杂方案是云上做中心化记忆仓,端侧只缓存热数据。但云端一介入,隐私优势就打了折扣,所以这个平衡点要产品来定,技术只能给出折中方案。

3.3 Skill 机制:把能力做成即插即用的标准件

今年 Agent 圈子里“Skills”这个概念火得不行,Claude 的 Agent Skills 机制出来后,很多团队开始把技能打包成标准化单元。我在自己的项目里也完整借鉴了这套思路,效果非常好。Skill 本质上是一个自包含的能力包:一个描述文件说明这个技能什么时候用、怎么用;一组提示词模板告诉模型怎么执行;一组工具脚本干具体的活;一个校验器检查执行结果。

举个例子,我要给 Agent 加一个“分析网页并保存为 Markdown”的能力,不需要改任何核心代码,只需要做一个 Skill 目录:描述文件里写清楚适用场景和输入要求,脚本里写清楚怎么抓取、怎么转换、怎么把结果落到本地。Agent 在推理时如果发现当前任务匹配这个技能,就自动加载并执行。这种机制让 Agent 的能力扩展从“改代码发版”变成了“热插拔装配”,运营同学也能参与到技能设计里。

但 Skill 机制有个安全副作用:技能包是外部加载的可执行代码,相当于给 Agent 装了一个插件系统。插件能干什么、不能干什么、访问哪些路径,必须有一套沙箱机制管住。我当时直接把技能脚本丢给系统执行,结果一个技能包里的路径清理逻辑把另一个技能的数据目录给误删了。后来清零重写,才意识到隔离是 Skill 机制的第一优先级。现在我的技能沙箱里强制做三件事:文件访问只能落在技能专属目录、网络访问只允许白名单域名、子进程超时强制回收。

3.4 多 Agent 协作的工程代价,能单就别多

热词里“多 Agent”出现频率很高,很多团队看到多 Agent 架构就想上。我的态度很明确:端侧能单 Agent 解决的,绝对不要拆多 Agent。原因有几点:每多一个 Agent,就要多一份上下文窗口、多一份推理开销、多一层通信复杂度。手机上跑两个 7B 模型同时推理,发热和耗电基本是灾难级的。

真需要多 Agent 协作,那也要做角色裁剪。比如主 Agent 负责任务理解,通过工具调用的方式“借用”其他 Agent 的专项能力,而不是真的让两个独立模型在那里对话。这种“伪多 Agent”模式在端侧非常适用:既有了专业化分工,又避免了多模型并行推理的资源爆炸。工程实现上,主 Agent 维护一个子 Agent 的结果池,子 Agent 的结果作为工具返回值回到主 Agent 的上下文里,整个流程依然收敛在单推理链路里,成本和风险都可控。

4. 资源受限下的并发与性能:端侧“扛并发”到底怎么扛

前面说了,端侧的并发和云端不一样,这里的“并发”是指多个 Agent 实例、多种任务类型在同一台设备上同时跑的工程问题。手机不是服务器,它没有 64 核 CPU 和 256G 内存,要在这样的环境扛住并发,必须一毫一秒地精打细算。

4.1 模型选型与延迟预算的计算方法

模型选型是性能工程的地基。端侧常用的是量化后的 1B、3B、7B 参数模型,经验公式是:模型内存占用约等于参数量乘以量化位数除以 8。7B 模型用 INT4 量化大约占 3.5GB 内存,用 INT8 就是 7GB。3B 模型 INT4 才 1.5GB,手机完全能扛,7B 就得看设备内存规格了。我做过一个内存预算表,可以参考:旗舰机 12GB 内存,系统占用约 5GB,Agent 运行时加模型推理最多只能再吃 5GB 左右,剩下要留给其他 App。

延迟预算上,交互类任务的端到端延迟要控制在 500ms 到 1s 以内,包含语音识别、推理、工具执行等全部环节。这意味着纯推理延迟不能超过 200ms。在这个预算下,3B 量化模型在旗舰芯片上勉强够用,7B 就必须上推理加速方案了。工程上还有一招:模型常驻。模型热加载一次要两三秒,用户每次交互等两秒是灾难性的,所以模型要启动时预加载,保持在内存里,哪怕不跑任务也占着。这就要跟系统内存博弈,你占着不释放,可能被系统判为高耗电应用,非常考验资源管理。

4.2 端侧并发模型的一个靠谱设计

我最终采用的并发模型是“单推理引擎 + 多任务队列 + 会话隔离”。推理引擎只有一个,所有 Agent 任务的模型推理都走它,但任务分成前台交互优先、后台任务低优先级、定时任务最低优先级三类。前台任务抢占推理资源,后台任务在推理间隙执行,定时任务在设备空闲时批量跑。这个设计解决了同设备的多个 Agent 抢资源的问题,实际体验下来很稳。

会话隔离同样重要。每个任务会话必须有独立的上下文缓冲、工具调用记录和执行状态,互不干扰。这个看起来简单,但牵涉到很多细节:你不可能让后台做文档总结的上下文和前台聊天的上下文互相污染;工具调用栈也不能共享。实现时我用了一个全局唯一的会话 ID 把所有数据打标,从输入到工具执行到记忆写入全链路绑定,这才彻底把并发问题理顺。

流式输出也是扛延迟的利器。用户体感上,首字出来得快比整句完成得快要紧得多。端侧推理用流式解码,第一个 token 大概几十毫秒就能出,用户可以立刻看到反馈。这个不是技巧,是端侧 Agent 交互体验的刚需。当年我们第一批版本是等待全文生成完再一次性吐出,用户反馈就是“这 Agent 怎么卡卡的”。改成流式之后,同样是 800ms 的总耗时,用户评价直接变了个样。

4.3 内存、功耗与发热的调优实战

端侧性能工程里最折磨人的不是快不快,而是热不热、废不废电。推理是高负载任务,跑一个 3B 模型,芯片功耗轻松拉到几瓦,连跑几分钟手机就明显发热。这里有几个经验:限制推理频率,两个任务之间加最小间隔;批量推理,把可以合并的任务放进一个 batch 里一次算完;动态降频,检测到设备温度高时自动降低推理精度或强制进入低功耗模式。

还有一个很容易忽视的坑:后台任务不能偷偷跑。后台 Agent 如果每隔几分钟就调一次模型,一个晚上能把手机耗掉大半格电。我的方案是后台任务全部交给“充电时执行 + 用户空闲时段执行”的调度器,完全避开用户正在使用手机的时间窗口。这个策略上线后,用户对耗电的抱怨基本清零。端侧 Agent 工程化说白了不是使劲塞功能,而是学会在没有余量的环境下克制。

5. 端侧 Agent 的安全防线:权限、数据与鲁棒性

Agent 安全这个题,越做越觉得水深。之前网上对 Agent 安全的讨论大多集中在提示注入、工具滥用这些偏攻防的领域,但端侧 Agent 真正要解决的是三个工程问题:权限怎么收、数据怎么防、失败怎么兜底。

5.1 权限设计:给 Agent 的权力清单画一条边界线

端侧 Agent 必须有权限清单机制,不能让它想干什么就干什么。我的做法是分三级权限:基础权限自动授予,比如查询天气、读取系统信息;中危权限要用户确认,比如发送消息、修改文件、访问通讯录;高危权限强制二次验证,涉及支付、删除数据、发布内容必须用户显式批准。

工程实现上是一个权限模块,所有工具执行前都要过这一关。模块维护一个权限表,每个执行请求匹配工具、操作类型、作用对象后,再决定是放行、询问还是拒绝。注意“作用对象”很关键:Agent 读取通讯录里的联系人名片可以放行,但读取通讯录然后生成一个“用户人际关系网”文档,这个行为就触碰了中危权限边界,必须停下来问用户。

还有一点,权限不能被用户授权一次后就永久放行。端侧 Agent 的权限要有有效期和上下文限定。比如用户允许了“本次发送一条消息”,不代表允许这个 Agent 以后随时都可以发消息。权限上下文超时自动回收,这个机制能避免很多潜在问题。

5.2 数据隔离:Agent 的数据不能和系统数据混在一起

端侧 Agent 访问了大量个人数据,这些数据的存储和流转必须做隔离。设计上分三类:Agent 自己的数据,比如技能包、记忆库、向量索引;用户数据的缓存副本,比如从相册分析出来的图片向量;系统级的敏感数据,比如用户的账号信息、支付凭证。三类数据存储位置分开,访问路径分开,加密密钥也分开。

加密这块我用的方案是:Agent 的数据默认用设备级密钥加密,用户敏感数据换用户级密钥单独加密,密钥本身存在系统安全硬件里。有人觉得手机本地端侧没必要加密,反正数据不出设备,这个想法太天真了——数据不出设备指的是你不主动上传,但你的设备可能被别人拿去刷机、ROOT、物理窃取。数据加密的成本不高,但能挡住一大票物理攻击场景。合规价值也更扎实。

防数据泄漏的另一个重要点是日志。Agent 的日志里往往带着用户数据,我遇到过调试日志把用户完整对话内容打印出来的事故。现在项目里的日志库强制做脱敏:邮箱、手机号、地址、身份标识自动打码,整段明文数据不允许进日志。宁可调试不方便,也不能把用户隐私当儿戏。

5.3 失败兜底:Agent 执行中止了怎么办

端侧 Agent 经常遇到执行中止,比如模型推理到一半手机内存告急、工具调用卡死、系统杀掉了后台进程。用户侧看到的现象就是“Agent 突然不说话了”或者“执行到一半停了”。这种体验一次两次可以接受,次数多了用户就卸载了。

兜底方案要分层做。最低层是 harness 级别的 watchdog,监控每个工具调用的超时和异常,异常时把状态回滚到上一安全点。上一层是会话级别的恢复机制,Agent 的每一步决策都记录下来,重启后可以恢复继续执行。最上层是用户界面层,Agent 中止时给用户一个透明的状态提示:是“正在重试”、是“执行成功但部分结果丢失”、还是“需要用户介入决策”。透明永远是第一位的,不要让用户对着一个黑屏干等。

我做任务状态机的时候吃过一个亏:Agent 执行一个多步任务,第一步完成后写了状态,第二步失败了,我直接报错。结果用户重试的时候,第一步被重复执行了。后来给每个任务加了幂等 ID 和步骤完成标记,重试时直接从断点继续。所以我说 Agent 工程化本质上是一个可靠性工程问题,把自己的系统当分布式系统设计,幂等、状态持久化、断点续跑,这些一个都不能少。

6. 工程化远景:从 Agent 内核到 Agent Anywhere

聊到这里,端侧 Agent 工程化的上半场基本讲完了,但有一件事我想最后提一嘴:工程化做得好,收益不只是“你有一个好用的 App 内助手”。好的端侧 Agent 内核,天然具备跨端复用的能力。

6.1 同一个内核跑在不同设备上的架构红利

我见过不少团队做多端 Agent 的方法是:手机端一套代码,PC 端一套代码,车机再一套,三个版本互相不认识,功能对齐全靠人肉。这种做法的本质问题不是代码重复,而是能力没有形成资产。

如果在工程化阶段就把 Agent 核心做成一个无所依赖、可移植的事件驱动引擎,跑在手机上有手机的形态,跑在手表上有手表的形态,跑在智能座舱上有座舱的形态,那么 Agent 的能力只写一次,所有端共用,这才是真正的 Agent Anywhere。我的实践是核心层不直接依赖任何 UI 框架和系统 API,UI 适配完全在交互层做掉。核心层只是输入输出事件的搬运工,这样移植一个新端基本只要写交互适配代码,一周时间足够从零跑通。设备之间的一致性也大幅提升:用户在这个设备加了一个技能,其他设备同步后立刻可用。

6.2 做工程化的人,要有一点“造平台”的心态

做了几年端侧 Agent,我最大的体会是:光把功能做出来不算数,要能沉淀出别人也能复用的结构才叫工程化。每一次新需求进来,先想能不能抽象成通用能力挂到技能层;每一次工具调用出问题,先想是这一个工具的 bug 还是工具框架的机制漏洞;每一个新环境的适配,先想是不是核心层没做好环境隔离。

工程化是很枯燥的,它没有模型算法的光鲜,也没有产品交互的亮眼,它就是一遍一遍打磨边界、补齐异常、优化资源。但端侧 Agent 时代刚刚开始,这波浪潮里真正能把产品做稳的团队,一定是工程化底子最好的团队。这篇先写了架构、harness、技能、记忆、并发、安全这六块,调试、评测、监控、灰度这些运维侧的工程化内容,下篇继续聊。在做端侧 Agent 的朋友,如果你们也在架构、框架选型或者资源优化上踩过什么坑,欢迎交流各自的解法,这个方向值得大家把经验都摊开来看一看。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询