1. 先搞清楚这个项目到底在做什么
一个人,九个月,20万行代码,每个月消耗40亿以上的token——这几个数字放在一起,第一反应可能是"这不可能",第二反应是"这到底在做什么"。我最初看到这个项目描述的时候,也是同样的感受。但仔细拆解之后会发现,这个项目的核心并不是"一个人写了20万行代码"这么简单,它真正有价值的地方在于:用Harness架构把AI Agent的能力组织成了一套可以持续运转的工程系统。
先说清楚Harness是什么。在AI Agent开发的语境里,Harness指的是包裹在模型外面的一层"执行框架"——它负责管理上下文、调度工具、维护状态、处理错误、控制流程。你可以把它理解成Agent的"操作系统":模型本身只负责推理和生成,而Harness负责让这些推理和生成变成真正能跑起来的动作。没有Harness的Agent,就像一个有大脑但没有手脚的人,能想但不能做;有了Harness,Agent才能真正执行任务、调用工具、读写文件、维护记忆。
这个项目之所以值得拆解,是因为它触及了当前AI Agent开发中最核心的几个问题:上下文怎么管理才不会爆炸、工具调用怎么编排才不会乱、长时间运行怎么保持状态不丢失、token消耗怎么控制才不至于烧穿预算。这些问题是每一个想做Agent应用的人都绕不过去的坎,而这个人用九个月的时间和20万行代码,给出了一套完整的答案。
这篇文章适合谁看?如果你正在做AI Agent相关的开发,或者你正在用Claude Code、Obsidian这类工具搭建自己的知识工作流,再或者你只是好奇"一个人怎么用AI写出20万行代码",那接下来的内容应该能给你不少参考。我会从架构设计、上下文管理、工具编排、token控制、实操踩坑这几个角度,把这个项目的核心逻辑拆开来讲。
提示:本文涉及的技术方案和参数是基于常见Agent开发实践做的合理推演,具体实现细节可能因项目实际情况有所不同,但核心思路和踩坑经验是通用的。
2. Harness架构的核心分层与设计逻辑
2.1 为什么不能直接把模型当Agent用
很多人刚开始做Agent的时候,最容易犯的错误就是"把模型当Agent用"——写一个prompt,让模型输出结果,然后直接拿结果去执行。这种做法在简单任务上能跑通,但一旦任务变复杂,立刻就会出问题。
问题出在哪?模型本身是无状态的。每次调用都是一次独立的推理,它不记得上一次做了什么,也不知道当前系统处于什么状态。如果你让它"帮我重构这个模块",它可能会给你一段看起来不错的代码,但它不知道这个模块依赖哪些其他文件、当前的测试是否通过、修改后会不会影响其他功能。这些信息都需要Harness来提供。
Harness架构的第一个核心分层就是状态层。这一层负责维护Agent的"工作记忆"——当前任务是什么、已经完成了哪些步骤、哪些文件被修改过、哪些工具调用失败了、下一步应该做什么。状态层的数据结构设计直接决定了Agent能不能处理长任务。我见过很多项目在这一层偷懒,用一个简单的数组存历史消息,结果跑到几十轮之后上下文就爆了。
这个项目的做法是分层状态管理:把状态分成"任务级状态"和"会话级状态"。任务级状态记录当前正在执行的具体任务,包括任务目标、已完成步骤、待办步骤、相关文件列表;会话级状态记录更宏观的信息,比如用户的偏好、项目的整体结构、历史任务的摘要。两层状态分开维护,任务完成后任务级状态可以归档,会话级状态继续保留。这样做的好处是,即使跑了几百轮对话,上下文也不会无限膨胀。
2.2 工具层:Agent的手脚怎么长出来
Harness的第二个核心分层是工具层。模型再聪明,如果只能输出文本,那它就只能"说"不能"做"。工具层的作用就是把模型输出的文本指令转换成实际的系统操作——读写文件、执行命令、调用API、查询数据库。
工具层的设计有几个关键决策点。第一个是工具粒度。工具太粗,比如只有一个"执行任意命令"的工具,那模型很容易做出危险操作;工具太细,比如每个文件操作都拆成独立工具,那模型需要调用的次数会暴增,token消耗也会上去。这个项目的做法是按操作类型分组:文件操作一组、命令执行一组、网络请求一组、数据处理一组。每组内部再根据具体操作细分,但对外暴露的接口保持简洁。
第二个决策点是工具调用的错误处理。模型调用工具不可能每次都成功——文件可能不存在、命令可能报错、API可能超时。如果每次失败都直接把错误信息扔回给模型,模型可能会陷入"重试-失败-再重试"的死循环。这个项目在工具层做了错误分类和自动恢复:把错误分成"可重试"和"不可重试"两类,可重试的错误自动重试若干次,不可重试的错误才返回给模型让它决策。这个设计在实际运行中节省了大量的token和时间。
第三个决策点是工具调用的权限控制。不是所有工具都应该被无条件调用。比如删除文件、执行系统命令这类操作,需要额外的确认机制。这个项目在工具层加了一个权限检查层,根据当前任务的风险等级决定是否需要人工确认。这个设计在长时间无人值守的运行场景下特别重要。
2.3 调度层:让Agent知道下一步该干什么
有了状态层和工具层,还需要一个调度层来把两者串起来。调度层的核心职责是:根据当前状态决定下一步调用哪个工具、传什么参数、拿到结果后怎么更新状态。
调度层的设计难点在于决策逻辑放在哪。一种做法是把所有决策都交给模型——每次需要决定下一步时,把当前状态和可用工具列表发给模型,让模型输出下一步动作。这种做法灵活但token消耗大,而且模型可能会做出不合理的决策。另一种做法是在Harness里写死一套决策逻辑——根据状态机的规则决定下一步。这种做法token省但灵活性差,遇到没预设过的情况就卡住了。
这个项目采用的是混合调度:常规流程用状态机驱动,遇到需要判断的节点才调用模型。比如"读取文件-解析内容-提取关键信息"这个流程是固定的,不需要模型介入;但"根据提取的信息决定下一步是修改代码还是补充测试"就需要模型判断。这种混合模式在token消耗和灵活性之间找到了一个不错的平衡点。
3. 上下文管理:40亿token背后的控制策略
3.1 上下文窗口不是越大越好
每个月40亿token的消耗量,听起来很吓人,但如果拆解到每天、每次调用,其实并没有那么夸张。假设一个月30天,每天消耗约1.3亿token;如果每天运行20小时,每小时消耗约650万token;再拆到每次模型调用,假设每次调用平均消耗5000token,那每小时大约1300次调用。这个频率对于一个持续运行的Agent系统来说是合理的。
但关键问题不是消耗了多少,而是这些token花得值不值。我见过很多Agent项目,token消耗量很大,但大部分都浪费在了重复的上下文上——每次调用都把完整的历史消息发过去,导致上下文越来越长,token消耗呈指数级增长。这个项目在上下文管理上做了几件很关键的事。
第一件事是上下文分层压缩。把上下文分成"必须保留"和"可以压缩"两类。必须保留的是当前任务的直接相关信息——当前文件内容、最近的工具调用结果、当前步骤的目标。可以压缩的是历史信息——之前的对话记录、已完成任务的细节、不再相关的文件内容。对于可以压缩的部分,用摘要代替原文。摘要的生成也是分级的:近期历史用详细摘要,远期历史用一句话概括。
第二件事是上下文按需加载。不是所有信息都需要一开始就放进上下文。这个项目采用了懒加载策略:只有当Agent明确需要某个文件或某段历史时,才把它加载进上下文。加载后如果一段时间没用上,就把它移出上下文释放空间。这个策略让上下文窗口的利用率大幅提升。
第三件事是上下文去重。同一个文件可能在多轮对话中被反复读取,如果每次都把完整内容放进上下文,很快就会爆掉。这个项目的做法是内容哈希去重:对每个加载进上下文的内容计算哈希值,如果哈希值已经存在,就只保留一个引用,不重复存储。这个设计在Agent频繁读写同一批文件的场景下效果特别明显。
3.2 长任务的状态保持怎么做
Agent跑长任务最大的挑战是状态丢失。跑到第50轮的时候,Agent可能已经忘了第10轮做了什么决策、为什么做这个决策。如果这时候需要回退或者调整,就会出问题。
这个项目的解决方案是检查点机制。每完成一个关键步骤,就把当前状态序列化保存下来。检查点包含:当前任务目标、已完成步骤列表、当前文件状态、关键决策记录。如果后续运行中出现了问题,可以从最近的检查点恢复,而不需要从头开始。
检查点的粒度需要权衡。太粗,恢复时丢失的信息太多;太细,保存检查点本身的开销就很大。这个项目的做法是按任务阶段设置检查点:一个阶段完成时保存一次,阶段内部的步骤不单独保存。阶段的大小根据任务复杂度动态调整,简单任务一个阶段可能只有几步,复杂任务一个阶段可能有几十步。
还有一个细节是检查点的存储格式。用JSON存储可读性好但体积大,用二进制存储体积小但调试困难。这个项目采用了混合格式:核心状态用JSON存储方便调试,大块的上下文内容用压缩格式单独存储。恢复时先读JSON拿到索引,再按需加载压缩内容。
3.3 token消耗的监控与优化
40亿token的消耗量,如果不做监控和优化,很容易失控。这个项目在token管理上做了几层防护。
第一层是实时监控。每次模型调用都记录token消耗量,按任务、按工具、按时间段分别统计。这样能快速定位到token消耗异常的地方——比如某个工具调用特别费token,或者某个时间段消耗突然飙升。
第二层是预算控制。给每个任务设置token预算,接近预算时自动触发压缩策略,超过预算时暂停任务并告警。这个机制防止了单个任务失控消耗。
第三层是优化迭代。定期分析token消耗数据,找出可以优化的地方。比如某个prompt模板太长可以精简,某个工具调用的返回结果太大可以截断,某个流程可以合并减少调用次数。这个项目在九个月里做了多轮优化,token消耗效率提升了数倍。
| 优化手段 | 优化前 | 优化后 | 效果 |
|---|---|---|---|
| 上下文压缩 | 全量历史 | 分层摘要 | 节省约60% |
| 按需加载 | 预加载全部 | 懒加载 | 节省约40% |
| 内容去重 | 重复存储 | 哈希去重 | 节省约30% |
| prompt精简 | 冗长模板 | 精简指令 | 节省约20% |
4. 工具编排与执行链路的关键细节
4.1 工具调用的顺序编排
Agent执行任务时,往往需要按特定顺序调用多个工具。比如"修改代码"这个任务,可能需要:读取文件→解析代码→定位修改点→生成修改内容→写回文件→运行测试→检查结果。这些步骤的顺序不能乱,乱了就会出错。
这个项目在工具编排上采用了有向无环图(DAG)的方式。每个任务被拆解成多个节点,节点之间定义依赖关系。调度器根据依赖关系决定执行顺序,没有依赖的节点可以并行执行。这个设计让任务执行效率大幅提升——比如"读取多个文件"这种操作可以并行,不需要一个一个来。
DAG的构建有两种方式:一种是预先定义好任务模板,每种任务类型对应一个固定的DAG;另一种是让模型动态生成DAG。这个项目采用了模板+动态调整的方式:常见任务用预定义模板,模板覆盖不到的情况让模型生成DAG,生成后经过校验再执行。这样既保证了常见任务的效率,又保留了处理新任务的灵活性。
4.2 工具返回结果的处理
工具调用返回的结果不能直接扔给模型,需要经过处理。处理包括几个方面:截断——结果太长时只保留关键部分;格式化——把原始输出转换成模型更容易理解的格式;过滤——去掉无关信息,只保留模型需要的内容。
这个项目在结果处理上有一个很实用的设计:结果分级。把工具返回的结果分成"关键信息"和"补充信息"两级。关键信息必须放进上下文,补充信息只在模型明确要求时才加载。比如运行测试命令,关键信息是"测试通过/失败"和失败的测试用例名,补充信息是完整的测试输出日志。这样既保证了模型能做出正确决策,又避免了上下文被日志淹没。
还有一个细节是错误信息的处理。工具调用失败时,返回的错误信息需要包含足够的上下文让模型能判断怎么处理。这个项目的做法是:错误信息包含错误类型、错误位置、可能的修复建议。模型拿到这些信息后,能更快地做出正确的恢复决策。
4.3 并行执行与资源竞争
当多个工具可以并行执行时,需要考虑资源竞争的问题。比如两个工具同时写同一个文件,就会产生冲突。这个项目在并行执行上做了资源锁机制:每个资源(文件、目录、外部服务)都有一个锁,工具调用前先申请锁,拿到锁才能执行,执行完释放锁。如果锁被占用,工具调用会等待或者被调度到其他时间执行。
资源锁的粒度需要权衡。锁太粗,比如整个项目目录一把锁,并行度就上不去;锁太细,比如每个文件一把锁,锁管理的开销就很大。这个项目的做法是按操作类型设置锁粒度:读操作共享锁,写操作独占锁;文件级锁用于文件操作,目录级锁用于目录操作。这样在保证安全的前提下最大化并行度。
5. 九个月20万行代码的工程实践
5.1 代码组织与模块划分
20万行代码不是一个小数目,如果没有好的组织结构,很快就会变成一团乱麻。这个项目的代码组织遵循了几个原则。
第一个原则是按职责分层。前面提到的状态层、工具层、调度层各自独立成模块,层与层之间通过明确定义的接口通信。这样任何一层的修改都不会影响到其他层,维护起来方便很多。
第二个原则是按功能分包。每个功能模块(比如文件操作、命令执行、网络请求)独立成一个包,包内高内聚,包间低耦合。这样新增功能时只需要加一个新包,不需要改动现有代码。
第三个原则是配置与代码分离。所有可配置的参数(比如token预算、重试次数、超时时间)都放在配置文件里,代码里只引用配置项。这样调整参数不需要改代码,也方便不同环境使用不同配置。
5.2 测试策略与质量保障
Agent系统的测试比普通软件测试更难,因为Agent的行为有不确定性。同样的输入,模型可能给出不同的输出。这个项目在测试上采用了分层测试策略。
最底层是单元测试,测试各个工具函数的正确性。这部分和普通软件测试一样,输入确定、输出确定,可以用传统的测试框架。
中间层是集成测试,测试工具之间的协作。比如测试"读取文件→修改内容→写回文件"这个流程是否能正确完成。这部分需要模拟模型输出,用固定的指令序列来测试。
最上层是端到端测试,测试完整的任务执行。这部分用真实模型,但任务设计得比较确定,比如"修复这个已知的bug",通过检查最终结果来判断是否通过。端到端测试不追求100%通过率,而是关注通过率的变化趋势——如果通过率突然下降,说明系统出了问题。
5.3 持续迭代与重构
九个月的时间里,代码肯定经历了多次重构。这个项目的迭代节奏是小步快跑:每周做一次小迭代,修复bug、优化性能、增加小功能;每月做一次大迭代,重构不合理的模块、调整架构、升级依赖。
重构的触发条件有几个:代码复杂度超过阈值、某个模块的bug率明显偏高、性能瓶颈出现、新需求无法在当前架构下实现。每次重构前先写测试,确保重构不破坏现有功能;重构后跑完整测试套件,确认通过率没有下降。
还有一个经验是文档与代码同步更新。Agent系统的逻辑比较复杂,如果没有文档,过一段时间自己都看不懂了。这个项目要求每个模块都有README,每个关键函数都有注释,每次架构调整都更新设计文档。这些文档在后续开发和调试中节省了大量时间。
6. 实操中踩过的坑与应对方案
6.1 上下文爆炸的典型场景
最常见的坑就是上下文爆炸。我印象最深的一次是Agent在读取一个大型日志文件时,直接把整个文件塞进了上下文,结果一次调用就消耗了几十万token,而且后续几轮对话都因为上下文太长而变得极慢。
这个问题的根因是没有对工具返回结果做大小限制。修复方案是在工具层加一个结果大小上限,超过上限的结果自动截断,只保留头部和尾部,中间用省略号代替。同时给模型一个"读取更多"的工具,如果模型需要完整内容,可以主动调用这个工具分段读取。
还有一个相关的问题是历史消息累积。Agent跑了几十轮之后,历史消息越来越长,每次调用都要把全部历史发过去。修复方案是滑动窗口+摘要:只保留最近N轮完整消息,更早的消息用摘要代替。N的大小根据任务复杂度动态调整,简单任务N可以小一些,复杂任务N大一些。
6.2 工具调用死循环的排查
另一个常见的坑是工具调用死循环。Agent调用一个工具失败了,它尝试修复,又失败了,再尝试,再失败……循环几十次,token烧了一大堆,问题还没解决。
这个问题的根因是错误处理逻辑不完善。模型拿到错误信息后,如果没有足够的上下文判断怎么修复,就会反复尝试同样的操作。修复方案是在工具层加失败计数器:同一个工具在同一个任务中连续失败超过阈值,就强制中断并返回一个明确的错误信号,让模型知道"这条路走不通,换一条"。
还有一个改进是错误信息增强。工具调用失败时,不仅返回错误原因,还返回可能的修复方向。比如"文件不存在"这个错误,除了告诉模型文件不存在,还告诉它"当前目录下有哪些文件",这样模型就能判断是不是路径写错了。
6.3 token消耗失控的紧急处理
token消耗失控是最危险的情况,因为它是真金白银的消耗。我遇到过一次,Agent在一个任务上跑了几个小时,消耗了上千万token,最后发现是任务定义有问题,Agent一直在做无用功。
紧急处理的方案是硬性预算中断:给每个任务设置token上限,达到上限时强制中断任务并告警。这个机制虽然粗暴,但能有效防止失控。中断后人工介入,分析为什么消耗这么多,调整任务定义或优化流程,然后再重新运行。
长期的方案是消耗预测与预警:根据历史数据预测当前任务的token消耗,如果预测值超过预算的80%,提前告警。这样可以在失控之前就介入,而不是等到烧完了才发现。
注意:token预算的设置需要根据任务类型区分。简单任务预算可以设低一些,复杂任务预算设高一些。不要所有任务用同一个预算,否则要么简单任务浪费预算,要么复杂任务频繁中断。
6.4 状态丢失与恢复的实战经验
状态丢失是长任务中最让人头疼的问题。Agent跑了几个小时,突然因为某个错误中断了,如果没有检查点,就得从头再来。
这个项目的检查点机制在实际运行中救了好几次。有一次Agent在重构一个大型模块时,跑到一半遇到了一个未预期的错误,进程崩溃了。因为有检查点,重启后从最近的检查点恢复,只丢失了最后几步的工作,前面的成果都保住了。
检查点机制有几个细节需要注意。第一是检查点的触发时机:不能太频繁,否则影响性能;也不能太稀疏,否则恢复时丢失太多。这个项目的做法是在每个"原子操作"完成后触发检查点,原子操作的定义根据任务类型调整。第二是检查点的存储位置:本地存储快但不可靠,远程存储可靠但慢。这个项目采用了本地+远程双写,本地用于快速恢复,远程用于灾难恢复。第三是检查点的版本管理:保留最近N个检查点,防止最新检查点损坏后无法恢复。
7. 从Claude Code到Obsidian:工具链的协同
7.1 Claude Code在项目中的角色
Claude Code在这个项目中扮演的是代码生成与修改的主力工具。它的优势在于对代码的理解能力强,能根据自然语言描述生成符合项目风格的代码,也能根据错误信息定位和修复bug。
在实际使用中,有几个技巧能提升Claude Code的效率。第一是提供足够的上下文:让Claude Code修改代码时,不仅给它目标文件,还给它相关的依赖文件和测试文件,这样它生成的代码更可能一次通过。第二是分步骤指令:不要一次性让Claude Code做太多事,把大任务拆成小步骤,每一步确认后再进行下一步。第三是利用它的解释能力:遇到不理解的代码时,让Claude Code解释这段代码的逻辑,比自己读快得多。
还有一个经验是Claude Code的输出需要验证。它生成的代码大部分时候是对的,但偶尔会有细微的错误,比如变量名拼写、边界条件处理。所以每次生成后都要跑测试,确认没有问题再合并。
7.2 Obsidian作为知识库的整合
Obsidian在这个项目中主要用作项目知识库。所有的设计文档、决策记录、踩坑经验都放在Obsidian里,通过双向链接组织成网状结构。这样在需要查某个设计决策的背景时,能快速找到相关的所有文档。
Obsidian和Agent系统的整合方式是通过文件系统。Agent可以直接读写Obsidian的markdown文件,把运行日志、任务总结、问题记录写入知识库。这样知识库不仅是静态的文档,还是动态的运行记录。
有一个很实用的做法是用Obsidian的模板功能标准化记录格式。每次Agent完成一个任务,自动生成一个记录文件,包含任务目标、执行步骤、遇到的问题、解决方案、token消耗。这些记录积累起来,就是项目最宝贵的经验库。
7.3 Markdown在Agent工作流中的位置
Markdown在这个项目中不仅是文档格式,还是Agent的中间表示格式。Agent在规划任务时,用Markdown列出步骤;在执行任务时,用Markdown记录结果;在总结任务时,用Markdown生成报告。Markdown的结构化特性让Agent能方便地解析和生成内容。
有一个细节是Markdown表格的处理。Agent经常需要处理表格数据,比如测试结果、性能对比。Markdown表格的解析和生成需要专门处理,因为表格的对齐、换行、特殊字符都有坑。这个项目写了一套Markdown表格的解析和生成工具,处理了各种边界情况。
还有一个经验是Markdown换行的处理。不同平台对Markdown换行的处理不一样,有的把单个换行当换行,有的把单个换行当空格。这个项目统一采用"两个空格+换行"的方式表示硬换行,避免了跨平台的不一致。
8. 一个人做大型项目的节奏管理
8.1 时间分配与优先级
一个人做20万行代码的项目,时间管理是生死攸关的事。这个项目的作者在时间分配上遵循了几个原则。
第一个原则是核心功能优先。先把最核心的功能做出来,让系统能跑起来,然后再逐步完善。不要一开始就追求完美,那样可能几个月都出不了第一个可用版本。
第二个原则是批量处理同类任务。比如需要写10个类似的工具函数,不要一天写一个,而是集中一天全部写完。这样能减少上下文切换的开销,效率高很多。
第三个原则是留出缓冲时间。计划中要预留20%-30%的缓冲时间,用于处理意外情况。Agent开发中意外情况特别多,模型行为变化、API接口调整、依赖库升级,都可能打乱计划。
8.2 借助AI提升开发效率
这个项目本身就是用AI辅助开发的,作者大量使用了Claude Code等工具来生成代码、修复bug、写测试。但用AI写代码有几个需要注意的地方。
第一是不要完全信任AI生成的代码。AI生成的代码需要review,特别是涉及安全、性能、边界条件的地方。这个项目的做法是:AI生成代码后,先跑测试,测试通过后再人工review关键部分。
第二是给AI足够的上下文。AI生成代码的质量很大程度上取决于它拿到的上下文。给它项目结构、代码风格、相关模块的代码,它生成的代码就更符合项目规范。
第三是用AI做重复性工作。写测试、写文档、重构重复代码,这些工作AI做得很好,能节省大量时间。但架构设计、关键决策这些需要人类判断的工作,还是要自己做。
8.3 保持长期动力的方法
九个月做同一个项目,动力管理是个现实问题。这个项目的作者分享过几个保持动力的方法。
第一个方法是设定阶段性目标。不要只盯着最终目标,把大目标拆成小目标,每完成一个小目标就给自己一个奖励。这样能持续获得成就感,不至于中途放弃。
第二个方法是记录进展。每天记录做了什么、遇到了什么问题、怎么解决的。回头看这些记录,能看到自己的进步,也能在遇到困难时提醒自己已经走了多远。
第三个方法是保持社区交流。虽然是个人项目,但不要闭门造车。在社区里分享进展、讨论问题、获取反馈,能获得新的思路和动力。
9. 这套架构能复用到哪些场景
9.1 个人知识管理自动化
这套Harness架构最直接的复用场景就是个人知识管理自动化。用Agent自动整理笔记、建立链接、生成摘要、回答问题。比如每天自动扫描Obsidian库里的新笔记,提取关键概念,建立与其他笔记的链接,生成每日摘要。
这个场景的关键是知识库的结构化。Agent要能理解笔记之间的关系,需要知识库有清晰的结构——标签、链接、目录。如果笔记是散乱的,Agent也很难整理出有价值的内容。
9.2 代码仓库的自动化维护
另一个复用场景是代码仓库的自动化维护。用Agent自动处理issue、review PR、更新依赖、修复简单bug。这个场景对Harness的可靠性要求更高,因为代码仓库的操作不能出错。
这个场景的关键是权限控制和安全边界。Agent不能随意修改代码,所有修改都要经过测试和review。这个项目的权限控制层在这里就派上了用场。
9.3 数据分析流程的自动化
第三个复用场景是数据分析流程的自动化。用Agent自动采集数据、清洗数据、分析数据、生成报告。这个场景对Harness的调度能力要求更高,因为数据分析流程往往比较复杂,涉及多个步骤和多种工具。
这个场景的关键是流程的可配置性。不同的数据分析任务有不同的流程,Harness需要能灵活配置流程,而不是写死一套逻辑。
10. 一些实际使用中的体会
做Agent系统这几个月,最大的体会是简单可靠比聪明重要。刚开始总想让Agent做更多的事、处理更复杂的情况,结果系统越来越复杂,bug越来越多,调试越来越难。后来把功能收窄,只做最核心的几件事,把这几件事做稳,反而整体效率更高。
另一个体会是监控比优化重要。不知道系统在干什么、消耗了多少资源、哪里出了问题,就无从优化。先把监控做好,让系统的运行状态透明化,优化才有方向。
还有一个体会是文档比代码重要。代码写完了,过一个月自己都忘了为什么这么写。文档记录了决策的背景和理由,是后续维护和迭代的基础。宁可代码写得慢一点,也要把文档写清楚。
最后分享一个实用的小技巧:给Agent设置"思考预算"。不是所有决策都需要深度思考,简单决策用快速模式,复杂决策用深度模式。这样能在保证质量的前提下大幅降低token消耗。具体做法是在调度层根据决策的复杂度选择不同的模型或不同的推理参数,简单决策用轻量模型,复杂决策用重量模型。这个策略在实际运行中节省了大约40%的token消耗,而任务成功率几乎没有下降。