最近有一个很火的智能体Pi Agent,它因小巧、轻量、可扩展性强而出圈,于是xiaoz去了解了下Pi Agent基本思路,再根据这些思路,用Golang开发了一个同样小巧、轻量的智能体Zlite,于是下这篇文章分享和记录AI智能开发的思路和一些经验。
提示:以下内容是根据自己的开发经验和对Agent框架的理解编写而成,不确保完全准确,如有错漏,还请指正。
为什么要开发Zlite?
其实xiaoz一直在寻找一款轻量、简单的智能体,用于一些不太复杂的场景(比如操作和管理Nginx),虽然Pi Agent已经满足这些条件,但Pi依赖Node.js环境,如果部署到服务器,对我而言依然不够轻量,于是就有了自己用Golang开发轻量级智能体Zlite的想法。
从想法到落地,在AI辅助下大概花了2天时间造出了Zlite,这个过程学到了很多,于是将所学和经验整理为了下面的内容。
智能体是什么?
我们可以把AI比做一个大脑,它可以思考,但它并不具备四肢,所以不具备任何操作事物的能力,最初只能进行原始的你问我答。当我们给AI装上四肢,让他可以去执行具体操作,比如帮你读取网页、帮你发邮件、帮你下单等,那么就形成了一个完整的智能体。
一些典型智能体代表包括:Hermes Agent、OpenClaw、WorkBuddy等,这类智能体综合能力比较全面,可以辅助办公,操作电脑,也可以写代码。另外还有一些用于特定领域的智能体,比如拿写代码来说有:Codex cli、Claude code、Deepseek harness,这些智能体在写代码领域有专门的优化和加强。
智能体本质就是“大脑 + 四肢”,AI大模型就属于这个“大脑”,那四肢又是什么?四肢其实就是“工具调用”。OpenAI在早期便支持了Function calling使其具备了工具调用的能力,目前已经成为业界标准,这里我们可以把Function calling理解为四肢,让AI拥有了手脚。
AI有了手脚后便成了一个智能体,智能体能做的事就更多了,比如让其读取网页,发送邮件,购物等,最后就形成一个完整闭环:用户输入内容 -> AI大脑思考发送指令 -> 手脚(Function calling) -> 完成具体事物(工具函数) -> 回传给AI大脑 -> AI大脑整理输出给用户。
工具函数
一个最基础的智能体,通常实现了下面的工具函数,以供AI调用:
- 读取文件内容
- 修改文件
- 删除文件
- 执行shell命令
如果稍微扩展下,我们还可以继续实现更多工具函数:
- 网页抓取(web_fetch):让AI可以直接读取某个链接内容
- 网络搜索(web_search):可以实时根据关键词搜索最新内容,但通常结合第三方API来实现
在一轮对话中,我们和AI进行交互,AI会揣测用户意图,然后根据已注入的工具函数集合,按需调用执行,最后将执行结果整理后再输出给用户。
备注:一轮对话一般循环调用多个工具函数。
当你了解工具函数调用后,已经能开发出一个最原始、最简单的智能体了,现在很多AI SDK都已经内置工具函数调用,我们无需了解更深层次的调用原理。
内容存储
由于AI大模型是无状态的,它根本不记得用户说过什么,因此我们就需要将每个窗口的对话内容进行进行存储,下次继续对话时,我们需要手动拼接历史消息,再一起回传给AI,没错,就是这么原始而又粗暴。那么我们具体存储到哪里?通常的做法有:
- 内存: 速度快,效率高,但是一旦重启,对话将丢失,不适合长期存储
- 本地文件: 对于一般小型项目,将对话内容存储到本地是一种简单可靠的方案,据xiaoz了解,目前很多Cli Agent都有存储到本地,用的格式是
.jsonl - 数据库::对于一些中大型的项目,本地文件存储比较有局限,通常会考虑存储到专业数据库,比如SQLite、PGSQL等
- 混合存储: 对于一些特殊场景的智能体,也可能采用“本地存储 + 数据库”混合模式。
对于一个轻量智能体,我们一般选择本地文件存储就够用了,首选格式推荐.jsonl,xiaoz之前也没接触过.jsonl,直到开发AI智能体的时候才有所了解。
简单来说jsonl其实就是由多行json数据构成的一个合集,如果说将每一轮对话整理为一个json对象,那么多轮对话,就是多个json对象,然后一行一段json字符串保存到jsonl中。
模式如何实现?
如果你用过OpenCode之类的编码工具,你会发现它提供plan、build之类的模式,有的工具可能提供多个模式,有的叫法不同,但本质其实都一样,比如:
plan:只读操作,不会去修改、编辑、删除文件build:执行模式,拥有较高权限,不需要经过用户同意可以直接操作文件
一开始xiaoz也不理解这个模式到低咋实现的,后面和AI探讨了一番,才幡然明白,其实就是“提示词 + 条件暴露工具函数”,比如:前端传递参数值为plan,后端读取到这个值后注入提示词,告诉AI,现在处于plan模式,只能只读操作,不能去操作文件。但光靠提示词约束,显然不可靠,因为某些智障AI大模型可能不太遵守提示词,因此我们还需要一个兜底方案。
我们可以将最开始提到的工具函数:读取文件、修改文件、删除文件、执行shell包装为一个工具函数的集合,当为plan模式的时候,这个集合只暴露:读取文件和少量可执行的shell命令,当为build模式的时候则暴露完整的函数集合和更多可执行的shell命令,这样不同模式下对AI可见的函数并不同,plan模式下AI想调用删除也调用不了,因为此时AI压根不知道删除函数的存在。
交互入口
既然我们要和AI进行自然语言对话,那肯定得有个入口,一般常见的方式有:
- WEB端:直接通过网页发送内容给AI
- 客户端:通过客户端将内容发送给AI
- TUI:通过终端界面的方式发送给AI
比如最近Deepseek刚发布的Deepseek harness就是WEB的形式作为交互入口,而腾讯的WorkBuddy则是以客户端的形式作为交互入口,Claude Code一开始则是用TUI这样的终端界面作为交互入口(现在也提供了桌面版),总之入口形式是多样的。
上下文压缩
AI大模型上下文窗口是有限度的,比如我们看到大模型的512K,1M等参数就是指的上下文窗口长度,虽然随着技术进步,上下文窗口越来越大,但目前扔做不到真正意义的无限长度,既然窗口有限度,我们就不可能在一个窗口无限对话,但是我们可以做到虚假的无限对话。
什么是虚假的无限对话?其实就是利用上下文压缩原理,将对话内容进行压缩,对话轮次多了之后,让AI进行一次总结,然后携带总结后的内容继续和AI对话,但这样存在一个弊端,压缩的内容可能丢失部分关键信息,这时候就会表现出,窗口快塞爆的时候你发现AI似乎有些降智(可能工具无形中已经给你压缩了上下文),所以上下文压缩并不是绝对可靠,但由于窗口大小限制又不得不用。
常见的上下文压缩方案
- 不压缩:这个方案很暴力,达到一定的对话轮次(或者tokens数量达到一定值后),直接将最初的对话直接裁剪丢弃,这样窗口内容就随之减少,但是AI也忘记了最初的内容,显然这个方案最简单,但很暴力,效果也不好。
- 智能压缩:达到一定的对话轮次后(比如60轮),这时候程序上进行逻辑判断,将前30轮的对话用AI总结一次,再继续对话的时候实际上变成了:总结内容 + 后面的30轮对话,这个方案提升了一点复杂度,但依然比较简单,效果更好了一些,但上面说过,总结的时候可能会丢失部分关键信息,质量也可能下降。
- 语义召回:你可能见过市面上有一种叫做
向量模型的,其实就是将输入的内容进行向量化,然后存储到专门的向量数据库中,当你和AI对话的时候,AI除了读取一定的上下文外,可能还会通过向量搜索的方式,通过语意去寻找对话中最匹配的内容,这个方案比较复杂,对于长对话来说效果也比上面2个方案更好一些,但窗口过大时依然存在质量下降。 - 其它:市面上应该还有一些更先进的做法,欢迎留言告诉xiaoz
实现技能(skills)
想必你已经听说并使用过AI技能了吧?我们也可以把AI技能叫做skills,很多桌面版智能体还内置技能中心,可以一键安装,很方便不是?其实skills的本质就是提示词注入,帮助AI理解,规范AI行为等,但是我们不能将整个skills内容注入到提示词中,不然多个skills容易导致提示词过于冗长,非常浪费tokens,所以skills有个巧妙的设计:“元数据 + 完整内容”
元数据
简述这个技能具体是干嘛的,我们通常只会将元数据注入到AI提示词中。
完整内容
这部分通常包括:描述使用场景 + 操作步骤 + 示例。
实现
所以我们只需要将元数据注入到AI提示词中,让AI知道个大概,直到我们的对话真的需要用到某个技能的时候,AI才回去读取这个技能的完整内容。
但技能并非越多能力越强,因为每个技能都需消耗宝贵的上下文窗口(Token)并增加调用时的“选择困惑”,过多的技能会相互干扰触发判断、挤占核心推理空间,反而导致AI在具体任务上的响应速度和执行准确性双双下降。
设计优化
所以我们在设计技能的时候,可以考虑通过“全局技能 + 项目技能 + 限制技能总数”来进行控制,而不是让用户无限的安装和增加技能,不然最后适得其反。
AI问询交互
你如果用过Coding CLI你会发现有的时候AI会弹窗询问,让你做选择,一开始我很好奇,AI是如何实现用户等待并继续的,因为HTTP连接通常具有超时时间,不可能一直处于等待状态浪费资源。
后面发现其实这是一个虚假的表象,AI在发出问询对话的时候通常遵循一定的格式,发送出去后这轮对话就已经结束了,只是前端捕获了这种特定格式,然后再弹窗让用户选择,然后继续回传给AI,回传给AI的时候实际上是拼接了一轮新的对话,但前端通过虚假处理,看起来像是在一轮对话中完成。
ACP协议
Agent Client Protocol (ACP) 是一个开放协议,旨在标准化AI编程助手(Agent)与客户端之间的通信。当你实现ACP协议支持后,那么任意支持ACP协议客户端就可以对你的智能体建立连接和发起通信,比如Zed、VS Code、Zacp、Codex等都可以通过ACP协议连接你的智能体进行对话。
ACP协议是可选的,如果你希望你的智能体拥有更强的通用性,可以考虑支持ACP协议,不同的开发语言都有现成SDK,直接调用实现即可,初期不需要太深入的理解。
MCP协议
MCP(模型上下文协议,Model Context Protocol) 是一个开放标准,旨在统一AI模型与外部数据源、工具之间的连接方式,让AI助手能通过一个标准化接口访问任意资源,避免为每个新数据源或API重复开发定制集成。你可以把它理解为AI领域的“USB-C接口”——一个通用协议,让AI能即插即用地连接整个世界。——这段内容引用自AI
目前xiaoz也只是通过MCP框架直接调用MCP服务端,对这部分理解不算深入,所以就没法展开细聊,一般情况来说我们开发一个Agent只需要具备MCP调用能力即可,不需要去实现MCP能力,MCP能力能力属于MCP服务端范畴,对于一个轻量智能体来说MCP调用也是可选的。
结语
通过这篇文章了解智能体大概框架和思路后,再去指挥AI去开发一个自己的轻量级智能体应该足够了。但如果还需要更加完善,做到好用而不是够用,则需要不断优化细节和修复BUG。
此外xiaoz开发的轻量级智能体Zlite已在Github开源:https://github.com/helloxz/zlite ,感兴趣的朋友和结合AI进行解读和拆解,希望对你有所帮助。
