Posts for: #Agent

opencode memory 实现与最佳实践

注:文章由 codex 整理。

背景

这里的 memory 不是操作系统内存,也不是模型推理时的 KV cache,而是 coding agent 在多轮、多 session、多项目之间保存和复用上下文的能力。

截至这次分析的源码快照,opencode 并没有内置一个类似 mem0mnemopi 或向量数据库的长期记忆系统。它的 memory 更接近三层组合:

  1. 规则型长期记忆AGENTS.md、全局 AGENTS.mdopencode.json 里的 instructions。这些内容每轮都会进入 system prompt,是最稳定、最可审计的记忆。
  2. 会话内压缩记忆compaction agent 把长会话压缩成摘要,并保留最近若干 turn,让当前 session 可以继续推进。
  3. 上下文型临时记忆:用户用 @file、MCP resource、skill、subagent 等方式临时补充上下文,主要服务当前任务。

所以分析 opencode memory 时,关键不是找一个 MemoryBackend,而是看它如何把规则文件、配置、压缩摘要和临时上下文组装进模型请求。

本文基于:

核心结论

opencode 的 memory 设计偏“显式上下文工程(context engineering)”,而不是“自动记住一切”。

这带来一个很重要的实践判断:应该把长期稳定的项目知识写进规则文件,把当前任务过程交给 session history 和 compaction,把低置信度、临时性、可能过期的信息留在对话里,而不是沉淀到 AGENTS.md。

可以这样理解:

层次 opencode 机制 适合保存什么 不适合保存什么
长期项目记忆 项目 AGENTS.md 架构边界、测试命令、代码风格、危险操作约束 临时任务进度、一次性 debug 现象
长期个人记忆 ~/.config/opencode/AGENTS.md 个人偏好、默认工作方式、输出习惯 某个项目的私有约定
可复用规则片段 opencode.jsoninstructions 多文件规范、共享团队标准、monorepo 分包规则 需要模型自己递归解析的隐式引用
会话内记忆 compaction 当前 session 的目标、决策、已完成动作、未解决问题 跨 session 的长期知识
临时上下文 @file、MCP、skills、subagents 本轮要读的文件、外部资料、专项流程 需要每次都遵守的硬规则

实现总览

一轮模型调用前,SessionPrompt 会把几类 system prompt 片段拼起来:

Loop Engineering 最佳实践

背景

注:文章由 codex 整理。

Loop engineering 讨论的不是普通代码里的 for/while,也不是 agent harness 内部已经存在的 observe -> act -> observe 工具调用循环,而是人类交给 agent harness 的外部循环规格(loop specification)

arXiv 论文 Stop Hand-Holding Your Coding Agent: Engineering the Loops that Replace Step-by-Step Prompting 给出的核心定义是:loop specification 是一个有边界、可复用的 artifact,包含 triggergoalverificationstopping rulememory,由人类交给 Claude Code、Codex 等 agent harness,让 agent 在无需人类逐步提示的情况下追踪目标、执行、检查并停止。

这篇论文的价值在于把社区里比较口号化的说法收束成一个工程问题:

  • prompt engineering 问的是:这一轮怎么问?
  • context engineering 问的是:agent 应该知道什么?
  • harness engineering 问的是:agent 能在什么环境里行动?
  • loop engineering 问的是:如何设计一个系统,让 agent 能发现工作、执行工作、验证结果、记录状态,并知道什么时候停?

所以它不是“prompt engineering 已死”,而是 prompt 之外多了一层控制系统。一个 loop 的底层仍然会使用 prompt,但关键杠杆从“写一句更聪明的话”变成“设计一个带反馈、验证和刹车的闭环”。

oh-my-pi memory 系统实现分析

注:文章由 codex 整理。

背景

oh-my-pi 的 memory 系统不是一个单一模块,而是一层 MemoryBackend 抽象下面挂了几种不同的实现。它要解决的问题是:Agent 的上下文窗口是短期的,但用户偏好、项目约定、设计决策、踩坑经验应该跨 session 保留下来,并能在未来对话中重新进入模型上下文。

从实现上看,oh-my-pi 把 memory 拆成三个问题:

  1. 记忆写到哪里:本地 Markdown 摘要、本地 SQLite、还是远端 Hindsight 服务。
  2. 什么时候写入:工具显式 retain,还是每 N 轮自动保留 transcript。
  3. 什么时候读出:启动时注入摘要,首轮 prompt 前自动 recall,或者由模型主动调用 recall / reflect

总体架构

memory backend 的公共接口定义在:

packages/coding-agent/src/memory-backend/types.ts
packages/coding-agent/src/memory-backend/resolve.ts

resolveMemoryBackend(settings) 根据 memory.backend 选择具体实现:

memory.backend = off        -> offBackend
memory.backend = local      -> localBackend
memory.backend = hindsight  -> hindsightBackend
memory.backend = mnemopi    -> mnemopiBackend

MemoryBackend 的关键 hook 是:

  • start():session 启动时建立运行时状态、订阅 session event。
  • buildDeveloperInstructions():构造要注入系统提示词的 memory 文本。
  • beforeAgentStartPrompt():在当前 turn 生成前追加一次性 recall 结果,保证首轮就能吃到记忆。
  • enqueue():强制触发 retain / consolidation。
  • clear():清理当前 backend 的持久化状态。
  • status() / search() / save() / stats() / diagnose():给 UI、slash command、extension 使用。

三种真实 backend 的定位不同:

Claude Code auto-mode 实现分析

注:文章由 codex 整理。

背景

本文分析的是 chengzhycn/claude-code 在提交 4b9d30f7953273e567a18eb819f4eddd45fcc877 上的源码实现。

源码入口:

  • 仓库:https://github.com/chengzhycn/claude-code/tree/4b9d30f7953273e567a18eb819f4eddd45fcc877
  • 权限模式定义:src/utils/permissions/PermissionMode.ts
  • auto-mode 状态切换:src/utils/permissions/permissionSetup.ts
  • 工具权限主流程:src/utils/permissions/permissions.ts
  • auto-mode classifier:src/utils/permissions/yoloClassifier.ts
  • Bash 权限判定:src/tools/BashTool/bashPermissions.ts
  • Bash 只读命令判定:src/tools/BashTool/readOnlyValidation.ts
  • Bash 注入/语法安全检查:src/tools/BashTool/bashSecurity.ts

核心问题是:Claude Code 怎么在“不每一步都问用户”和“不直接 bypass permissions”之间做折中。源码里的 auto-mode 不是一个简单的全局 allow,而是一套组合机制:

  1. 进入 auto-mode 时先检查 feature gate 和 opt-in。
  2. 临时剥离会绕过 classifier 的危险 allow rule。
  3. 工具调用先走原有本地权限系统。
  4. 对本地系统仍然需要 ask 的动作,再交给 auto-mode classifier 判断 allow/block。
  5. classifier 不可用、输出不可解析或 transcript 太长时,按场景 fail closed 或回退到人工 permission prompt。

模型

auto-mode 可以理解成一个“permission prompt 的自动代理”,而不是新的沙箱。它的安全性来自三层:

工具自己的权限检查
  -> 本地静态安全规则:路径、只读命令、deny/ask/allow rule、shell 注入模式
  -> auto-mode 快速路径:acceptEdits 可允许的操作、安全工具 allowlist
  -> auto-mode classifier:读取 transcript + 当前 action,输出 allow/block

这意味着:

常见的大模型 OpenAPI 规范

AI Gateway 的对接开发中,一个重要的内容就是对接不同厂商推理服务的接口协议。目前,推理服务的接口协议主要分为以下几种类型:

  • 文本对话接口,如 OpenAI 的 chat completions 和 response API 等
  • 向量接口,向量接口用于将输入的文本或者图片、视频(多模态)等转换成向量表示,适用于搜索(文搜图、图搜图、图文混合搜索)、聚类、推荐等场景。

文本对话

文本对话 API 需要提供如下能力支持:

  1. 模型选择
  2. 用户、系统、模型输入内容角色区分
  3. 模型参数调整
  4. 工具调用
  5. MCP 支持
  6. 用量统计

目前使用最广泛的文本对话接口自然是 OpenAI 的 chat completions API。几乎所有的 LLM 服务提供商都支持 chat completions compatible 调用。

https://platform.openai.com/docs/api-reference/introduction

chat completions

基本调用:

curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-5",
    "messages": [
      {
        "role": "developer",
        "content": "You are a helpful assistant."
      },
      {
        "role": "user",
        "content": "Hello!"
      }
    ]
  }'
  • model: 请求调用的模型
  • messages:构成对话的消息体。根据消息的来源角色,message 可以分为 developer/system(开发者,系统提供的 prompt),user(用户自身的输入)和 assistant(模型的响应,用于多轮对话时模型的上下文传递)。
    • content 分为两种类型,纯文本即为 string,非纯文本 content 为列表类型,内容根据 type(text,image_url,input_audio 等)有不同的字段
  • stream:采用正常 HTTP 响应还是 sse 响应
  • stream_options: 在 sse 响应时,有些模型默认不会输出 usage 信息,需要显式将 stream_options.include_usage 设置成 true
  • temperature:模型温度,取值范围 0 - 2,值越高,输出的 tokens 随机性越大
  • top_p:和 tempreature 一样对模型输出进行调整的参数,模型会考虑概率质量最高的top_p个tokens的结果。所以0.1意味着只考虑概率质量最高的10%的tokens。
  • reasoning_effort:模型的推理深度,比如对于 OpenAI 模型来说有 minimal,low,medium,high 等多种选择。
  • max_completion_tokens:最大输出 tokens 数,包括 output tokens 和 reasoning tokens。替代原来的 max_tokens 字段。
  • tools:告知大模型本地可调用的工具列表。工具里面定义了工具的名称、描述和 json schema 表示的参数描述。替代原来的 functions 字段。
  • tool_choice:告知模型对于工具的调用选择。none 表示不要调用任何工具直接生成 messages,auto 表示由模型自己决定是否调用 allowed_tools。required 表示模型必须调用至少一个工具。

除此之外,各家可以在 OpenAI 标准的 API 上扩展自己的字段,比如 cherry studio 会使用 thinking 字段来开启/关闭模型思考: