我的工作流

graph TB A["Agent"] --> U["Utility.app"] U --> M["本地 MCP 服务"] U --> P["Proxy 网关"] U --> G["依赖图"] U --> K["知识面板"] M --> D1["记忆体"] M --> D6["内置 Tools"] P --> D8["动态提示词注入"] P --> D9["Token 分析治理"] K --> D4["知识池"]

为了保证留存率,我会先问你几个问题,在使用 Agent 的过程中:

  • 是否遇到过跨会话上下文丢失、前后理解不一致?
  • 希望 Agent 记住对话中产生的记忆、内容?
  • 是否遇到过长上下文污染?越长的会话,模型遵从率、智能程度越低?
  • Agent 在开发过程中,是否需要经常检索项目,对项目缺少全局视野?
  • Agent 与上游 LLM 之间是否是黑盒系统,较难感知内部?Token 消耗未知,无法针对性治理?
  • Agent 使用多了,是否觉得探索知识的欲望、主动阅读文章、源码的意愿更低了?

如果有遇到过这些问题,可以看看我是怎么搭建自己的工作流的。

另外说下,我使用的工具是:Claude Code + Utility.app 接入 LLM API。

Utility.app 是我自用的一个核心工具。

记忆体,跨上下文理解的基石

当使用多个 Agent 时、当跨会话开发时、当会话内产生知识时,你会想到需要什么?

我的回答是:共享记忆体 。我们需要一个能够记录工作进度、对话知识的记忆体,所有消费层使用同一个记忆体,就像人脑一样,不管做什么总是从一个记忆体出发,形成行为的一致性。

那么对于 Agent 来说,记忆体的最佳形态是什么?

本地 MCP 服务 ,MCP 协议被设计为可拔插的,可以随意接入任何支持了 MCP 协议的 Agent,供它们消费。

拥有了这两样东西,我们可以解决两件事:

  1. 上下文保留、理解一致
  2. 知识的存储

这还只是明面上的价值,在背后,我们可以思考、分析这些记忆,我们可以提炼记忆进行沉淀,产出更优质的内容;也可以从记忆中生成报告等等。

落到实际,则表现为三层存储记忆架构:

graph TB A[&#34;Agent&#34;] -->|&#34;tools/call&#34;| M[&#34;MCP 服务&#34;] M -->|&#34;结果&#34;| A M --> R[&#34;recall&#34;] M --> W[&#34;remember&#34;] subgraph MEM[&#34;三层记忆&#34;] H[&#34;热层<br/>会话记忆&#34;] C[&#34;冷层<br/>长期知识&#34;] N[&#34;Markdown 笔记&#34;] end W --> H R --> H R --> C R --> N

热层保留温热的、新的记忆;冷层保留长期有用的记忆;最终沉淀到笔记层,目的是永久存储与方便人工阅读。

remember / recall 是本地 MCP 服务内置的两个工具,用于记忆的写入与检索,Agent 通过调用这两个工具来操作记忆。

Proxy 网关,扩展的关键

记忆体 解决了跨会话理解、多 Agent 共享记忆的问题,我们现在聚焦到长上下文污染 与黑盒系统的问题。

黑盒系统破局需要 Proxy 网关很好理解,在 Agent 与上游 LLM 厂商插入一层代理层,就可以使黑盒系统透明,那么长上下文污染为什么会需要代理层呢?

我们知道,在长对话中,初始的系统提示词、规则、或者是工具描述,非常容易被后续的上下文污染,导致模型的注意力更关注最新内容,而忽略了系统提示词、规则、工具描述,造成的后果可能是:

  • 行为漂移
  • 遵从率下降
  • 工具调用意愿下降
  • 智能降低

这种时候一般做法是新开会话,我认为这很麻烦,所以我找到了另一个方式:动态提示词注入。

graph TB A[&#34;Agent&#34;] -->|&#34;请求&#34;| P[&#34;Proxy 网关&#34;] S[&#34;提示词&#34;] -->|&#34;读取规则&#34;| P P -->|&#34;注入提示词&#34;| B[&#34;每条真实 user 消息&#34;] B -->|&#34;转发&#34;| U[&#34;上游 LLM&#34;] U -->|&#34;响应&#34;| P P -->|&#34;响应&#34;| A

它的工作原理很简单,既然 LLM 对于旧的消息注意力下降,那就将核心的提示词注入到每条最新的用户消息中,使其具有最高优先级。

为什么是注入到用户消息中呢?而不是到系统提示词位置?这个决策来自长久的观察,在使用 DeepSeek 这种较智能的 LLM 时,注入不缓存的系统提示词通常不会有太大的问题,但对于像 小米 mimo 这种智能程度较低的 LLM 来说,它更愿意遵守最新的用户消息。

这种方式的效果非常好,但代价也很明显,由于每轮用户消息都注入同样的内容,会增加 Token 消耗 ,所以一般动态注入的提示词偏向轻量、核心、全局可用 ,对于项目生效的提示词而言,更适合用 AGENT.md/CLAUDE.md。

Token 分析治理,省钱必做的一步

代理还有一个核心的价值是黑盒系统可观测了,我们可以记录每个请求的输入输出、模型的请求成功率、延迟、缓存率,这些指标具有很高的价值,我们可以根据这些内容来分析、量化 Token,并据此进行针对性的治理。

在漫长的治理过程中,我发现核心的就几点:

  • 提高缓存率
  • 不破坏缓存
  • 减少输入

不破坏缓存 是一个很重要的前提,代理层能够在请求转发到上游前操作消息,一般能想到的做法是在转发前压缩、裁剪、剔除消息,以期达到减少 Token 输入的目的,这种做法是不完全正确的,因为这会破坏缓存,使每条断了缓存的消息都以非缓存的价格计费。

在进行 Token 治理时,应该从成本的维度去分析,而不是 Token 输入的多少。

也就是说,当大量缓存输入的成本超过因裁剪破坏缓存的成本时,是可以考虑裁剪历史消息的。

减少输入就很好理解了,Agent 在使用过程中通常会进行多次工具调用,这些工具会产生大量的Token 输入,有些可能只使用一次,却在后续的每次对话中都携带,即使以缓存价格计算,但数量暴增时也会导致成本的增加。

所以我们需要针对工具输出内容进行瘦身,比如 Bash 只看是否有 warning/error。

我做的 Token 治理有:

  • 减少重复内容:同一会话反复获取到同一份工具输出内容时,第二份起替换成一句短提示,保留第一次的全文。
  • 裁剪 shell 输出:超长命令输出保留前 70% 和后 30%,中间插入截断标记;JSON 做无损压缩。
  • 注入保证幂等性:前置注入保证幂等性,不破坏缓存
  • 工具限流:减少内置工具的默认响应
graph TB A[&#34;Agent&#34;] A -->|&#34;模型请求&#34;| P[&#34;Proxy 网关&#34;] P --> Q[&#34;请求侧治理<br/>规则注入 · 内容去重 · Shell 瘦身&#34;] Q --> U[&#34;上游 Provider&#34;] U --> R[&#34;响应侧治理<br/>Usage 记录 · 响应注记 · 上下文提示&#34;] R --> D[&#34;用量库&#34;] R --> A A -->|&#34;工具调用&#34;| M[&#34;MCP 服务&#34;] M --> L[&#34;工具返回限流&#34;] L --> A

依赖图,全局感知视野

使用过 Claude Code 这类 Agent 开发项目的应该都有一个感受,缺乏全局视野的感知能力,可能这次实现了一个组件、工具,下次有相同需求时就忘了,并重复实现;或者经常需要全局查找某个组件、工具。

这是因为缺失全局视野能力 的原因,或者说是整个项目的依赖图。

针对这个痛点,我给 Utility.app 加了一个扫描依赖图的功能,表现为 cli 命令:

sh 复制代码
utility -a "agent"
# eg. utility -a claude

它做了这样几件事,启动扫描器,扫描项目符号,生成依赖图,并存储到 .utility/deps.sqlite 库中,然后启动 Agent,进行 Agent 终端,控制权回到 Agent,而 Utility.app 则在后台侦听文件变化并更新依赖图。

然后 Agent 可以通过本地 MCP 服务暴露的 project_search / project_structure / project_exports / project_packages 工具查询。

graph TB A[&#34;Agent&#34;] --> Q[&#34;查询层<br/>project_search · project_structure<br/>project_exports · project_packages&#34;] Q --> DB[&#34;.utility/deps.sqlite<br/>目录 · 文件 · 符号 · 包 · FTS&#34;] S[&#34;ProjectScanner<br/>全量扫描&#34;] --> E[&#34;符号提取&#34;] W[&#34;FileWatcher<br/>增量扫描&#34;] --> E E --> AST[&#34;AST 脚本<br/>Python · Babel&#34;] E --> RE[&#34;正则提取器<br/>Swift · JS · TS · Vue · Java · Kotlin&#34;] AST --> DB RE --> DB

知识面板,主动推送新鲜知识

这是关于个人成长的问题,我想解决它,问题的关键在于,Agent 用多了,主动阅读、探索新知识的意愿变低,我希望有一个主动弹出的面板,能展示一些我从未见过,或者说感兴趣的内容,能够让我花点时间去阅读。

为什么是从未见过的内容呢?我们知道,我们有一个记忆体,里面存了一些知识,为什么不能从里面提取一些内容来展示呢?

问题的关键在于,记忆体中的内容都是对话中产生的,这些内容已经在我们脑海中了,再次看到它不能让我们的大脑感到兴奋。所以我们需要一点未知的、感兴趣的新内容。

它的运作方式是这样的,我们会配置一些感兴趣的主题,然后大模型会去爬取有关主题的内容,当时间间隔到时,它会抽取一条知识显示在知识面板上。

graph TB U[&#34;用户&#34;] --> P[&#34;知识面板<br/>主题卡片 · 碎片&#34;] subgraph REFILL[&#34;后台补货&#34;] T[&#34;定时器&#34;] -->|&#34;池未满时补货&#34;| E[&#34;知识引擎&#34;] W[&#34;Web 检索&#34;] --> E E --> L[&#34;LLM 生成&#34;] L --> C[&#34;自检&#34;] end C -->|&#34;写卡&#34;| DB[&#34;知识池&#34;] DB -->|&#34;读取&#34;| P

这些核心能力在我的 Utility.app 中,我把它开源在:yuanyxh/utility

相关推荐
badhope1 小时前
AI Agent安全治理实战:从API密钥泄露到沙箱隔离的完整防线
后端·llm·agent
武子康1 小时前
旧工具结果写进新回合:两次消费之间的打断窗口
人工智能·后端·agent
许雪里2 小时前
Agent 记忆架构设计:原理 × 业界三大范式 × XXL-AI 落地实践
后端·llm·agent
hpoenixf2 小时前
如何给投研 Agent 配上 Subagent:从上下文隔离到专业化协作
agent
墨心@3 小时前
图片归一化
agent·pi·coding agent·harness
skywalk81633 小时前
FreeBSD系统在Deepseek-harness中配置使用其它几家的模型,比如hy3 hunyuan-2 glm5.3-flash等
人工智能·freebsd·deepseek·harness
墨心@5 小时前
Pi 项目分析
agent·coding agent
ZzT5 小时前
context-mode 拆解:98% 是怎么算出来的,装进 Claude Code 实际省多少
ai编程·claude
用户3134672143546 小时前
learn-claude-code笔记3: Permission — 执行前做权限判断
llm·agent