前几天,我在网上看到一篇介绍 AI Agent 原理的文章,于是产生了一个想法:能不能从头开发一个自己的 AI Agent ?毕竟只有了解 Agent 的工作原理,使用各种 Agent 工具时,才能更加得心应手。
其实,Agent 的核心并不复杂。它本质上是一个循环:接收用户输入,将上下文发送给大模型,根据模型返回的结果调用内部工具,再把工具结果交给模型继续处理,直到任务完成。
我用了两天时间,开发出了 sekrun 。它已经发布到 npm ,现在通过一条 npx 命令就能直接运行。后端接入的是 DeepSeek V4 Flash 。我很喜欢这个模型:响应迅速、体验流畅,编程能力也不错。对于我目前的开发需求来说,已经完全够用。
执行任务时,sekrun 会显示每一步工具调用,以及对应的耗时和 Token 消耗。每轮生成结束后,还会列出:工具调用步骤数、输入与输出 Token 数量各缓存命中率,这样使用时就能清楚看到额度消耗,主打一个透明。
DeepSeek 本身的上下文缓存价格就很低。开发 sekrun 时,我也针对缓存命中做了一些优化,让它可以用更低的成本处理更多 Token 。sekrun 本身也是用它自己开发出来的,它是一个可以自举的 Agent 。整个开发过程消耗的模型费用大约两块钱,一根雪糕的价格。
最开始,我考虑过使用 Zig 开发。技术论坛里面对这个语言吹得天花乱坠,也有人说进入 AI 编程时代以后,开发语言已经不重要了。但仔细考虑后,还是放弃了。Zig 目前仍处于快速发展阶段,标准库和 API 还可能发生较大变化。更重要的是,我开发 Agent 是为了长期处理真实任务,而不是做一个只能展示的玩具项目。即使代码主要由 AI 编写,我也必须看得懂它写了什么,才能判断实现是否合理,把握整个项目的质量。最后选择了自己非常熟悉擅长的 JavaScript 。
因为目标是学习 Agent 原理,目前 sekrun 没有使用任何第三方依赖。终端界面、工具调用、流式输出、会话管理和 Token 统计,都是从零实现的。也希望大家不要过度歧视 JavaScript 。语言只是工具,真正决定项目质量的,仍然是使用工具的人。AI 写代码的速度已经快到人很难跟上。开发过程中适当慢下来,理解每一次修改,反而更容易保证项目质量。
在保证任务准确率的前提下,我目前主要通过以下方法减少 Token 消耗并提高缓存命中率:
第一,截断内部工具的输出。工具可能返回大量日志和文件内容,但模型通常不需要看到全部结果。只保留与任务有关的部分,可以显著减少上下文长度。
第二,压缩历史对话。当对话越来越长时,将较早的内容总结成简短记录,而不是永久保留所有原始消息。
第三,丢弃孤立的工具消息。如果工具调用已经失去对应的上下文,继续保留这些结果只会浪费 Token ,还可能干扰模型判断。
第四,固定系统提示词前缀。尽量让系统提示词和工具定义保持稳定,使更多上下文能够命中 DeepSeek 的缓存。
因为这是自己从零开发的工具,我可以随时加入自己喜欢的功能。例如,我还实现了类似 Fish Shell 的输入感知和智能补全,可以根据当前输入推荐命令和历史内容,减少重复输入,提高开发效率。
这就是我开发 sekrun 的过程。它目前仍然是一个非常早期的项目,功能也无法与成熟 Agent 相比。但从零实现工具调用、上下文管理、缓存优化和终端交互,让我真正理解了 Agent 是如何工作的。
整个过程很有趣,我也学到了很多,分享给大家。
