AI 编程智能体真正难做的地方,不只是让大语言模型(LLM,大语言模型)会写代码,而是让它在复杂项目里长期、稳定、安全地工作。
一次简单问答里,模型只需要根据当前输入生成答案;但在真实工程任务中,它要理解项目约定、读取代码、规划修改、运行命令、处理报错、记住用户偏好,还要避免误删文件、泄露凭证或在错误目录执行危险命令。只靠提示词,很难把这些问题全部解决。
Harness Engineering 解决的就是这个问题:在模型外面加一层“控制系统”,负责上下文组装、工具调度、权限控制、状态恢复、沙盒隔离和多智能体协作。模型负责推理,Harness 负责把推理变成可审计、可回放、可约束的工程流程。
flowchart LR
User[用户目标] --> Harness[Harness 控制层]
Harness --> Context[上下文管理]
Harness --> LLM[Claude / LLM]
Harness --> Permission[权限与风险控制]
Harness --> Sandbox[Sandbox 执行环境]
Harness --> Session[(Session 事件流)]
LLM --> Harness
Sandbox --> Harness
Session --> Harness
Harness Engineering 解决的核心矛盾
AI 编程智能体同时面对三类约束:
| 问题 | 具体表现 | Harness 需要做什么 |
|---|---|---|
| 上下文有限 | 项目规则、历史对话、代码片段都塞进上下文会超出窗口 | 选择、压缩、分层存储、按需检索 |
| 行为不可完全预测 | 模型可能忘记规则、误判命令风险、过早修改代码 | 用工作流、权限系统、生命周期钩子约束行为 |
| 执行环境有风险 | 命令可能破坏文件,代码可能读取敏感信息 | 用 Sandbox 隔离执行,用 Vault 管理凭证 |
可以把 Harness 理解成“驾驶辅助系统”:模型是司机,Sandbox 是道路和车辆,Session 是行车记录仪,权限系统是限速和刹车规则。司机仍然做决策,但关键操作不能完全靠记忆和自觉。
上下文工程:让模型只看到当前最该看的东西
AI 编程任务里,上下文既是能力来源,也是成本来源。给得太少,模型不知道项目约定;给得太多,模型会被噪声干扰,还会浪费 Token(模型上下文计量单位)。所以,上下文工程的目标不是“尽量多塞”,而是“把信息按价值和时效组织好”。
持久化指令文件:把项目规则写进仓库
如果每次会话都临时告诉智能体代码风格、测试命令、禁止事项,规则很容易遗漏。更稳妥的方式是把长期有效的约定写成项目文件,例如 CLAUDE.md、AGENTS.md 或类似的指令文件。
一个简化示例:
# 项目开发约定
## 代码风格
- TypeScript 开启 strict 模式,不允许使用 any 规避类型错误。
- 提交前必须运行 npm run lint 和 npm test。
## 修改边界
- 不要修改 generated/ 目录下的文件。
- 数据库 migration 需要单独说明风险。
## 常用命令
- 安装依赖:npm install
- 单元测试:npm test
- 类型检查:npm run typecheck
这类文件解决的是“重复告知”的问题。它让智能体每次进入项目时都能获得稳定规则,减少同样错误反复发生。
代价也很直接:指令文件会过期。项目结构、测试命令、目录约定变化后,如果文件没有同步更新,智能体会被旧规则误导。
作用域上下文组装:组织规则、项目规则、任务规则分层加载
真实团队里的规则通常不止一层:
- 组织层:安全要求、代码审查标准、许可证约束。
- 项目层:目录结构、构建命令、测试命令。
- 模块层:某个服务、某个包的内部约定。
- 任务层:本次修改的目标、限制和验收标准。
如果把所有规则都堆在一个文件里,可读性会越来越差。更好的做法是按作用域拆分,再由 Harness 根据当前目录和任务动态组装上下文。
flowchart TD
Task[当前任务] --> Assembler[上下文组装器]
Org[组织级规则] --> Assembler
Repo[项目级规则] --> Assembler
Module[模块级规则] --> Assembler
History[相关历史记录] --> Assembler
Assembler --> Prompt[发送给 LLM 的上下文]
这种设计让模型拿到的规则更贴近当前任务。例如修改 packages/api 时,加载 API 服务约定;修改前端组件时,加载 UI 规范。
它的风险是规则冲突。组织层说“必须运行全量测试”,项目层说“只运行受影响测试”,任务层又说“跳过测试先看 diff”,Harness 需要有清晰的优先级策略,否则模型会不知道听谁的。
常见优先级可以这样定:
| 优先级 | 规则来源 | 说明 |
|---|---|---|
| 最高 | 系统安全策略 | 例如禁止泄露密钥、禁止执行危险命令 |
| 高 | 用户本次明确要求 | 例如只读分析、不修改文件 |
| 中 | 项目指令文件 | 例如测试命令、代码风格 |
| 低 | 历史偏好和经验 | 例如常用实现方式、输出格式偏好 |
分层记忆:热点摘要、按需细节、完整历史分开存
长期任务不能把所有历史都放进上下文。分层记忆的思路是:不同信息有不同访问频率,应该放在不同层。
flowchart TD
L1[常驻摘要<br/>当前目标、关键约束、最新结论]
L2[按需细节<br/>相关文件、调试过程、设计讨论]
L3[完整历史<br/>事件流、聊天记录、工具结果]
L1 --> Prompt[当前上下文]
L2 -->|检索命中后加载| Prompt
L3 -->|搜索 / 回放| L2
三层可以这样理解:
| 层级 | 存什么 | 何时使用 |
|---|---|---|
| 常驻摘要 | 当前目标、用户明确要求、关键决策 | 每轮都带上 |
| 按需细节 | 某次排错过程、某个文件分析、某段设计讨论 | 当前任务需要时加载 |
| 完整历史 | 原始对话、工具调用、命令输出 | 搜索、审计、恢复状态时使用 |
这样做能节省 Token,也能减少无关信息干扰。代价是实现复杂度会上升:需要判断哪些信息该提升为摘要,哪些信息该沉入历史,还要保证索引和原始数据一致。
后台整理:让记忆系统持续清洁
长时间运行后,记忆里会出现重复、过时、冲突的信息。例如模型曾经记录“测试命令是 npm test”,后来项目改成了 pnpm test;如果两条记录都存在,后续任务会受影响。
后台整理可以定期做几件事:
| 操作 | 作用 |
|---|---|
| 去重 | 合并重复结论,减少噪声 |
| 过期检测 | 标记可能已经失效的规则 |
| 冲突发现 | 找出互相矛盾的记忆 |
| 重写摘要 | 把零散信息整理成更短、更准确的摘要 |
| 建立索引 | 让后续检索更快命中相关内容 |
这个过程很像垃圾回收。它能让长期记忆保持可用,但不能无代价运行:整理本身消耗计算资源,也可能把低频但重要的信息误删。所以关键事实最好保留原始证据,摘要只是索引和压缩后的视图。
渐进式上下文压缩:越新的信息越详细
长对话中,最近几轮通常最重要,较早内容只需要保留结论。渐进式压缩按照时间距离处理信息:
flowchart LR
Recent[最近对话<br/>保留完整细节]
Middle[稍早对话<br/>压缩为过程摘要]
Old[更早对话<br/>只保留关键结论]
Archive[(完整事件归档)]
Recent --> Prompt[当前上下文]
Middle --> Prompt
Old --> Prompt
Archive -.需要细节时检索.-> Prompt
例如一个修复 Bug 的任务:
- 最近对话保留完整报错、文件路径、失败测试。
- 稍早内容压缩成“已排除数据库连接问题,问题集中在缓存失效逻辑”。
- 更早内容压缩成“目标是修复用户资料更新后页面仍显示旧数据”。
压缩一定会损失信息。如果后续又需要某个细节,模型可能因为看不到原始内容而猜测。所以压缩后的摘要应该能指回完整事件流,让 Harness 在需要时重新取回原始证据。
工作流编排:把复杂任务拆成可控阶段
复杂代码修改不能一上来就让模型写文件。更可靠的方式是把任务拆成阶段,每个阶段有不同权限和产物。
探索、规划、行动三阶段
flowchart LR
Explore[探索<br/>只读权限<br/>理解代码和问题] --> Plan[规划<br/>列修改方案<br/>和用户对齐]
Plan --> Act[行动<br/>获得写权限<br/>修改、测试、提交结果]
三个阶段的边界很重要:
| 阶段 | 允许做什么 | 不允许做什么 | 产物 |
|---|---|---|---|
| 探索 | 读文件、搜索、运行只读命令 | 修改文件、安装依赖、删除内容 | 问题定位、影响范围 |
| 规划 | 给出修改步骤、风险、验证方式 | 擅自执行高风险操作 | 可确认的计划 |
| 行动 | 编辑文件、运行测试、修复错误 | 超出计划大改架构 | 代码变更、测试结果 |
这种流程适合不熟悉的代码库、跨模块修改、数据库变更和安全相关任务。它会让小任务显得慢,例如改一个拼写错误不一定需要完整三阶段,所以 Harness 可以根据任务风险调整流程强度。
上下文隔离子智能体:不同角色不要共享全部上下文
有些任务需要多个阶段或多个角色,例如“调研方案”和“执行修改”。如果所有信息都塞给同一个上下文,模型可能被中间猜测、废弃方案和临时日志污染。
上下文隔离的做法是创建子智能体,每个子智能体只拿到完成角色所需的信息。
flowchart TD
Main[主智能体<br/>协调任务] --> Research[调研子智能体<br/>只读上下文]
Main --> Implement[实现子智能体<br/>代码修改上下文]
Main --> Review[审查子智能体<br/>diff 与规则]
Research --> Summary[结构化结论]
Implement --> Patch[代码变更]
Review --> Feedback[审查意见]
Summary --> Main
Patch --> Main
Feedback --> Main
它的好处是边界清楚:调研智能体不会修改代码,审查智能体只看 diff 和规则,实现智能体不需要知道所有探索过程。
难点在信息传递。传得太少,子智能体无法完成任务;传得太多,又失去隔离意义。比较稳的做法是让每个子智能体输出结构化结果,而不是把整段聊天记录直接传下去。
分支、合并并行:让多个智能体同时尝试
当任务能拆成互不依赖的部分时,可以并行处理。例如一个性能问题可以让多个智能体分别检查数据库查询、缓存策略和前端渲染。
flowchart LR
Task[总任务] --> A[分支 A<br/>数据库方向]
Task --> B[分支 B<br/>缓存方向]
Task --> C[分支 C<br/>前端方向]
A --> Merge[合并分析]
B --> Merge
C --> Merge
Merge --> Decision[选择方案或组合方案]
并行能缩短等待时间,也能获得多个角度的结果。代价集中在合并阶段:不同分支可能修改同一个文件、给出互相冲突的建议,Harness 需要处理冲突、排序优先级,并保留可审计记录。
工具与权限:让智能体能做事,但不能乱做事
AI 编程智能体的能力主要来自工具:读文件、搜索、编辑、运行命令、访问外部接口。工具越强,风险越高。Harness 需要把工具变成可控资源。
渐进式工具扩展:先给少量工具,按需开放
一开始就给模型几十个工具,会增加选择成本,也会提高误用概率。更稳的策略是按任务阶段开放工具。
| 阶段 | 可用工具 | 说明 |
|---|---|---|
| 初始理解 | 读文件、目录列表、搜索 | 只获取信息 |
| 方案制定 | 代码索引、依赖分析 | 帮助判断影响范围 |
| 执行修改 | 编辑文件、运行测试 | 开始产生副作用 |
| 高风险操作 | 安装依赖、数据库命令、网络请求 | 需要额外确认或策略放行 |
这种方式不是削弱智能体,而是减少无关工具对决策的干扰。
命令风险分类:不同命令走不同处理策略
Shell 命令是高风险入口,因为同一个命令加不同参数,影响完全不同。Harness 可以根据命令、参数、目录、环境变量和历史行为判断风险。
| 风险等级 | 示例 | 处理策略 |
|---|---|---|
| 安全 | pwd、ls、grep、cat package.json | 自动执行 |
| 有风险 | npm install、pytest、docker compose up | 可能消耗资源或改变环境,按策略确认 |
| 危险 | rm -rf、git reset --hard、生产数据库写操作 | 拦截或强制人工确认 |
| 敏感 | 读取 .env、访问密钥文件 | 默认拒绝或脱敏读取 |
风险分类不能只看命令名。例如 rm tmp.log 和 rm -rf / 都是 rm,但风险完全不同;cat README.md 通常安全,cat .env 则可能泄露凭证。
单用途工具:用明确接口替代万能 Shell
通用 Shell 灵活,但不利于审计和权限控制。对常见操作,可以封装成单用途工具:
| 通用做法 | 单用途工具 | 好处 |
|---|---|---|
cat file | read_file(path) | 可限制读取范围,可做脱敏 |
grep -R keyword . | search_code(query, include, exclude) | 可自动排除大目录和敏感文件 |
sed -i ... | edit_file(patch) | 可生成 diff,可回滚 |
npm test | run_test(target) | 可记录测试类型和结果 |
单用途工具会牺牲一部分自由度,但换来更好的可审查性。对生产级智能体来说,这通常更重要。
确定性生命周期钩子:不要把关键步骤交给模型记忆
模型可能忘记“每次修改后运行格式化”,也可能在长任务中漏掉测试。生命周期钩子把这些动作放到系统层执行,而不是依赖提示词提醒。
sequenceDiagram
participant H as Harness
participant L as LLM
participant S as Sandbox
H->>L: 发送上下文
L-->>H: 返回工具调用
H->>S: 执行文件修改
S-->>H: 返回结果
H->>S: 触发 after_edit 钩子:格式化
S-->>H: 返回格式化结果
H->>S: 触发 after_test 钩子:收集报告
钩子适合处理确定性动作:
hooks:
after_edit:
- run: "npm run format -- --changed"
before_finish:
- run: "npm run lint"
- run: "npm test"
on_session_start:
- run: "git status --short"
这类机制的关键点是“系统保证执行”。即使模型没有主动要求,关键检查也会发生。
Managed Agents:把智能体拆成 Session、Harness、Sandbox
一个可运行的 AI 编程智能体可以拆成三个核心组件:
| 组件 | 角色 | 状态特点 |
|---|---|---|
| Claude / LLM | 大脑,负责推理和决策 | 可替换、可多实例 |
| Harness | 双手和控制器,负责循环、工具路由、权限 | 尽量无状态 |
| Sandbox | 工作台,负责文件、进程、命令执行 | 可创建、销毁、重建 |
| Session | 事件流,记录所有输入、输出和工具结果 | 持久、不可随意丢失 |
这里有一个很重要的基础设施哲学:Session 是“宠物”,Harness 和 Sandbox 是“牲畜”。
“宠物”意味着要精心保存,不能随便丢,因为 Session 保存了任务历史、工具结果、状态恢复依据。“牲畜”意味着可以随时重建,某个 Harness 崩了就换一个,某个 Sandbox 脏了就销毁后重新创建。
flowchart TD
Session[(Session<br/>不可变事件流)]
Harness[Harness<br/>运行循环与工具路由]
Claude[Claude / LLM<br/>推理]
Sandbox[Sandbox<br/>隔离执行环境]
Harness -->|读取事件| Session
Harness -->|调用| Claude
Claude -->|响应 / 工具请求| Harness
Harness -->|执行工具| Sandbox
Sandbox -->|工具结果| Harness
Harness -->|追加事件| Session
Session:只追加的事件流
Session 的核心接口可以非常简单:
interface Session {
emitEvent(event: AgentEvent): Promise<void>;
getEvents(query?: EventQuery): Promise<AgentEvent[]>;
}
事件可以包含用户消息、模型响应、工具调用、工具结果、摘要、错误等:
{
"id": "evt_1024",
"type": "tool_result",
"timestamp": "2026-06-07T10:30:00Z",
"tool": "run_test",
"input": {
"target": "user-service"
},
"output": {
"exitCode": 1,
"summary": "UserProfileCache.test.ts failed"
}
}
只追加事件流有几个好处:
- 可以回放:重新读取事件就能恢复任务过程。
- 可以审计:知道模型何时做了什么、工具返回了什么。
- 可以容错:Harness 或 Sandbox 崩溃后,新的实例可以从 Session 继续。
- 可以压缩:摘要事件可以追加进去,但不破坏原始记录。
Session 不应该被随意修改。纠错可以追加一条新事件,例如“上一条摘要已过期”,而不是直接改掉历史。
Harness:无状态运行循环
Harness 驱动智能体运行,典型循环如下:
flowchart TD
A[从 Session 读取事件] --> B[组装上下文]
B --> C[调用 Claude / LLM]
C --> D[把模型响应写入 Session]
D --> E{是否有工具调用}
E -- 否 --> F[等待下一轮输入]
E -- 是 --> G[权限检查与风险分类]
G --> H[路由到 Sandbox 或外部代理]
H --> I[记录工具结果]
I --> A
Harness 本身最好不要保存关键状态。它可以有缓存,但缓存丢失不能影响任务恢复。真正的状态应该进入 Session。这样一来,Harness 可以横向扩展,也可以在故障后替换。
Sandbox:隔离执行环境
Sandbox 是模型操作代码的地方。它应该具备几个属性:
| 属性 | 含义 |
|---|---|
| 隔离 | 文件系统、进程、网络与宿主环境隔开 |
| 可重建 | 环境损坏后可以从镜像或快照恢复 |
| 可扩展 | 多任务可以创建多个 Sandbox |
| 可限制 | 控制 CPU、内存、网络、文件访问范围 |
Sandbox 的存在不是为了方便模型,而是为了限制模型。智能体可以在里面运行测试、编辑文件、执行构建,但不能直接碰宿主机敏感资源。
凭证永不进入 Sandbox
凭证管理是安全设计的分界线。一个危险做法是把云服务密钥、GitHub Token、数据库密码放进 Sandbox 环境变量,让模型生成的代码可以直接访问。更稳的做法是 Vault + Proxy 架构。
flowchart LR
Sandbox[Sandbox<br/>无凭证] -->|请求外部操作| Proxy[Proxy<br/>校验与审计]
Harness[Harness] -->|授权策略| Proxy
Proxy -->|按需取凭证| Vault[(Vault<br/>凭证保险库)]
Proxy --> External[第三方服务]
Vault -.不直接暴露.-> Sandbox
这个设计的原则是:Sandbox 只提出“我要调用某个受控能力”,Proxy 根据策略决定是否执行。凭证只在 Proxy 和 Vault 之间流动,不暴露给模型生成的代码。
好处包括:
- 最小权限:每次外部调用只拿所需权限。
- 可审计:Proxy 记录谁在何时访问了什么服务。
- 可轮换:凭证集中在 Vault 中,替换时不需要重建所有 Sandbox。
- 降低泄露面:即使 Sandbox 内代码被污染,也拿不到原始密钥。
多智能体协作:大脑、双手、工作台可以重新组合
Session、Harness、Sandbox 解耦后,多智能体协作不再是简单“开多个聊天窗口”,而是可以组合不同数量的大脑和执行环境。
| 模式 | 结构 | 适合场景 | 难点 |
|---|---|---|---|
| 多脑一手 | 多个 Claude 共享一个 Sandbox | 对同一份代码做安全审查、性能分析、重构建议 | 防止多个决策互相覆盖 |
| 一脑多手 | 一个 Claude 控制多个 Sandbox | 在 Python、Node.js、不同依赖版本中并行验证 | 汇总不同环境结果 |
| 多脑多手 | 多个 Claude 各自拥有 Sandbox,通过 Session 协调 | 大型迁移、多阶段复杂任务 | 任务分解、冲突合并、成本控制 |
多脑一手像是多个专家围着同一张工作台讨论;一脑多手像是一个负责人同时调度多个实验环境;多脑多手则更接近工程团队协作,需要明确分工和合并规则。
flowchart TD
Session[(共享 Session)]
C1[Claude A<br/>安全审查]
C2[Claude B<br/>性能分析]
C3[Claude C<br/>实现修改]
S1[Sandbox A]
S2[Sandbox B]
C1 --> Session
C2 --> Session
C3 --> Session
Session --> C1
Session --> C2
Session --> C3
C1 --> S1
C2 --> S1
C3 --> S2
协作的关键不是“智能体越多越好”,而是能否把角色、上下文、权限和产物边界定义清楚。
解耦带来的性能收益:推理不必等容器启动
如果把模型推理和 Sandbox 生命周期绑在一起,每次会话恢复都可能要等待容器启动、依赖加载、环境检查。对用户来说,最明显的问题是首 Token 延迟变高:模型还没开始输出,就已经在等环境。
解耦后,Harness 可以先从 Session 读取事件并调用模型,让推理立即开始;Sandbox 可以在需要执行工具时再准备,或者提前异步预热。
sequenceDiagram
participant U as 用户
participant H as Harness
participant S as Session
participant L as Claude / LLM
participant B as Sandbox
U->>H: 发起任务
H->>S: 读取历史事件
H->>L: 立即发送上下文
par Sandbox 预热
H->>B: 准备执行环境
and 模型推理
L-->>H: 输出分析与工具请求
end
H->>B: 执行工具调用
这种架构把“思考”和“执行环境准备”拆开。只要当前轮不需要立刻运行命令,用户就能更快看到模型开始响应。
Hermes 式进化:让智能体从任务中积累能力
普通智能体完成任务后,经验往往留在聊天记录里,下次不会自动复用。可进化智能体要做的是把成功经验转化为技能、知识、用户模型和长期日志。
一个典型循环包含五步:
flowchart LR
Plan[规划] --> Execute[执行]
Execute --> Observe[观察结果]
Observe --> Learn[学习沉淀]
Learn --> Adapt[调整策略]
Adapt --> Plan
关键在“学习”不是口号,而是有明确存储结构。
五层记忆架构
flowchart TD
L1[L1 短期记忆<br/>当前会话便利贴]
L2[L2 技能手册<br/>可复用步骤]
L3[L3 知识库<br/>向量语义检索]
L4[L4 用户模型<br/>偏好与例外]
L5[L5 工作日志<br/>全文检索 + 摘要]
L1 --> Prompt[当前上下文]
L2 --> Prompt
L3 --> Prompt
L4 --> Prompt
L5 --> Prompt
| 层级 | 名称 | 存储内容 | 使用方式 |
|---|---|---|---|
| L1 | 短期记忆 | 当前目标、临时假设、刚得到的结果 | 当前会话直接使用 |
| L2 | 技能手册 | 完成某类任务的步骤和注意事项 | 遇到相似任务时加载 |
| L3 | 知识库 | 概念、代码经验、问题解法 | 语义检索 |
| L4 | 用户模型 | 用户偏好、工作习惯、例外情况 | 个性化决策 |
| L5 | 工作日志 | 跨会话完整历史、摘要、工具记录 | 全文搜索、审计、恢复 |
L2 技能手册:把复杂任务沉淀成 SKILL.md
当智能体完成一个多步骤任务后,可以把过程整理成技能文件。这个文件不应该只是结果描述,而要包含可复用流程。
# 技能:生成项目周报
## 适用场景
用户要求整理本周进展、风险和下周计划。
## 输入
- 时间范围
- 项目名称
- 任务记录或提交记录
## 步骤
1. 收集本周完成事项。
2. 按模块归类。
3. 提取阻塞和风险。
4. 生成「进展 / 风险 / 下周计划」三段结构。
5. 如果缺少数据,列出需要用户补充的问题。
## 输出格式
- 本周进展
- 当前风险
- 下周计划
下次遇到类似任务时,智能体不用重新摸索流程,可以直接加载技能。
L3 语义记忆:字面不同,也能找回相近经验
语义记忆通常依赖向量检索。它会把文本转换成向量,语义接近的内容在向量空间里距离更近。
例如用户查询“进度报告”,知识库里可能没有完全相同的标题,但有“项目周报”技能:
| 查询 | 候选内容 | 相似度 | 判断 |
|---|---|---|---|
| 进度报告 | 生成项目周报.md | 0.92 | 高度相关 |
| 进度报告 | 预订机票.md | 0.15 | 无关 |
这解决了关键词检索的局限。用户不需要说出完全相同的词,系统也能找回相关经验。
L4 用户模型:不是覆盖旧判断,而是处理例外
用户建模不能简单写成“用户喜欢 X”。真实偏好经常有条件和例外。
更合理的更新方式是把旧判断、新证据和冲突一起考虑:
flowchart TD
Old[旧模型<br/>用户通常选择美式咖啡]
Evidence[新证据<br/>周三下午选择拿铁]
Conflict{是否冲突}
Old --> Conflict
Evidence --> Conflict
Conflict --> Update[更新模型<br/>用户通常选择美式<br/>但周三下午可能选择拿铁]
这类模型更新适合处理工程偏好:
- 用户通常希望输出简洁,但架构设计问题需要详细说明。
- 用户偏好 TypeScript,但脚本任务可以接受 Python。
- 用户一般不想改公共接口,除非明确要求重构。
好的用户模型不是给人贴固定标签,而是记录“通常情况”和“条件例外”。
L5 工作日志:全文检索加摘要
长期日志需要同时满足两种需求:
- 快速查到关键词。
- 快速理解一段历史的大意。
FTS5(SQLite 的全文检索扩展)可以用于关键词搜索,LLM 摘要可以用于快速浏览。两者结合后,既能搜“缓存失效”,也能直接看到某次会话的核心结论。
flowchart LR
Events[完整事件] --> FTS[FTS5 全文索引]
Events --> Summary[LLM 摘要]
FTS --> Search[关键词检索]
Summary --> Overview[历史概览]
Search --> Recall[恢复相关上下文]
Overview --> Recall
摘要不能替代原始日志。摘要适合快速定位,原始日志负责提供证据。
落地时的设计清单
构建一个可长期运行的 AI 编程智能体,可以按这张清单检查:
| 设计点 | 应该具备的能力 |
|---|---|
| 指令文件 | 项目规则可持久化,并能随目录作用域加载 |
| 上下文组装 | 能区分当前必要信息、可检索信息和归档信息 |
| 记忆系统 | 有摘要、技能、语义知识、用户模型和完整日志 |
| 工作流 | 高风险任务支持探索、规划、行动分阶段 |
| 工具系统 | 工具有明确权限边界,优先使用单用途接口 |
| 命令风控 | 能按命令和参数判断安全、有风险、危险、敏感 |
| 生命周期钩子 | 格式化、测试、状态检查等动作由系统触发 |
| Session | 所有关键事件只追加记录,支持回放和恢复 |
| Sandbox | 执行环境隔离、可重建、可限制资源 |
| 凭证管理 | 凭证存放在 Vault,通过 Proxy 受控调用 |
| 多智能体 | 角色、上下文、权限和合并策略清晰 |
| 性能 | 推理链路和执行环境生命周期解耦 |
Harness Engineering 的本质是把 AI Agent 从“会聊天的模型”变成“可运行的工程系统”。模型能力决定上限,Harness 决定这个上限能不能在真实项目里安全、稳定地发挥出来。