Skip to main content
对话与会话

记忆

用原生记忆让 Agent 跨轮次、跨会话延续知识,或由应用接管记忆的生成与消费。

记忆让 Agent 把一次会话中获得的知识保留下来,供后续会话使用。项目的构建命令、测试目录结构、代码约定这类信息,无需在每次会话中重新探索。 Qoder Agent SDK 的记忆由生成与消费两部分组成,可分别配置:
组成作用何时运行
生成(Generation)将 Agent 获得的知识写入记忆文件一轮结束后,由后台记忆 Agent 执行
消费(Consumption)将记忆文件加载进 Agent 的上下文会话初始化时,以及显式刷新时
语言可用性:仅 TypeScript。memory 选项以及 flushMemory() / refreshMemory() 运行时方法仅存在于 TypeScript SDK。Python SDK 未提供对应选项,因此 Python 应用无法配置 SDK 记忆、选择作用域,也无法接收生成与消费结果。本页内容仅适用于 TypeScript。

启用原生记忆

mode: 'native' 将全部行为交由运行时的默认策略处理,建议作为起点使用:由运行时判断哪些内容值得记录、存放在何处、何时加载。
import { query } from '@qoder-ai/qoder-agent-sdk';

for await (const message of query({
  prompt: '增加一个健康检查接口,并跑一遍测试',
  options: {
    memory: { mode: 'native' },
  },
})) {
  console.log(message);
}
native 模式下可配置的仅有两个作用域开关和结果回调。存储位置、生成提示词、加载预算等由运行时掌握,并随版本持续优化。

选择记忆作用域

原生记忆有两个作用域,默认均启用。
作用域根目录 id存放内容
用户级user跟随使用者、跨项目通用的知识
项目级project仅属于当前工作目录的知识
可在单次 Query 中关闭其中一个:
// 仅使用项目级知识,不读写用户级记忆
options: {
  memory: { mode: 'native', userScope: false },
}
native 模式要求至少启用一个作用域,同时关闭两个会抛出异常:
native mode requires at least one enabled scope; use memory: {} to disable SDK memory

关闭记忆

空对象是显式的关闭开关,等同于不传 memory,不会向运行时下发任何记忆配置。
options: {
  memory: {},
}

覆盖生成与消费

mode: 'custom' 仅覆盖显式给出的部分,其余沿用运行时默认行为。当记忆的存放位置或记录标准需要由应用决定时,使用该模式。

控制写入什么

options: {
  memory: {
    mode: 'custom',
    generation: {
      roots: [
        { id: 'team', path: '/srv/knowledge/team', access: 'read' },
        { id: 'service', path: '/srv/knowledge/checkout', indexFile: 'INDEX.md' },
      ],
      prompt: '只记录部署步骤与故障特征。',
    },
  },
}
每个 root 对应一个记忆 Agent 可访问的目录:
字段类型默认值说明
idstring稳定标识,用于提示词、初始化和生成结果
pathstring运行 Qoder CLI 的机器上的目录路径
access'read' | 'read-write''read-write'记忆 Agent 是否可写入该 root
indexFilestringroot 内的相对索引路径。若所有文件均为内容文件则省略

按轮决定是否写入

生成默认在每轮结束后触发。通过 shouldGenerate,应用可以否决单次生成,例如跳过无价值的轮次、按租户控制预算,或在只读评审场景中不写入记忆。
options: {
  memory: {
    mode: 'custom',
    generation: {
      turnComplete: {
        shouldGenerate: async (input, { signal }) => {
          if (input.prompt.length < 40) {
            return { run: false, reason: '提示词过短,不值得记录' };
          }
          return { run: true };
        },
        timeoutMs: 5_000,
        onGateError: 'skip',
      },
    },
  },
}
回调接收本轮的 promptresponse,以及 sessionIdcwd 和从 1 开始的 turnIndex。返回 run: false 时不启动后台 Agent,改为产生一条 skipped 结果。
字段类型默认值说明
enabledbooleantrue是否启用轮次结束生成
shouldGenerate回调应用侧闸门。省略时仅使用运行时内置的保护规则
timeoutMsnumber10000闸门回调的最长耗时
onGateError'skip' | 'report_failed''skip'回调报错或超时的上报方式

控制加载什么

显式传入 files 会在本次 Query 中替换原生自动记忆,静态指令仍照常加载。
options: {
  memory: {
    mode: 'custom',
    consumption: {
      files: [
        { id: 'conventions', path: '/srv/knowledge/CONVENTIONS.md', required: true },
        { id: 'runbook', path: '/srv/knowledge/RUNBOOK.md' },
      ],
      maxTokens: 4_000,
      overflow: 'truncate',
      failureMode: 'fail_query',
    },
  },
}
文件按数组顺序注入,id 作为注入内容的小节名。
字段类型默认值说明
enabledbooleantrue是否加载记忆
filesMemoryConsumptionFile[]显式文件列表,会替换原生自动记忆
maxTokensnumber所有显式文件共享的 token 预算
overflow'truncate' | 'fail_query''truncate'内容超出 maxTokens 时的处理方式
failureMode'best_effort' | 'fail_query''best_effort'读取失败时的处理方式。仅标记 required 的文件会导致 Query 失败

查看记忆的执行结果

记忆在后台运行,其结果应显式暴露给应用,不宜默认成功。有两种获取方式。 一是注册回调,nativecustom 模式均支持:
options: {
  memory: {
    mode: 'native',
    generation: {
      onResult: (result) => {
        console.log(`[memory] ${result.status},耗时 ${result.durationMs}ms`);
        for (const file of result.writtenFiles) {
          console.log(`  已写入 ${file.rootId}:${file.path}`);
        }
      },
    },
    consumption: {
      onResult: (result) => {
        for (const file of result.files) {
          console.log(`  已加载 ${file.id}: ${file.status}`);
        }
      },
    },
  },
}
二是从消息流中读取,对应 subtype 为 memory_generationmemory_consumptionsystem 消息:
for await (const message of q) {
  if (message.type === 'system' && message.subtype === 'memory_generation') {
    console.log(message.result.status);
  }
}
生成会上报以下五种结果之一:
状态含义
saved所有待写文件均写入成功
partial至少一个文件写入成功、一个失败,需检查 failedFiles
no_change已执行,但未发现需要记录的新内容
skipped未执行,例如闸门返回了 run: false
failed已执行,但没有任何文件写入成功
消费会上报 successpartialfailed,并给出每个文件的状态:loadedmissingfailedtruncatedmissing 不属于错误,首次运行时记忆文件可能尚未创建。

在运行时控制记忆

查询对象提供两个方法,用于处理后台生成带来的时序问题。
const q = query({ prompt: userMessages(), options: { memory: { mode: 'native' } } });

// 退出进程或校验文件内容前,等待未完成的轮次生成结束
await q.flushMemory();

// 外部进程修改记忆文件后,重新加载
await q.refreshMemory();
flushMemory() 在 CI 和测试场景中尤为重要:若进程在收到最终 result 消息后立即退出,可能中断正在进行的写入。

校验实际生效的配置

记忆选项需与运行时协商确定,因此应读回实际生效的配置,而非依赖传入值:
const init = await q.initializationResult();
console.log(init.memory);
// {
//   enabled: true,
//   requester: 'sdk',
//   mode: 'native',
//   generationEnabled: true,
//   turnCompleteEnabled: true,
//   consumptionEnabled: true,
//   roots: [{ id: 'user', access: 'read-write' }, { id: 'project', access: 'read-write' }]
// }
memory 省略或设为 {} 时,init.memoryundefined

下一步