怎么造一个 Claude Code 级别的 AI 编程 Agent?9 层工程内核万字拆解
前言:
造一个编程智能体(Coding Agent),门槛不高——一个 while 循环调模型、跑工具、把结果喂回去,二十行代码就能跑通 demo。但让它在一个十万行的代码库里稳定跑完一个跨文件重构任务、在第 50 步还记得第 1 步的约束、写完代码自动符合风格规范、接本地小模型不幻觉、闲置时自己整理记忆越用越聪明——靠的不是模型,而是循环周围那一整套工程基础设施。
这篇文章把我们在 AuraMate 上造编程智能体的工程内核拆开讲:Agent Loop 怎么防死循环、上下文怎么压缩、编码工具链怎么设计、LSP 怎么集成、写后怎么自动格式化、幻觉怎么检测、记忆系统怎么搭、多模型怎么适配、技能和 MCP 怎么扩展。每个工程内核都讲清楚怎么实现、为什么这么实现、有哪些坑。这些不是理论,是十几万行 Go 代码和无数次生产故障打磨出来的。全文约 1.6 万字,建议 PC 端阅读。
第一章:搭 Agent Loop 主循环
Agent Loop 的核心是 observe → think → act 的循环。跑起来容易,跑长了不劣化难。我们在这条循环上踩过三个大坑:死循环、幻觉、上下文爆炸。这一章讲死循环,后两个后面讲。
1.1 不要设总步数硬上限
直觉上,防死循环最简单的办法是设一个总步数上限——跑满 50 步就停。我们一开始也是这么做的,结果发现会误杀合法长任务:跨 20 个文件的重构天然需要上百步,硬总上限会让模型跑到一半被截断,留下半成品代码比死循环还危险。
所以我们改成不设总步数硬上限,把步数管理从全局收窄到修改后局部:维护一个"修改后步数"计数器,从最后一次文件修改算起,允许再走 28 步用于验证、跑测试、收尾。同时还有限制单轮修改次数(12 次)和静默恢复次数(3 次)的辅助计数器。
为什么是 28 步?这是反复调出来的——太少(比如 10 步)会打断模型做合理的多步验证;太多(比如 100 步)就失去熔断意义。28 步足够模型跑一轮测试、看结果、做一次针对性修复,但不够它无限转圈。
1.2 两段式软干预
超过 28 步还没收敛,触发"修改后分析瘫痪"检测。这个熔断的精髓在于两段式处理:
第一次触发不直接停,而是注入一条系统检查点消息,强制模型三选一——跑测试/编译/验证、再做一次有针对性的修改、或输出当前结果说明剩余风险——然后重置计数器继续。只有第二次再触发才真正停下问用户,并触发一次摘要。
为什么两段式?直接硬停会打断合法任务(模型可能正在做合理的多步验证),但完全不停会无限转圈。两段式给了模型一次"自我纠偏"的机会——很多时候第一次提醒后模型就会去跑测试,跑完发现没问题就收敛了。第二次还纠不回来才认为真的卡死了。这种设计只有跑过大量真实任务、见过各种边界情况才会加。
1.3 用户续接的绕开机制
还有个细节:如果用户对上一轮的停止文案明确回复了"继续"语义,本轮会绕开修改类熔断。这是个很脏但很真实的用户体验问题——否则每个新任务都会把同一段停止文案再吐一遍,用户会被烦死。能想到处理它,是因为我们在生产里被这个问题坑过。
1.4 流式响应与工具调度
循环的每一轮要做三件事:把 context 发给模型、流式接收响应、从响应里提取工具调用并执行。
流式响应处理是个容易踩坑的点。模型返回的是 SSE 流,按行解析,工具调用以 tool_use block 的形式穿插在文本里。难点在于工具调用的 JSON 可能分多个 chunk 到达——你不能假设一个 chunk 就是一个完整的 JSON。我们的做法是按 block 累积部分 JSON,等 block 闭合了再解析。流中断(网络抖动、超时)要做恢复,已累积的部分不能丢。
工具调度走 BaseTool 接口:每个工具实现 Run 方法,附带一个 ToolInfo 结构体(Name、Description、DisableAutoSummary 等字段)。模型输出 tool_use 后,dispatcher 按 name 找到对应工具、解析参数、调 Run、收集结果。工具描述从 ToolInfo 自动生成注入 system prompt——这样加新工具只改一处,不用手动维护 prompt 里的工具列表。
1.5 按角色分配工具集
不是所有代理都该拿到全套工具。我们把工具集按角色分:编码型代理(CoderAgent)拿到完整的 LSP 工具集加文件编辑工具;非编码型代理(生活助理、普通对话代理)拿到精简工具集,不给 LSP、不给高风险文件操作。这降低了非编码代理误操作代码库的风险——一个聊天代理不应该能 rename_symbol。
这个设计有个延伸:LSP 工具集只注册进编码代理的工具列表,非编码代理连工具描述都看不到,自然不会尝试调用。这是"最小权限"在工具层的落地。
第二章:上下文压缩工程
写到第 50 步时还记得第 1 步的约束吗?这是编码智能体最大的工程难题。上下文窗口有限,但任务产生的对话、工具输出、报错信息无限。怎么在有限窗口里保留最相关的信息,决定了 Agent 能跑多长的任务。
2.1 四阈值协同
我们的上下文管理是四个阈值协同工作,不是常见的"软硬两档":
| 阈值线 | 触发动作 | 性质 |
|---|---|---|
| 65% 软档 | 异步摘要(后台 goroutine 压缩,主 loop 不阻塞) | 悄悄压缩,用户和模型无感 |
| 70% 压缩目标 | 摘要把上下文压到这个比例(低于硬熔断线留 headroom) | 压缩终点 |
| 80% 硬档 | 同步阻塞摘要 + 5 次重试(主 loop 必须等) | 再不压就要爆 |
| 92% 保命档 | 硬截断 + checkpoint 落盘 | 最后防线,至少能恢复 |
四个阈值不是孤立的,而是一条递进防线:65% 先悄悄压、压不住到 80% 强制压、还压不住到 92% 保命截断。70% 的压缩目标卡在 65% 和 80% 之间,是"压缩到哪算够"的目标值。
2.2 压缩目标为什么要在熔断线下方留 headroom
这是踩坑踩出来的。最初压缩目标和熔断线重合,结果压缩完一加新消息立刻又触发熔断,loop 陷入"压缩 → 触发 → 压缩"的抖动——模型每轮都在等压缩,什么都干不了。后来把压缩目标调到熔断线下方 10 个百分点,留出"保质期"——压缩完之后还能塞几轮新消息才会再次触发。这个 10% headroom 只有跑过生产、见过抖动才会加。
2.3 失败保护
摘要服务会抖动。如果摘要 API 偶发失败就把整个 Agent 拖死,那是设计缺陷。我们加了失败保护:最多重试 5 次,每次失败后冷却 30 秒。5 次都失败就放弃这次摘要、等下一轮再试。摘要是副作用路径,不能让它把主 loop 拖垮——这个原则要守住。
2.4 工具输出源头裁剪
除了对话级压缩,还有工具输出级的源头控制。任何单次工具输出超过 20000 字符(grep 命中几百行、read 大文件),先就地摘要再入 context。
但有一类工具被豁免:read、read_file、cat、grep。理由是这些工具的本职就是返回原始内容——把 grep 结果摘要成"找到了一些匹配"是没用的,模型需要看具体匹配行。这是个聪明的取舍:无脑摘要所有长输出会破坏代码搜索的可用性,但完全不摘要会让一次大 grep 就撑爆 context。按工具语义分类豁免,是工程上的精打细算。工具还可以通过 DisableAutoSummary 标记主动关闭摘要,给工具开发者留了逃生口。
2.5 KV Cache Token 追踪
我们还做了一件很多 Agent 没做的:在 LLM 响应里解析并累计 KV cache 命中 token,单独维护 CacheReadTokens 和 CacheCreationTokens 两个字段,成本核算时 cache hit 单独按更低价计费。
这不是性能优化,是企业算账。cache hit token 通常是 input token 价格的 10%,单独量化才能告诉客户"你省了多少钱"。在私有部署场景,客户最关心 token 成本——尤其是接本地小模型时,每次 cache miss 都是真金白银的推理算力。把 cache 命中率做成可观测指标,是给企业客户的成本透明度。
第三章:编码工具链设计
这一章是编码智能体最接地气的部分。工具链是模型和代码库之间的接口,每个工具的实现细节决定了模型能不能精确、安全、高效地操作代码。只关注工具有哪些是不够的,真正决定可靠性的是每个工具的边界处理。
3.1 精确字符串替换与唯一性校验
edit 工具做精确字符串替换:给定 old_string 和 new_string,把文件里的 old_string 替换掉。难点在唯一性校验。
如果 old_string 在文件里出现多次,直接替换会改错地方。我们的做法是:old_string 必须在文件里恰好出现一次,否则报"歧义匹配"错误,要求模型提供更多上下文让 old_string 唯一。这是个强约束——它强迫模型在替换前先精确定位,而不是模糊匹配。old_string 为空时表示整文件替换,走另一条审批路径。
权限审批在这个工具里分了四个拦截点,分别对应整文件替换、内容删除、内容编辑、写入失败恢复,每个拦截点都用结构化的审批参数(包含文件路径和 diff)发起请求。为什么分四个点而不是一个?因为不同操作的破坏性不同,审批 UI 需要展示不同的 diff 形态让用户判断——整文件替换的 diff 和局部删除的 diff 审查重点不一样。
3.2 多 hunk 补丁
patch 工具处理多 hunk 补丁,适合一次性改多个不连续的位置。三个权限拦截点分别对应文件新增、文件更新、文件删除——三种操作破坏性递增,分别审批。
和 edit 的区别在于:edit 是单点精确替换,适合小修小补;patch 是多 hunk 批量修改,适合重构。两者并存是因为模型在不同场景下需要不同精度——改一个函数用 edit,重构一个模块用 patch。
3.3 文件写入的原子性与目录创建
write 工具做整文件写入。两个工程细节:一是写入前先创建必要的父目录——模型经常需要写新文件到不存在的目录,如果工具不自动建目录就会失败;二是权限审批用结构化参数(路径 + diff)发起。
batch_write 工具做批量写入,标注为"best-effort atomic"。它的实现是先备份再写入、失败回滚:写入前先把已存在的文件备份到内存,新建的文件记录路径;如果任何一个文件写入失败,触发回滚——恢复所有备份、删除所有新建文件。这不是真正的数据库级原子事务(没有 WAL、没有 fsync 同步),而是应用层的 best-effort 回滚。但在编码场景够用了:要么全部写成功,要么恢复到写入前状态,不会留下一半改一半没改的脏状态。
3.4 Shell 执行与只读白名单
bash 工具执行 Shell 命令。权限设计有个细节:维护一个只读安全白名单,命中白名单的命令(如 ls、cat、git status)直接放行不审批,非白名单命令才走审批,审批参数包含命令字符串和超时。这平衡了流畅性和安全性——只读命令频繁调用,每次都审批会卡死体验;写命令破坏性强,必须审批。
3.5 长任务命令三件套
我们有套 run_command / check_command_status / stop_command 三件套,专为长任务命令设计(跑测试套件、起开发服务器、长时间构建)。
bash 是同步阻塞——命令跑完才返回结果,适合秒级命令。run_command 是异步——通过进程组管理 fork 后台进程、立即返回 task ID,模型可以继续干别的,需要时再查状态或停止。check_command_status 通过共享状态存储(内存 map)查任务状态,返回 stdout、stderr、exit code。stop_command 先发 SIGTERM 到进程组,没响应再 SIGKILL 强制终止,最后清理资源。
这是为长任务设计的——跑一个测试套件可能要几分钟,同步阻塞会让 loop 卡死。三个工具协作的关键是共享状态存哪:用内存 map 存 task ID → 进程句柄/输出缓冲的映射,进程组管理避免僵尸进程。
这里有个已知的设计权衡:run_command 持有权限字段但不调用审批。理由是长任务命令往往是模型在任务中段自发触发的验证步骤(跑测试看改对没有),每次都审批会打断长任务的流畅性。这是个安全性和流畅性的取舍——bash 严审批保安全,run_command 放行保流畅。代价是 run_command 成了审批绕过点,企业部署需要单独收紧。
3.6 搜索:ripgrep 优先 + 回退
grep 工具体现"用最好的工具,但要能回退"的工程哲学。优先用 ripgrep——先 exec.LookPath("rg") 检查系统有没有装,有就用 exec.CommandContext 调起,享受 ripgrep 的速度和正则能力;没有就回退到 Go 标准库的 regexp 包做内置匹配。这样既能在装了 ripgrep 的机器上跑得飞快,又能在没装的机器上不罢工。
两个安全限制:处理最多 5000 个匹配(防止超大结果集拖垮后续处理)、截断过长行(防止单行超长内容撑爆 context)。grep 在工具输出摘要里被豁免——因为 grep 的本职就是返回原始匹配行,摘要了就没用。这个豁免和它的安全限制是配套的:既然不摘要,就必须从源头限流。
3.7 代码库结构树:目录遍历而非 AST
repo_map 工具生成代码库结构树。需要澄清一个常见误解:它不是基于 AST 符号提取,而是目录遍历——递归 walk 配合 maxDepth 深度限制和 ignoreMap 排除规则,生成一棵压缩的目录树。
这个设计取舍是有意的:AST 符号提取需要为每种语言写 parser、维护 tree-sitter 语法树,复杂度高且语言覆盖有限;目录遍历语言无关、实现简单、足够让模型理解项目骨架。模型要符号级精度时,用 LSP 工具(document_symbol、lookup_symbol)按需获取,而不是在 repo_map 里一次性提取所有符号。
这是个"分层精度"设计,有三层而不是一层:repo_map 给宏观骨架(目录遍历,便宜、快、语言无关),collectCodeSymbols 给中观符号(正则提取 func/type/const/var/interface 定义,不需要 parser),LSP 的 document_symbol 给微观 AST(按需、精确、带类/方法/字段树)。
为什么要分三层?因为代码结构理解的精度需求是分级的。模型刚进项目时只需要知道"有哪些目录、哪些文件"——repo_map 够了,零成本。要定位"这个文件有哪些函数"——collectCodeSymbols 够了,正则扫一遍就出符号列表,不需要为每种语言接 tree-sitter parser。要精确到"这个函数的参数类型、这个类的字段、这个方法的完整签名"——才调 LSP document_symbol,拿真正的 AST 级符号树。
collectCodeSymbols 的设计值得展开。它没有用 go/ast 或 tree-sitter 做完整语法树解析——那需要为每种语言维护一套 grammar,复杂度高、语言覆盖有限。它用一个正则匹配 func/type/const/var/interface 关键字,提取紧随其后的标识符作为符号名。这是个"够用就好"的取舍:牺牲了参数类型、字段类型这些细节,换来了语言无关(Go/Rust/Python/Java 的符号定义关键字大同小异)和零依赖。需要细节时由 LSP document_symbol 补——LSP 由各语言的 server 实现做 AST,AuraMate 不用自己维护 parser。
这套分层精度是工程上的精打细算:90% 的代码导航只需要正则符号就够,不必每次都走 LSP;剩下 10% 需要精确签名的,再走 LSP。避免了"要么没 AST、要么全量 AST"的二选一困境。
3.8 文件读取:分页与搜索定位
read 工具支持 offset/limit 分页,但它的 offset 不只是数字——还支持正则搜索定位:给定一个搜索词,工具先用正则找到匹配行,从那一行开始读。这对大文件很有用——模型不必先读前 1000 行再找目标,可以直接跳到包含特定函数定义的位置开始读。还支持二进制文件检测,避免把二进制内容当文本读进 context 污染。
3.9 文件历史与回滚
file_history 工具基于 git 记录文件修改历史——每次修改自动提交、记录日志,需要时通过 git 命令回滚。这比自研版本控制系统靠谱:git 已经处理好了所有边界情况(合并、冲突、diff),没必要重新发明轮子。模型可以查"这个文件之前长什么样",也可以回滚到某个历史版本。
3.10 任务进度跟踪
todo_helper 工具让模型以结构化方式管理任务进度。模型在复杂任务里调用它记录和更新 todo 项,配合任务跟踪逻辑。这解决了长任务里模型"忘了自己做到哪一步"的问题——todo 列表是外部记忆,比靠 context 里的对话回忆靠谱。
3.11 工具链的设计哲学
把这十来个工具放一起一览:
| 工具 | 职责 | 审批 | 关键特性 |
|---|---|---|---|
| edit | 精确字符串替换 | 审批 | 唯一性校验,old_string 必须唯一 |
| patch | 多 hunk 补丁 | 审批 | 新增/更新/删除三拦截点 |
| write / batch_write | 写新文件 / 批量写 | 审批 | 自动建父目录;批量写 backup-then-rollback |
| bash | 同步执行命令 | 审批 | 只读白名单(ls/cat/git status)直接放行 |
| run_command / check / stop | 异步后台命令三件套 | 绕过审批 | 长任务不阻塞,进程组管理 |
| grep | 代码搜索 | 豁免摘要 | ripgrep 优先 + regexp 回退 + 5000 匹配上限 |
| repo_map | 代码库骨架 | 豁免摘要 | 目录遍历,语言无关 |
| read | 读文件 | 豁免 | 正则定位 offset + 二进制检测 |
| file_history | 文件回滚 | — | 基于 git,不重新发明轮子 |
| todo_helper | 任务进度 | — | 外部记忆,防"忘了做到哪一步" |
把这些工具放一起看,能总结出几条设计哲学:按破坏性分级审批(只读白名单 → 写操作审批 → 危险操作硬拦截)、按语义分类摘要(代码搜索豁免、其他工具摘要)、分层精度(repo_map 给骨架、LSP 给符号)、最好用专业工具但能回退(ripgrep 优先、regexp 回退)、长任务和短任务分治(bash 同步、run_command 异步)、不重新发明轮子(file_history 用 git)。这些不是孤立的工具实现,而是一套连贯的工具链工程观。
第四章:LSP 集成
没有 LSP 的 Agent 靠 grep 找符号。在 1000 行项目里没问题,在 10 万行项目里是灾难——"重命名 User 类"会把注释、字符串、同名变量全改了。LSP 给的是语义级答案,这是编码智能体从"补全工具"升级为"工程师"的分水岭。
4.1 六个 LSP 工具的分工
我们实现了六个 LSP 工具:go_to_definition(跳转定义)、find_references(找引用)、rename_symbol(跨文件重命名)、document_symbol(文档符号树,AST-like 输出)、lookup_symbol(工作区符号查找)、get_diagnostics(诊断信息)。这六个覆盖了代码导航和重构的核心操作——模型可以精确地找到符号定义、查看所有引用、安全地跨文件重命名,而不是靠 grep 模糊匹配。
4.2 server 类型检测的顺序陷阱
LSP 客户端启动时要先判断 server 类型,才能选对握手方式。我们用命令路径的字符串包含匹配来判断——比如路径含 “gopls” 是 Go server,含 “rust-analyzer” 是 Rust server。这里有个真实的 bug 故事:ruff(Python linter)的检测分支必须在 python 分支之前。原因是 pip 安装的 ruff 路径形如 ...\Programs\Python\Python311\Scripts\ruff.exe,路径里含 “Python” 字样。如果 python 分支在 ruff 之前,ruff 会被误判成 Python server,然后走 ruff 不支持的 workspace/symbol 握手方式,30 秒超时。
这个 bug 只有打包后部署到真实用户机器才会暴露——用户机器上装了 pip 的 ruff,路径里恰好有 “Python”。开发环境永远碰不到,因为开发环境用的是内置 bundle 的 ruff,路径不含 “Python”。这是个典型的"环境差异导致的隐藏 bug",能发现并修复它是因为真的在真实用户环境上调试过。
教训:字符串匹配做类型检测要按"更具体的关键词优先"排序,否则会被包含关系坑。理想做法是用 server 的初始化响应里的 capabilities 字段做能力协商,而不是靠路径猜——但路径猜是冷启动快速分流的最简方案,能力协商要等握手完,启动慢。
4.3 进程生命周期管理
LSP server 是子进程,需要管理它的生命周期。Go 的 cmd.Wait() 有个约束——只能调用一次,多次调用会 panic。我们用一个独占的 monitorProcess goroutine 调 Wait(),进程退出时设置原子标志、关闭 channel。WaitForServerReady 改读这个原子标志,这样 server 崩溃时能早退,不用等满 30 秒超时。Close() 复用同一个 channel 避免二次 Wait() panic。
这是个 Go 进程管理的标准套路,但很多 LSP 客户端实现会踩坑——要么忘了 Wait() 只能调一次、要么没在崩溃时早退、要么 Close 时泄漏 goroutine。把这三点都处理对,LSP 客户端才算生产可用。
4.4 PATH 优先与 bundle 回退
LSP server 的命令解析遵循"PATH 优先、bundle 回退":用户在 PATH 上装了 server 就用用户的(尊重用户环境、不污染客户系统),没装才回退到内置 bundle。对二进制类 server(如 ruff,单文件可执行),直接用 PATH 命中;对需要依赖的 server(如 TypeScript server 需要 node_modules),检查 bundle 是否带了依赖。
这个设计在企业场景很重要:企业用户可能用自己合规审计过的 ruff 版本,强制用内置 bundle 会绕过合规审计。PATH 优先让企业保持对工具版本的控制权。
4.5 写后自动格式化:autoformat
写完代码不格式化是个常见问题——模型生成的代码缩进混乱、import 顺序乱、不符合项目风格规范。传统做法是依赖模型自觉或事后人手跑 gofmt/ruff。我们在三个写工具(write/edit/patch)里集成了 autoformat:文件写入磁盘后,自动触发 autoFormatViaLSP,调 LSP 的 textDocument/formatting 让语言 server 格式化整个文档,再把格式化结果写回文件。
这个机制依赖 LSP Registry——格式化由对应语言的 LSP server 执行(Go 用 gopls 跑 gofmt 语义格式化、Python 优先用 ruff)。几个工程细节:nil registry 时跳过格式化不报错(LSP 没就绪不能阻塞写入——写入是主路径、格式化是增益);非 Go 文件按 server 能力决定是否格式化;格式化失败不回滚写入(格式化是锦上添花,失败保留原始写入比失败回滚强)。
autoformat 的价值是"写后即合规"——模型不用消耗 token 去手动调格式,写完自动符合风格规范。这在长任务里尤其重要:跨 20 个文件重构,每个文件都手动格式化要几十次工具调用,autoformat 把这部分完全自动化了。这是编程智能体区别于通用 Agent 的细节——通用 Agent 不在乎代码风格,编程智能体必须在乎。Cursor 这类 IDE 内嵌的 Agent 靠 IDE 自身的 format-on-save 兜底,独立 Agent 没有IDE 兜底,必须自己在工具层做。
第五章:幻觉检测护栏
编码智能体有个高频幻觉模式:用户说"帮我修这个 bug",模型回复"我已经修改了 foo.go,把 bar() 改成了 baz()"——但它根本没调用任何工具,只是文本上"声称"做了。如果 loop 不检测,用户以为修好了,实际代码没动。这种"空声称"幻觉在弱模型上尤其常见。
5.1 回执式检测
我们的幻觉护栏基于一个核心洞察:检测幻觉的正确信号是工具执行回执,不是模型文本里的关键词。
检测逻辑提取三个信号:用户是否要求了动作、机器人是否声称了动作、最近是否真正调用过工具。触发条件是这四个信号的合取——用户要求了动作 ∧ 机器人声称了动作 ∧ 但最近没真正调用工具 ∧ 允许执行引导。关键信号是第三个:历史里有没有真实的工具调用记录。如果有真实工具调用,那模型声称做了就是真的;如果没有,那声称就是幻觉。
5.2 放弃关键词匹配的演进
这个设计有个重要的演进故事。早期版本用关键词匹配——如果模型回复含"建议""推荐"就跳过幻觉挑战。但这既会误判(模型说"建议"的同时其实在声称动作)也会漏判(模型不用这些词但照样空声称)。后来明确放弃了关键词匹配,改用回执式检测,源码注释直接引用了 arxiv 上的 receipts-based verification 论文作为依据。
教训:基于模型文本的关键词匹配是脆弱的——模型换个说法就绕过。正确的信号应该来自模型行为本身(有没有真实工具调用),而不是模型的自我描述。这是 2026 年的工程最佳实践。
5.3 防护栏自身变成死循环
防无限循环用 retryCount < 2:往回看 3 条消息里有多少 “SYSTEM MONITOR:” 前缀,最多挑战 2 次,第 3 次就放行。因为如果模型连续两次被挑战还不调用工具,再挑战也没用,不如让用户介入。这是个务实的退避——护栏本身不能变成新的死循环源。
5.4 为什么要做这层护栏
这层护栏是为接小模型准备的——本地部署的 70B 模型幻觉率比最强的云端模型高一个量级,没有这层护栏根本不能用。如果只接最强云端模型,可以省掉这层靠模型自觉。但我们目标是私有部署、接本地模型,就必须有这层兜底。
这是个普遍规律:模型越弱,框架越要做兜底;模型越强,框架可以越薄。工程复杂度是模型能力的补偿函数。一个为弱模型设计的 Agent 内核,必然比一个为最强模型设计的 Agent 内核更复杂。这不是缺陷,是场景适配。
第六章:记忆系统
只靠 context window 记忆是不够的——窗口有限,长任务必然丢信息。要真正解决"第 50 步还记得第 1 步约束"的问题,需要外部记忆系统。但记忆系统做到能用,远不止"存进去、查出来"这么简单——还要解决冲突、去重、来源可信度、跨语言检索、衰减遗忘、自主改代码的安全边界。我们搭了一套叫 IKTS(集成知识树系统)的记忆引擎,它不只是数据库,是个有治理、会学习的记忆系统。
6.1 四层记忆模型
IKTS 把记忆分成四层,参考认知心理学的记忆巩固理论:
| 层 | 名称 | 存什么 | 读写频率 | 检索方式 |
|---|---|---|---|---|
| L1 | Core 核心层 | 身份与原则(角色定义、用户最高指令) | 只读/极少写 | 无条件全量注入 context 最前端 |
| L2 | Domain 领域层 | 经验技能(用户偏好、项目规范、最佳实践) | 长期读写 | Category 精确查询 |
| L3 | Knowledge 知识层 | 事实档案(代码事实、客观信息) | 大量读写 | FTS5 + embedding 向量召回 |
| L4 | Episodic 情景层 | 意识流(对话日志、工具结果、报错) | 高频写、短暂留 | 滑动窗口 + FTS5 + embedding |
四层都用 SQLite 存储,节点结构统一:Layer、Category、Content、Summary、Keywords、Confidence、Source、时间戳。L1/L2 靠 Category 精确查询(结构化),L3/L4 靠 FTS5 全文检索加 embedding 向量召回(半结构化)。
6.2 图记忆:记忆之间的关系网
记忆不是孤立的条目,记忆之间有关系。我们给记忆系统加了图结构——Link 操作建立两条记忆之间的关系(relation 字段描述关系类型,weight 描述关系强度),GetRelated 查询某条记忆的关联记忆。
为什么需要图?举个例子:L3 存了"用户在用 React",L3 还存了"用户讨厌 Bootstrap"。如果只有平铺存储,问到"前端框架偏好"时可能只召回一条。有了图,Link 把这两条用 “frontend_preference” 关系连起来,查任何一条都能顺藤摸瓜找到另一条。这是 GraphRAG 的雏形——不只靠向量相似度召回,还靠图遍历扩展关联记忆。
图记忆的价值在长周期任务里:用户两周前说过的偏好,可能因为关键词不匹配而向量召回不到,但只要它和最近某条记忆有图关系,就能被遍历到。这比纯向量检索鲁棒。
6.3 记忆治理合约:不只是 CRUD
这是记忆系统最容易做粗、但我们做得最用心的部分。记忆写入不是简单的 insert,而是走一套治理合约,产出可审计的决策。
每次写入产出 MemoryWriteDecision,包含合约名、动作(4 种)、原因码(15 种)、冲突键、来源信息。4 种写入动作:inserted(新增)、reused_existing(复用已有)、overwrote_existing(覆盖已有)、rejected_conflict(冲突拒绝)。15 种写入原因码覆盖了所有决策路径——合约应用、来源可信度评估、冲突键检测、精确重复、语义重复、覆盖执行、插入执行、embedding 生成/不可用、来源优先级(已有优先/新入优先)、显式覆盖请求、证据附加。
搜索也一样,11 种搜索原因码记录每次检索用了哪条路径——exact_match/fts/vector/vector_unavailable/cache_wait_timed_out/fts_fallback/list_fallback/category_filtered/no_results 等。这意味着每次记忆操作都可追溯:为什么这条记忆被写入、为什么被召回、走了哪条检索路径,全有记录。
MemoryWriteRequest 带 ConflictKey(冲突键)、Evidence(证据链)、AllowOverwrite、AllowSemanticDedup 等字段。冲突检测靠 ConflictKey——同 key 的新记忆不会静默覆盖旧记忆,而是按合约决策(拒绝/覆盖/复用)。来源可信度评估决定"已有优先还是新入优先"——可信来源的记忆不容易被覆盖。证据链让记忆可回溯到原始依据。
为什么做这么重?因为记忆是 Agent 的长期资产,脏数据会持续污染决策。一个被错误固化的偏好(比如误把"用户暂时用 Tab"固化成"用户永远用 Tab")会在后续所有任务里误导模型。治理合约保证记忆写入是可解释、可审计、可冲突消解的,不是黑箱 insert。这是企业级记忆系统和玩具 RAG 的分水岭。
6.4 四路搜索融合
记忆检索不是单路向量召回,是四路融合:FTS5 全文检索、向量检索(cosineSimilarity 余弦相似度)、词法回退(lexical fallback)、精确匹配(exact match)。四路结果用 fuseResults 融合,融合时可带 lexicalBias 权重调整词法匹配的比重。
为什么要四路?因为单一检索都有盲区。向量检索懂语义但慢、且对小模型 embedding 质量敏感;FTS5 快但只懂关键词、不懂同义词;精确匹配零误报但漏报高;词法回退是向量不可用时的保底。四路融合让检索鲁棒——任何一路失效(比如 embedding 服务挂了),其他路顶上,不至于查不到。
跨语言是个细节但重要的点。我们做了 CJK 检测(isCJKRune/queryContainsCJK)和跨语言词法扩展(expandCrossLingualLexicalTerms)——中文查询能匹配英文记忆、英文查询能匹配中文记忆。这在中文用户场景里是刚需:用户用中文问,但代码符号、技术文档是英文的,记忆库里中英混杂。不做跨语言扩展,中文查询召回率会塌掉一半。
6.5 打分、去重与缓存
召回结果要排序,靠多因子打分:recencyBoost(最近访问加分,最近用过的记忆更可能再用)、accessBoost(访问次数加分,高频记忆更重要)、confidenceBoost(置信度加分,高置信记忆优先)、categoryListSortScore(分类内排序)。多因子加权而非单靠向量相似度,让排序更符合直觉。
去重(Deduplicate)基于相似度阈值,支持 dryRun 预览模式——先看会删哪些再决定是否执行。记忆库用久了会有语义重复(同一偏好被不同表述存了多遍),不清理会让检索结果充满冗余。dryRun 让清理可审阅,避免误删。
缓存层(CachedMemory + memoryUsageSignal)把热记忆驻留内存,避免每次检索都打 SQLite。MarkUsed 更新访问计数和时间戳(喂给 recencyBoost/accessBoost),UpdateConfidence 动态调整置信度(被验证有效的记忆提置信,被否决的降置信)。记忆不是静态存档,是动态演化的——用得越多越准。
6.6 意图识别:模式短路 + LLM 分类
detectIntent 做意图识别,决定本轮走哪个 prompt。这里有个关键优化:模式短路。如果用户已经显式选了 coding/normal/autonomous 模式,直接返回固定 intent,不调 LLM——省一次 LLM 调用(200-500ms + token)。注释写得很直白:coding 模式不该被 chat 模式的"老朋友/呀呢啦"口吻污染专业身份,normal 模式不该被误导去用不存在的 LSP 工具。
模式没固定时,用 LLM 做四分类(coding/task/search/chat)。这里我们用的是 LLM 分类而不是 embedding 或关键词——注释引用了 2026 年的最佳实践(OpenAI/Anthropic/Vercel AI SDK 都这么推荐),关键词匹配是非确定性路由的反模式,LLM 原生理解才是正道。用一个轻量 summarizer 模型做分类,3 秒超时,summarizer 不可用时 fallback 到默认 intent。
清理输入里的环境标签(<cwd>...</cwd>、<env>...</env>)后再分类——这些标签会干扰分类器,而且对意图判断没用。
6.7 并行认知管线
每轮 loop 开始时,用 errgroup 并行跑三件事:加载并构造历史上下文、意图识别、广域 RAG 检索。三者无数据依赖,并行后延迟从"三者之和"压到"三者之最大值"。
并发安全靠"只有写历史的任务碰共享变量、另外两个只写局部变量"来保证——用 errgroup.Wait() 后才读共享变量,隐式同步而非显式锁,代码更清晰。Task C(RAG 检索)失败不会拖垮整条管线——只记 warning,因为 RAG 失败不该阻断主 loop。
这层并行的价值在接小模型时最明显。本地部署的模型推理慢,如果历史加载、意图识别、RAG 检索串行跑,每轮 loop 起步就要几秒;并行后压到最慢那个的耗时。这是 Go + goroutine 的天然优势,但也只有把 loop 拆细了才能用上。
6.8 自主模式下的工具沙箱:Guard
编程智能体除了人机交互的编码模式,还可能跑在自主模式——用户给个模糊目标让它自己干。自主模式下没有人在循环里逐个审批,但 AI 主动改文件的风险更高。我们用 ToolGuard 包裹所有工具(WrapToolsWithGuard),在自主模式下做硬沙箱。
Guard 的策略是分级放行:只读工具(ls/glob/read/grep/repo_map/fetch/manage_core_memory)直接放行——这些不破坏任何东西;写工具(write_file/edit_file)做路径限制——只允许写到沙箱目录(memory_scratchpad/creative_zone)和用户文档区(Desktop/Downloads/Documents),项目代码库等其他路径一律拒绝;其他工具默认禁用。还有 checkIntrusion 做入侵检测——防止 prompt injection 让自主 Agent 越权改代码。
这个 Guard 和第八章的 permission 审批是两套独立的安全机制:permission 管人机交互时的逐项审批(人点确认),Guard 管自主活动时的硬边界(机器自己挡)。自主重构时,Guard 保证 AI 只在授权目录里动代码,不会把系统文件或无关项目改坏。两套机制叠加:交互模式靠 permission、自主模式靠 Guard,覆盖两种工作形态。
6.9 记忆固化:自动沉淀编码偏好
记忆系统光能存能查还不够,还要能自己"学习"——把高频模式自动固化为长期规则,让 Agent 越用越懂这个项目。我们用 Dreaming 机制做记忆固化:闲置时扫描 L4 情景日志,识别重复出现的模式,固化为 L2/L3 长期记忆。
对编程场景最直接的价值:用户在今天的对话里三次纠正变量命名风格,Dreaming 识别出这个模式,自动生成一条 L2 规则"本项目变量名用驼峰",写入 L2。固化完成后原始 L4 日志标记可归档,释放热存储。后续所有编码任务都自动遵守这条规则,不用用户每次重申。同理,用户偏好的框架、错误处理风格、注释习惯,都会被自动沉淀。
配套的衰减(Decay)机制清理低价值、陈旧、低置信度的记忆——比如早期误固化的、后来被纠正的偏好。记忆不是越多越好,过时记忆会干扰检索,遗忘是必要的。容错设计:固化失败不中断整个周期,继续做衰减维护——固化是增益,失败不该阻断必要的清理。
这是从"有记忆"到"会学习"的跨越。编程智能体最大的体验差距就在这里——你是每次都要重申"用 tab 不用空格"“错误要 wrap”“注释用中文”,还是它用几次就自己记住了。
6.10 模型主动管理记忆
光靠后台固化不够,模型还需要主动读写记忆。我们提供 manage_core_memory 工具让模型主动往 L1-L4 写记忆——比如模型发现了一条重要的用户偏好,可以直接写入 L2 而不是等 Dreaming Engine 提取。manage_cognitive_state 工具让模型维护自己的认知状态(当前目标、情绪、意图),保持长任务的一致性。
这两个工具把"记忆"从被动存储变成主动资产——模型既能被动接收 Dreaming 固化的规则,也能主动记录即时发现。主动写入同样走 6.3 的治理合约(冲突检测、来源评估、证据链),保证模型自己写的记忆也合规。这是记忆系统的闭环。
第七章:多模型适配与扩展性工程
顶级编程智能体不能绑死一家模型。企业私有部署要接本地 vLLM、个人开发者想用 DeepSeek 省钱、前端团队偏好 Claude——这些诉求要求 Agent 内核模型无关。同时,技能和 MCP 协议让 Agent 能力可扩展,不靠官方更新。这一章讲三块扩展性工程:多模型 Provider 适配、Skills 技能系统、MCP Client 热重载。
7.1 多模型 Provider 统一抽象
我们做了一套 Provider 统一接口,支持 8+ provider:anthropic(Claude)、openai、azure(Azure OpenAI)、bedrock(AWS)、copilot(GitHub Copilot)、deepseek、gemini(Google)、local(本地 sensevoice/resource_search)。每个 provider 实现统一接口,Agent 内核不感知底层差异。
接口的核心是 Stream 方法——所有 provider 走流式响应,统一成 11 种事件类型:content_start/content_delta/content_stop(文本流)、tool_use_start/tool_use_delta/tool_use_stop(工具调用流)、thinking_delta(推理模型思考链)、usage(token 用量)、complete/error/warning。thinking_delta 是关键——它支持 Claude extended thinking 和 GPT o-series 这类推理模型的思考链流式输出,让 Agent 能看到模型的推理过程而不只是结论,这对调试和可观测性极有价值。
TokenUsage 结构统一追踪四类 token:InputTokens、OutputTokens、CacheCreationTokens、CacheReadTokens。KV cache 追踪在 provider 层就统一了,不管接哪个 provider 都能算 cache 命中率。UsageDelta 做增量计算时负值归零——防止 provider 偶发上报异常 token 数导致增量为负,这是个只有真实跑过多 provider 才会遇到的脏数据问题。maxRetries=5 处理 429/500/超时,重试在 provider 层而非 agent 层,让 agent loop 不感知网络抖动。
tool_schema.go 处理不同 provider 的工具调用格式差异——OpenAI 用 function calling、Anthropic 用 tool_use block、有的 provider 不支持工具调用要降级成纯文本解析。这层转换让 agent 内核用统一的工具调用抽象,不被 provider 差异污染。加新 provider 只需实现接口 + 写 schema 转换,不动 agent 内核。
7.2 本地模型与私有部署根基
local_sensevoice 和 local_resource_search 是两个本地 provider 适配——一个接本地语音/多模态模型,一个做本地资源检索。本地模型接法走标准 OpenAI 兼容 API(vLLM/Ollama 都暴露这个接口),所以核心逻辑复用 openai provider,但本地模型的特殊性(窗口小、无 cache、不支持工具调用时要降级)在 provider 层单独处理。
这是私有部署的根基:企业把 vLLM 部署在内网,Agent 通过 OpenAI 兼容 API 接入,代码不出域、模型权重在内网、token 成本自控。强绑云端模型的 Agent(如 Codex 绑 OpenAI、Claude Code 绑 Anthropic)做不到这点——它们的企业版走云厂商通道也只是改账单,模型权重仍在云端推理。模型无关不是噱头,是私有部署场景的硬约束。
7.3 Skills 技能系统:技能即工具
技能系统让 Agent 能力可扩展,不靠官方更新。Manager 扫描多个技能目录,每个技能是文件(YAML 或 Markdown 描述),解析成 SkillDefinition,注册成 SkillTool——技能即工具,模型可以像调内置工具一样调技能。
热加载是关键:StartWatching 监听技能目录变化,加新技能文件不用重启就生效。ToggleSkill 启用/禁用,GetDefaultActiveSkills 控制默认激活。LoadTool 按需加载——技能不全部驻留内存,用到才加载,避免技能数量爆炸拖垮 context。
解析层有两个 parser:通用 parser 解析标准格式,claude_parser 兼容 Claude 的 SKILL.md 格式——这意味着 Claude 生态的技能可以直接拿来用,不用重新编写。parser_fallback 做容错:某个技能解析失败不影响其他技能加载,失败的跳过、成功的继续。这个容错很重要——技能是用户/社区提供的,格式难免出错,一个坏技能不能拖垮整个技能系统。
技能和 MCP 工具的区别:技能是本地文件(脚本 + 描述),执行在 Agent 进程内,轻量、快;MCP 工具是外部 server(独立进程),通过协议调用,重、但要跨进程。技能适合轻量能力(数据处理、格式转换、自定义算法),MCP 适合重服务(数据库连接、外部 API 集成、长期运行的服务)。两者互补,覆盖从轻到重的扩展谱。
7.4 MCP Client 热重载
MCP(Model Context Protocol)让 Agent 连接外部服务。我们实现了 MCP Client,支持两种传输:stdio(MCP server 作为子进程,本地通信)和 SSE(MCP server 作为 HTTP 服务,可远程)。GetClient 建立连接、GetTools 拉工具列表、CloseAll 清理资源。
maybeReloadMCPConfig 是热重载机制——MCP 配置文件变化时不重启 Agent,重新加载 MCP server 连接。这让运维可以动态加/减 MCP server(接新的数据库、新的 API)而不中断 Agent 服务。企业环境里集成点是会变化的,热重载让 Agent 跟着业务变,不用停机。
MCP 工具和内置工具统一调度——GetTools 返回的 MCP 工具和内置工具一起注册进 agent 的工具列表,模型不区分两者。这是扩展性的关键:第三方能力通过 MCP 接入后,对模型来说是透明的新工具,不用改 agent 内核。一个 MCP server 暴露几十个工具时,配合 tool_search 做工具发现,避免把所有工具描述灌进 context。
7.5 扩展性的工程哲学
这三块放一起看,体现一条哲学:Agent 内核要稳、扩展面要宽。内核(loop/上下文/工具/LSP/认知)是打磨过的稳定层,不该频繁改;扩展面(provider/skills/mcp)是开放接口,让第三方能力接入不动内核。Provider 让模型可换、Skills 让能力可加、MCP 让服务可接——三者构成"模型无关 + 能力自扩展 + 服务可集成"的扩展三角。
很多编程智能体在这层做反了——内核频繁改(每加个能力改 loop)、扩展面封闭(只支持自家模型/自家插件)。结果是内核越来越乱、生态越来越窄。把内核做稳、扩展面做开,才是可持续的架构。
第八章:安全审批层
企业落地的生死线。审批层做得再好,一个绕过点就前功尽弃。这章讲我们的设计,包括我们自己的已知缺口—— upfront 说,不藏。
8.1 优先级链
审批是优先级链:环境变量全放行 → 配置全放行 → 只读白名单 → 会话自动审批 → 已授权记录 → 否则发布事件并阻塞等待用户确认。环境变量 AURAMATE_ALLOW_ALL_TOOLS=true 或配置 allowAllTools=true 任一为真,直接跳过所有审批。
而默认配置是 allowAllTools=true——默认就跳过审批。这是为开发体验做的默认值,但企业部署必须显式关掉。诚实地说,这是个容易踩的坑——默认宽松意味着开箱即用体验流畅,但生产部署不改配置就裸奔。
优先级链拆成表更清楚:
| 优先级 | 条件 | 动作 |
|---|---|---|
| 1 | 环境变量 AURAMATE_ALLOW_ALL_TOOLS=true |
直接放行所有 |
| 2 | 配置 allowAllTools=true |
直接放行所有(默认就是它) |
| 3 | 只读白名单(ls / cat / git status 等) | 放行 |
| 4 | 会话自动审批 | 放行当前会话 |
| 5 | 已授权记录 | 放行 |
| 6 | 都不满足 | 发布事件 + 阻塞等待用户确认 |
8.2 工具分级审批
工具层面,bash/write/edit/patch 都调了审批。但不同工具的审批粒度不同:bash 有只读白名单(ls/cat/git status 直接放行),edit 分四个拦截点(整文件替换/删除/编辑/恢复各自审批),patch 分三个(新增/更新/删除)。这种分级避免了"一刀切"——只读命令频繁调用不该卡体验,写操作破坏性强必须严审。
8.3 已知缺口:run_command 绕过
run_command 持有权限字段但不调用审批。理由前面讲过——长任务命令往往是模型自发触发的验证步骤,每次都审批会打断流畅性。代价是它成了审批绕过点。
这是个真实的安全缺口,我们选择暂不修复以保持长任务流畅,但企业版需要单独收紧(比如对 run_command 也加审批、或限制可执行命令白名单)。诚实承认缺口比假装它不存在重要——企业客户知道边界在哪,才能做自己的风险决策。
8.4 私有部署的安全前提
审批层之外,企业更关心的是数据出不出域。我们的设计是模型无关——可接本地 vLLM/Ollama,实现 100% 离线、代码真不出内网。这是金融、政企、军工、医疗场景的硬需求,这些场景的合规要求是代码不能出域推理,不是"不出域训练"。
这点上,强绑云端模型的 Agent 没法满足——它们代码必须发到云端推理,企业版走云厂商通道也只是改账单,模型权重仍在云端。真正的数据主权要求模型也在内网,这只有模型无关的本地 Agent 能做到。
第九章:子代理与并行
复杂任务需要并行——一个子任务跑测试、一个子任务查文档、一个子任务重构另一个模块。串行跑完要半小时,并行可能五分钟。但并行引入新问题:context 怎么隔离、并发怎么控制。
9.1 delegate 与 context 隔离
delegate 和 batch_delegate 工具委派子任务给子代理。子代理有独立的 context window,跑完只把摘要返回主代理,中间过程不占主 context——这是上下文隔离的关键机制。
为什么必须隔离?如果子代理的中间过程(几十次工具调用、几万 token 的工具输出)都灌进主 context,主代理的 context 会立刻爆炸。隔离后,主代理只看到"子代理完成了 X 任务,结果是 Y",几十次调用的噪音被压缩成一句话。这是用并行换 context 效率——既加速又省 token。
9.2 无硬并发上限的取舍
batch_delegate 支持并发委派多个子代理。按照我们的设计约束,子代理并行没有硬性数量上限——这是有意为之,让复杂任务能尽可能并行加速。
代价是缺少全局并发限流,极端情况下可能资源爆炸。这是个"信任调度者自律"的取舍——我们假设上层会合理控制委派数量,框架不做硬限制。如果担心爆炸,可以在上层加信号量或 worker pool 限流,但框架层留灵活性。
9.3 按角色限制工具集
子代理的工具集也按角色限制。编码子代理拿完整 LSP 工具集,非编码子代理拿精简集。这和主代理的按角色分配逻辑一致——最小权限原则,降低误操作风险。
9.4 三种隔离范式
子代理隔离有不同范式。我们用的是 context window 隔离(共享进程);其他系统有工作目录隔离(worktree,每个子代理在独立 git worktree 操作,文件级隔离)和完整执行上下文隔离(独立 token 预算、独立进程)。隔离越细,并行越安全但开销越大。
context 隔离对我们够用——我们的目标是私有部署的单机场景,进程内并发足够轻量。如果是多机分布式场景,worktree 或独立进程隔离更合适。隔离粒度要匹配部署场景,没有绝对最优。
第十章:结语 —— 模型会被追平,工程内核不会
拆完这九个工程内核,一个结论反复浮现:编程智能体的天花板由模型能力决定,但地板由工程内核决定。
模型再强,没有防死循环的 loop 会在第 30 步转圈、没有上下文压缩会在第 50 步丢约束、没有 LSP 集成只能做 grep 级修改、没有幻觉护栏会被弱模型的空声称坑、没有记忆系统永远是金鱼记忆、不会自动沉淀偏好就不会越用越聪明。工程内核是地板,决定了 Agent 能不能稳定跑而不崩。
而这九个工程内核的复杂度,都遵循同一个规律:工程复杂度是模型能力的补偿函数。模型越强、窗口越大,工程层可以越薄;模型越弱、窗口越小,工程层必须越精细。四阈值压缩是为小窗口场景打磨的——接 1M 窗口的云端模型根本不需要这么精细;回执式幻觉检测是为弱模型准备的——接最强云端模型可以省掉这层靠模型自觉;认知管线并行是为慢模型设计的——接快模型串行也够快;四路搜索融合 + CJK 跨语言是为小模型 embedding 质量不稳定准备的——接最强 embedding 模型单路向量就够;记忆治理合约 + 自动沉淀是为长周期项目准备的——一次性任务用完即走不需要沉淀偏好。
所以造编程智能体的第一性问题不是"用什么模型",而是"目标场景的模型多弱、窗口多小、合规多严、任务多长"。这几个约束决定了工程内核该厚还是该薄。厚薄没有优劣,匹配才是关键。
为最强云端模型造 Agent,工程可以很薄——模型自己能兜底。为本地小模型、私有部署、十万行代码库造 Agent,工程必须厚——四阈值压缩、回执式幻觉检测、LSP 生产级集成、四路搜索融合的记忆治理合约、会自动沉淀偏好的记忆固化、工具链分级审批,每一层都是为补偿模型能力不足而存在。这不是过度工程,是场景适配。
造编程智能体的竞争,表层是模型能力的竞争,底层是工程内核的竞争。模型能力会被开源追平,工程内核的积累不会被轻易追平——那是十几万行代码和无数次生产故障打磨出来的。看一个编程智能体的成色,看它的 loop 怎么防死循环、上下文怎么压缩、工具怎么校验、LSP 怎么集成、记忆怎么治理、会不会自动学习,比看它的 demo 视频靠谱得多。
AuraMate 想做的不是又一个套壳的编码助手,而是一套能跑在本地小模型上、能进企业内网、能在十万行代码库里稳定作业的编程智能体基础设施。模型会迭代、会被开源追平,但 loop 防死循环的工程直觉、上下文压缩的阈值拿捏、LSP 集成的踩坑修复、记忆治理的合约设计——这些工程内核的积累,才是真正的壁垒。
这条路很长,九个工程内核之外还有太多没讲透的细节:会话持久化与断点恢复、prompt 工程的 write budget、浏览器与视觉工具的集成、定时任务调度。每一项都是一篇长文。我们边走边写。
如果你也在造编程智能体,欢迎来社区交流工程细节——loop 怎么调、阈值怎么定、LSP 怎么接,这些踩坑经验对齐了才有意义。
如果你在企业里被"代码不能出域"卡着,欢迎试试 AuraMate 的私有部署,看模型无关 + 本地 LSP + 记忆系统能不能填上 Cursor、Codex、Claude Code 留下的空白。
项目地址与资源:
官网下载: https://auramate.cn
开发者文档: https://auramate.cn/community
————————————————
版权声明:本文为CSDN博主「xsdick」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
更多推荐



所有评论(0)