AI Agent 工程化总览篇:从 Prompt 到 Harness

本文以 Cherry Studio 的 AI 运行时为例,说明 Prompt Engineering、Context Engineering、Loop Engineering、Harness Engineering 如何从单一提示词演化为可上线的 Agent 系统。

写在前面:为什么要研究别人的 Agent

笔者所在团队正在实现一款 AI 桌面端工具,既要把 Chat 做顺手,也要让 Agent Work 能真正接住多步骤任务。

说起来很美好:聊天、查资料、调工具、改文件、等审批、任务中断后继续跑......把这些关键词写在需求里只要一分钟,真正落到工程里却是一串连续的"那这个谁来管?"。

本着"他山之石,可以攻玉"的想法,团队选择研究社区内成熟的开源实现。Cherry Studio 已经把多模型调用、Chat、Agent Session、工具、知识库和运行时控制串成了一条相对完整的链路,非常适合作为拆解 Agent 工程问题的样本。

本文不是要照搬某个产品,而是想借它的实现回答一个更朴素的问题:

一个 AI 桌面端工具,怎样从"能聊两句",走到"能把事办完,而且别把事办砸"?

从 Chat 到 Agent Work:为什么只会写 Prompt 不够

早期 LLM 应用通常只有一个输入框和一段系统提示词:

text 复制代码
用户问题 + System Prompt → 模型回答

这足以完成一次性问答。可当 Agent Work 要开始调用工具、读取用户资料、跨会话记忆、等待审批,甚至在失败后恢复时,事情就不是"再补两句 Prompt"这么简单了。

AI Agent 的工程化可以拆成四层:

text 复制代码
Prompt    定义目标、角色和行为策略
Context   提供当前任务所需的可信事实
Loop      推进「思考---行动---观察---继续」的任务过程
Harness   约束工具、权限、生命周期和可观测性

它们的分工很明确:

  • Prompt 告诉模型应当做什么,但不能强制模型只做允许的事。
  • Context 提供证据,但不能决定任务何时结束。
  • Loop 让模型完成多步任务,但不能替代权限和审批。
  • Harness 可以限制和托管模型行为,却不能弥补错误的目标与缺失的事实。

所以,成熟的 Agent 产品不是"更长的 Prompt",而是四层共同组成的运行系统。

Agent 能力是怎样一步步长出来的

Prompt Engineering:先让模型听懂人话

第一阶段最直观:角色设定、输出格式、few-shot 示例、约束和拒答策略,能写的先写进 Prompt。

它解决的是模型"不知道应该如何回答"的问题,但存在明显边界:

  • 事实会过期,Prompt 不能承担知识库。
  • 用户偏好和项目约定跨会话丢失。
  • Prompt 无法可靠限制文件写入、网络访问等副作用。
  • 工具调用成功与否、重试次数和结束条件无法仅靠自然语言约束。

Prompt 仍是 Agent 的行为契约,但不应被误认为安全策略或状态机。

例如"删除文件前请先确认"可以写在 Prompt 中;真正拦住删除动作的,必须是运行时权限和审批。

Context Engineering:再让模型看到该看的东西

随着上下文窗口和 RAG 出现,问题从"如何说清要求"变成"此刻到底该把什么交给模型"。

Context Engineering 关注:

  • 对话历史的选择、截断、压缩和分支。
  • 文件、图片、网页、代码工作区等附件的表示方式。
  • 长期记忆与临时事件的分层。
  • 知识库的按需检索、引用与权限范围。
  • 工具结果的大小、可信度和生命周期。

把聊天记录、附件和知识库切片一股脑灌进去,看似省事,token 和噪声却会很快失控。

关键原则不是"尽可能多放入上下文",而是让模型在当前步骤拿到最少但足够、可追溯的证据

Loop Engineering:工具会调了,也得知道什么时候停

当模型可以调用工具后,单次请求演化为循环:

text 复制代码
模型决定下一步
  → 调用工具
  → 获得工具结果
  → 基于结果继续推理、再次调用工具或结束

Loop Engineering 的工作,就是把这个过程变成可控制的程序:步数上限、停止条件、错误语义、取消、用户插话、暂停审批和结果流式传输。否则 Agent 很容易从"认真办事"变成"原地转圈"。

Harness Engineering:最后,得有人给它划边界

真正上线的 Agent 还需要一个运行 Harness,把模型能力放在受控边界中:

  • 哪些工具可见、可调用、需要审批或被禁用。
  • 哪些目录、知识库和 MCP 服务可访问。
  • 会话如何创建、续接、恢复、取消和持久化。
  • 工具执行、模型调用、失败和成本如何观察。

Harness 是从可演示 Demo 走向可靠产品的分水岭。模型可以提出动作,但最终能不能做、怎样做,不能只由模型说了算。

把原理落回 Cherry Studio

Prompt:从一段文案到可组合的行为契约

Cherry Studio 有两条主要运行路径:

  • 通用 Chat 基于 AI SDK 的 Agent
  • Agent Session 由 AgentSessionRuntimeService 托管,并可使用 Claude Code Runtime Driver。

通用 Chat 的系统提示词由 buildAgentParams 调用 assembleSystemPrompt 组装,包含 Assistant 指令和延迟暴露工具的指引。参数、工具、模型适配插件和 Hook 由同一参数管线构造,详见 Params Pipeline

Agent Session 的 Prompt 更接近"个人 Agent 的操作手册"。PromptBuilder 会组合:

  1. 工作区 system.md 或内置身份提示。
  2. Web、自动化、Memory 等工具使用策略。
  3. 用户自定义 instructions。
  4. 工作区、语言、频道安全和运行环境信息。
  5. Agent 身份与长期记忆文件。

其身份和记忆文件分工明确:

文件 语义 上下文策略
SOUL.md Agent 的角色、语气、原则与边界 每次系统提示词加载
USER.md 用户偏好、称呼、时区和个人背景 每次系统提示词加载
memory/FACT.md 长期事实、项目决策和可复用经验 每次系统提示词加载
memory/JOURNAL.jsonl 一次性事件和会话日志 仅通过工具按需检索

这种设计避免了把所有历史事件永久塞入 Prompt,同时让稳定的身份和长期事实跨工作区、跨会话保留。

这一层的落地要点

  • Prompt 只表达行为目标、策略和解释;权限必须由运行时强制。
  • 将稳定信息与易变信息分开。易变信息应通过 Context 或工具读取。
  • 对 Prompt 建立版本、评审和回归用例,而不是把它当作不可测试的字符串。
  • 给工具提供明确的使用时机和失败处理指引,避免模型盲目重试。

Context:按需取证,而非整库灌入

Context 是一次模型调用真实可见的信息集合,不等同于聊天历史。

Cherry Studio 的 Chat 通过 ChatContextProvider 为不同 topic 类型准备请求:持久聊天、临时聊天和 Agent Session 各自拥有不同的持久化与派发逻辑。完整调用路径见 Core Architecture

知识库使用 Agentic RAG,而非预先把所有检索文本插入 Prompt:

text 复制代码
kb_list
  → 发现知识库和资料结构
kb_search
  → 返回少量相关 chunk 与 conceptId
kb_read
  → 读取全文、分页或 grep,核验上下文
模型回答
  → 引用检索结果

该工具链的共享实现位于 src/main/ai/tools/knowledgeLookup.ts,底层由 KnowledgeService 查询本地知识库。知识库绑定是范围上限:每轮在 Composer 中选择的库只能收窄范围,不能扩大 Agent 已绑定的可见范围。

这与"把全部资料切片后塞入 system prompt"相比有三个收益:

  1. 控制 token 消耗和上下文噪声。
  2. 允许模型先发现资料,再深读证据。
  3. 可以把来源、conceptId 和原文定位传递到最终回答。

这一层别图省事

  • 将长期身份、当前任务、资料检索和工具结果放入不同 Context 层。
  • 对 RAG 分别评估召回率、引用正确性、答案正确性和延迟;不要只评估"回答看起来是否合理"。
  • 资料库、工作区和用户数据必须有明确 scope;UI 限制不是安全边界,主进程仍应校验。
  • 大文件和长历史要可分页、可压缩、可回读,而不是无限增长。

Loop:把模型调用变成可终止的任务过程

AI SDK 路径中的 Agent 包装了 ToolLoopAgent。它对一次流式执行提供:

  • stopWhen:步数上限和特性贡献的停止条件。
  • prepareStep:每一步开始前改写或补充请求。
  • onStepFinish:汇总 usage、记录步骤结果。
  • onToolExecutionStart / onToolExecutionEnd:围绕工具执行的观测。
  • onFinishonAbortonError:区分正常完成、取消和错误。

该 Agent stream 是单次流式执行,不会把新用户消息直接注入正在进行的普通 Chat Loop。普通聊天的 steering 由 Stream Manager 在上层处理:当前执行安全结束后再启动 continuation。Agent Session 则有自己的 follow-up 队列和 Driver 能力;Claude Code Driver 可在下一次工具调用前通过 PreToolUse 注入 steer。

这一区分很重要:用户插话不是简单 append 一条消息,而是会影响当前执行的边界、持久化顺序和是否需要重新构造上下文。

这一层最怕边界不清

  • 定义可观测的终止状态:成功、步数耗尽、用户取消、等待审批、不可重试失败。
  • 不把所有错误当作 retry;工具失败、权限拒绝、模型错误和用户取消有不同处理路径。
  • 对每个 Loop 设置预算:最大步骤、最大耗时、最大工具调用数和 token/cost 上限。
  • 把用户 steering 设计为有明确边界的状态迁移,避免修改正在执行的历史。

详细实现见 Agent LoopAgent Session Runtime

Harness:将 Agent 放进可管理的产品运行时

Harness 不是单个类,而是一组控制面和运行时宿主能力。

text 复制代码
模型请求
  → 工具选择与策略
  → 权限检查 / 用户审批
  → MCP 或本地工具执行
  → 流式事件、持久化与可观测性
  → UI 与外部渠道

Cherry Studio 的关键组成包括:

能力 实践
工具面 Tool Registry 管理内置工具、MCP 工具和延迟暴露元工具;Claude Code Runtime 通过 MCP bridge 提供对应工具。
权限与审批 工具可声明 needsApproval;Main 是审批状态唯一写入者,Renderer 只提交用户决定。
工作区边界 Agent Session 使用 workspace 作为 cwd,并对越界路径和高风险工具执行额外检查。
会话宿主 AiStreamManager 管理流、订阅、取消和持久化;AgentSessionRuntimeService 管理长生命周期 Agent Session。
外部生态 MCP Runtime 管理用户配置的 MCP server、工具目录和 OAuth 等连接生命周期。
可观测性 AI SDK / Claude Code 路径可接入 trace、usage 记录和工具执行事件。

工具审批体现了 Harness 的核心原则:模型能够提出动作,但不能自行绕过产品授权。对于需要确认的调用,运行时将 stream 置于等待状态;用户决定后由 Main 恢复或拒绝执行。详见 Tool Approval

这一层必须足够硬

  • 最小权限原则:只暴露当前任务真正需要的工具、目录和知识库。
  • 把"模型建议执行"与"系统实际执行"分离。
  • 对破坏性工具、网络写入、凭据访问和工作区外文件操作设置强制审批。
  • 保留端到端 trace,至少覆盖模型调用、工具调用、审批等待、失败和成本。
  • 将运行时能力和具体模型/SDK 解耦,使 Provider 或 Agent Driver 可替换。

四层合起来,任务是怎么跑完的?

下面是一条"查询私有技术文档并生成答案"的简化路径:

text 复制代码
Prompt
  → 说明何时应查询资料、如何引用来源
Context
  → 当前用户问题、会话历史、知识库 scope
Loop
  → kb_list → kb_search → kb_read → 生成答案
Harness
  → 只开放已授权 kb_* 工具;记录工具调用;处理审批和取消

如果其中任何一层缺失,系统都会退化:

缺失层 典型后果
Prompt 模型不知道何时检索、何时停止或如何表达引用。
Context 模型只能猜测,或因上下文过多而被噪声干扰。
Loop 工具调用无法形成多步任务,错误和取消语义混乱。
Harness 模型拥有不受控的副作用,难以审核、恢复和运维。

开工前,先过一遍这张清单

在为一个新 Agent 功能投入开发前,先把下面的问题过一遍。

别等工具都接完了,才开始讨论"审批放哪儿""中断以后怎么办"。

Prompt

  • 模型的目标、边界、输出格式和工具策略是否明确?
  • 哪些内容必须随产品版本更新,哪些属于用户可配置指令?

Context

  • 当前调用真正需要哪些历史、附件、记忆和资料?
  • 敏感数据、知识库和工作区的 scope 是否由服务端验证?
  • 每个检索结论能否回到原始证据?

Loop

  • 何时完成、暂停、重试、取消和失败?
  • 是否定义了步骤、时间、工具和成本预算?
  • 用户在执行中补充要求时,状态如何安全迁移?

Harness

  • 工具是否最小化暴露,危险动作是否需要审批?
  • 模型、工具、会话、流和持久化分别由谁拥有?
  • 是否能追踪一次任务的模型调用、工具输入输出、审批和成本?

小结

Prompt Engineering 仍然重要,但它只是 Agent 工程的开始:

Prompt 定义目标,Context 提供证据,Loop 推进任务,Harness 约束行动。

Cherry Studio 的价值不只在于连接多个模型,也在于将提示词、上下文、工具循环和运行时控制拆分为独立但协同的系统。对正在建设 AI 桌面端工具的团队而言,这种拆分能让 Agent 能力从"改一段 Prompt 的试验"走向可评审、可测试、可观测和可持续演进的软件工程。

继续阅读

相关推荐
2501_926978332 小时前
以说明书 DNA 为模板——完整 AGI 的结构图景
前端·人工智能·经验分享·笔记·ai写作
IT_陈寒2 小时前
Vite静态资源引用这个坑我踩得有点疼
前端·人工智能·后端
天天爱吃肉82182 小时前
商用车多体动力学实战笔记|第6篇:动力传动系统(发动机、变速箱、分动器、TCS、LSD限滑差速)
大数据·人工智能·笔记·python·嵌入式硬件·汽车
程序员黑豆3 小时前
鸿蒙应用开发:AttributeModifier 使用教程
前端·harmonyos
把所有砖敲烂3 小时前
DeepSeek V4正式版发布,教你在Codex中配置Flash
人工智能·产品
wyg_0311133 小时前
从0搭建极简transformer大模型
人工智能·深度学习·transformer
codeniu3 小时前
TRAE Work 实战 | 从"有个想法"到线上Demo,我全程只靠对话就完成了
前端·trae
妙码生花3 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(五十):增加管理员角色组管理
前端·后端·ai编程
飘尘3 小时前
一文讲清楚前端面试会问到的所有缓存
前端·javascript·面试