长记忆使用Hooks对接Qoder
概述
AnalyticDB for PostgreSQL长记忆Hooks是AnalyticDB for PostgreSQL提供的会话生命周期钩子集成方案,为Qoder AI编程助手提供无感知的跨会话持久记忆能力。
Qoder Hooks是Qoder提供的会话生命周期钩子机制。当用户在Qoder中进行特定操作(发送消息、AI调用工具、退出会话)时,Qoder会自动执行用户预先注册的脚本,在会话的关键节点插入自定义逻辑。
每个Hook通过stdin接收Qoder传入的JSON输入(包含会话ID、工作目录、用户消息等信息),通过stdout返回JSON输出来影响Qoder的行为(如注入上下文、阻止危险操作)。
工作原理
AnalyticDB for PostgreSQL长记忆通过httpx(Python异步HTTP客户端库)直接调用长记忆服务 REST API,不依赖MCP Server,工作流程如下:
安装Hook脚本:通过
pip install安装Python包,注册3个Hook CLI入口。注册到Qoder:通过
adbpgmem-install-hooks命令将Hook脚本写入~/.qoder/settings.json。自动触发:Qoder在用户提交消息、工具调用前、会话结束等时机自动执行对应Hook脚本。
API调用:Hook脚本通过httpx调用AnalyticDB for PostgreSQL长记忆 REST API完成记忆的搜索和保存。
所有操作在后台静默执行,不影响Qoder的正常使用。配置修改后立即生效,无需重启。
三个Hook
Hook名称 | 触发事件 | 功能 | 一句话定位 |
| UserPromptSubmit | 首条prompt时双查询搜索历史记忆,注入additionalContext | 会话首次交互时自动加载相关知识 |
| Stop | 提取会话摘要并保存到记忆库 | 会话结束时自动保存新知识 |
| PreToolUse | 阻止写入MEMORY.md等本地记忆文件 | 守护本地文件,重定向到MCP工具 |
与Claude Code的差异:Qoder自1.106.x版本起已停止触发SessionStart事件,且从未支持PreCompact事件。因此Qoder仅注册3个Hook,记忆上下文注入改用UserPromptSubmit事件(首条prompt触发 + 会话级节流)。
所有Hook在长记忆服务不可用时Qoder正常工作,不会因Hook失败而中断会话。
适用场景
适合使用Hooks集成的场景:
无感知记忆管理:您希望记忆在后台自动加载和保存,不需要手动操作。
会话启动自动加载:每次开启新会话时,首条消息自动注入历史架构决策和编码偏好。
会话结束自动保存:退出会话时自动提取并保存本次会话的有价值知识。
防止本地文件分散:阻止Qoder AI将记忆写入MEMORY.md等本地文件,集中管理到AnalyticDB for PostgreSQL长记忆服务。
安装Hooks
前置要求
Qoder IDE或Qoder CLI已安装并可正常使用。
Python >= 3.10。
已获取AnalyticDB for PostgreSQL长记忆服务的API地址和Token。
已获取
adbpgmem_mcp_selfhosted项目源码adbpgmem-mcp-server-0.2.0.tar.gz。请将压缩包解压到指定目录
adbpgmem_mcp_selfhosted,后续步骤中的路径均指向该解压目录。
安装步骤
通过pip install安装Python包,将Hook CLI入口注册到当前Python环境:
pip install -e /path/to/adbpgmem_mcp_selfhosted-e(editable)模式将源码链接到当前环境,修改代码后无需重装即可生效。适合开发和调试阶段。如需生产部署,可去掉-e使用标准安装。
安装完成后,以下Qoder专用的CLI命令将可用:
命令 | 说明 |
| Hook注册工具(支持多平台) |
| Hook卸载工具(支持多平台) |
验证安装:
which adbpgmem-qoder-stop
# 应输出安装路径,如 /usr/local/bin/adbpgmem-qoder-stop配置Hooks
Hooks支持通过环境变量或配置文件配置长记忆服务连接参数,优先级从高到低:
优先级 | 配置来源 | 说明 |
1 | 环境变量 | 通过 |
2 |
| 环境变量,指向配置文件所在目录,程序会在该目录下查找 |
3 |
| 项目级配置文件 |
4 |
| 全局配置文件 |
需要配置的参数
参数 | 类型 | 必填 | 说明 |
| string | 是 | AnalyticDB for PostgreSQL长记忆服务的API地址 |
| string | 是 | 服务鉴权Token(敏感信息) |
| string | 否 | 用户标识,默认取系统用户名 |
方式一:环境变量
在启动Qoder前导出环境变量,Hooks会继承父进程的环境变量:
export ADBPGMEM_API_URL="https://api-longmemory-cn-chengdu.opentrust.net"
export ADBPGMEM_API_TOKEN="sk-your-token-here"
export ADBPGMEM_USER_ID="your.username"环境变量方式每次开新终端都需要重新设置,建议写入~/.zshrc或~/.bashrc持久化。
方式二:配置文件(推荐)
写入后无需再次操作,ADBPGMEM_USER_ID可省略(默认取系统用户名)。
全局配置(推荐,对所有项目生效):
mkdir -p ~/.qoder
cat > ~/.qoder/adbpgmem.conf << 'EOF'
ADBPGMEM_API_URL="https://api-longmemory-cn-chengdu.opentrust.net"
ADBPGMEM_API_TOKEN="sk-your-token-here"
ADBPGMEM_USER_ID="your.username"
EOF项目级配置(仅对当前项目生效):
mkdir -p .qoder
cat > .qoder/adbpgmem.conf << 'EOF'
ADBPGMEM_API_URL="https://api-longmemory-cn-chengdu.opentrust.net"
ADBPGMEM_API_TOKEN="sk-your-token-here"
ADBPGMEM_USER_ID="your.username"
EOFadbpgmem.conf包含API Token,请勿提交到Git。建议在.gitignore中添加.qoder/adbpgmem.conf。配置不完整时Hooks会静默跳过执行,不影响Qoder正常运行。
注册Hooks
安装并配置完成后,执行以下命令将3个Hook脚本注册到Qoder的生命周期事件。安装器会自动检测当前平台(也可通过--platform qoder手动指定)。
全局安装(推荐)
写入~/.qoder/settings.json,对所有项目生效:
# (可选)备份现有配置
cp ~/.qoder/settings.json ~/.qoder/settings.json.bak 2>/dev/null
# 全局注册(自动检测平台)
adbpgmem-install-hooks --global
# 或手动指定Qoder平台
adbpgmem-install-hooks --platform qoder --global项目级安装
写入<项目>/.qoder/settings.json,仅对当前项目生效:
# (可选)备份现有配置
cp .qoder/settings.json .qoder/settings.json.bak 2>/dev/null
# 项目级注册
adbpgmem-install-hooks
# 或手动指定
adbpgmem-install-hooks --platform qoder按类型选择性安装
安装器支持按Hook职责分组选择性安装:
# 仅安装记录类Hook(stop + pretooluse)
adbpgmem-install-hooks --global --type write
# 仅安装注入类Hook(userpromptsubmit)
adbpgmem-install-hooks --global --type read
# 安装全部(默认)
adbpgmem-install-hooks --global --type all声明式语义:每次安装会先清除Qoder平台下所有adbpgmem Hook,再写入指定分组,切换type时不会遗留旧配置。
注册后,settings.json中会写入以下Hook配置:
{
"hooks": {
"UserPromptSubmit": [
{
"matcher": "",
"hooks": [
{"type": "command", "command": "adbpgmem-qoder-userpromptsubmit", "timeout": 10}
]
}
],
"Stop": [
{
"matcher": "",
"hooks": [
{"type": "command", "command": "adbpgmem-qoder-stop", "timeout": 30}
]
}
],
"PreToolUse": [
{
"matcher": "*",
"hooks": [
{"type": "command", "command": "adbpgmem-qoder-pretooluse", "timeout": 2}
]
}
]
}
}幂等安装:重复执行adbpgmem-install-hooks不会产生重复条目,会先清除已有的adbpgmem Hook再重新写入。立即生效:Qoder在编辑配置文件后即刻生效,无需重启或启动新会话。
卸载Hooks
# 自动检测平台(推荐)
adbpgmem-uninstall-hooks --global # 全局卸载
adbpgmem-uninstall-hooks # 项目级卸载
# 手动指定平台
adbpgmem-uninstall-hooks --platform qoder --global
# 同时清理会话注入标记目录
adbpgmem-uninstall-hooks --global --remove-sessions卸载命令会从配置文件中移除所有adbpgmem-*开头的hook entry,并清理空的事件数组。配合--remove-sessions可同时删除~/.qoder/.adbpgmem-injected-sessions/节流标记目录。
怎么使用Hooks
验证注册
# 检查Hooks是否注册成功
cat ~/.qoder/settings.json
# 应包含 adbpgmem-qoder-stop 等条目功能测试:在Qoder中发送一条消息,观察AI回答是否包含了历史记忆上下文。
查看日志
Hook运行日志写入~/.qoder/adbpgmem-hooks.log,排障时查看最新日志:
tail -50 ~/.qoder/adbpgmem-hooks.log调用方式
Hooks全自动运行,无需任何手动操作。Qoder在以下时机自动触发:
触发时机 | 执行的Hook | 用户感知 |
用户发送首条消息 |
| Qoder AI回答时已包含历史偏好和架构决策 |
Qoder AI写入文件时 |
| 阻止写入MEMORY.md等本地记忆文件 |
退出会话 |
| 无感知,后台提取并保存会话摘要 |
各Hook详细工作原理
adbpgmem-qoder-userpromptsubmit(UserPromptSubmit:记忆上下文注入)
触发时机:用户每次向Qoder AI发送消息时。通过会话级节流机制,仅在每个会话的首条消息时触发记忆注入,后续消息自动跳过。
工作流程:
读取Qoder传入的JSON输入(包含
session_id、prompt、cwd等信息)。加载AnalyticDB for PostgreSQL长记忆配置。
会话级节流检查:在
~/.qoder/.adbpgmem-injected-sessions/目录下查找以session_id命名的标记文件。如果标记文件存在,说明本会话已注入过记忆,直接跳过。执行双查询搜索策略:查询1使用用户发送的
prompt文本获取与当前问题最相关的历史记忆;查询2使用{{项目名}} 项目架构 技术栈获取项目背景信息。对两组结果去重(按
memory_id)。格式化为编号列表,通过
hookSpecificOutput.additionalContext字段注入到Qoder AI的会话上下文中。创建标记文件,防止同一会话重复注入。
由于Qoder自1.106.x版本起已停止触发SessionStart事件,记忆注入改用UserPromptSubmit事件。会话级节流确保每个会话只注入一次,避免重复触发带来的性能开销。
输出示例:
# adbpgmem 跨会话记忆
1. 项目使用 Go 1.22 + Gin 框架,ORM 使用 GORM v2
2. 数据库选择 PostgreSQL 15,连接池用 PgBouncer,最大连接数 50
3. API 统一使用 RESTful 风格,错误码遵循 RFC 7807adbpgmem-qoder-stop(Stop:会话结束保存)
触发时机:用户退出Qoder会话时。
工作流程:
读取Qoder传入的JSON输入(包含
session_id、cwd、transcript_path等)。读取会话transcript文件(JSONL格式的完整对话记录)。
智能摘要提取(两遍处理):第一遍收集所有user/assistant消息;第二遍智能筛选,保留用户最后一条消息,过滤assistant的过渡性消息(< 100字符),按长度排序取top 5条assistant消息(总预算6000字符)。
如果transcript文件不可用,回退到从stdin JSON的
conversation_summary字段提取。短会话过滤:摘要长度 < 50字符时跳过保存。
以
infer=false方式保存到AnalyticDB for PostgreSQL长记忆服务,附加metadata:type=session_summary。
设计目的:自动保存每次会话的有价值内容,无需用户手动操作,下次会话时可通过UserPromptSubmit Hook检索到。
adbpgmem-qoder-pretooluse(PreToolUse:守护本地记忆文件)
触发时机:Qoder AI调用文件写入工具时。matcher设为*(通配符),因为Qoder同时支持原生命名和Claude Code兼容命名的工具。
工作流程:
读取Qoder传入的JSON输入(包含
tool_name、tool_input等)。判断是否为文件写入工具(Write/Edit/SearchReplace)。
检查目标文件路径是否匹配守护模式:
MEMORY.md、memory.md、.claude/memory/。匹配则同时返回
decision: "block"和permissionDecision: "deny",阻止写入。不匹配则放行,允许正常写入。
设计目的:防止Qoder AI将记忆分散写入本地文件,确保所有记忆集中存储到adbpgmem,便于跨会话检索和管理。
典型场景使用案例
场景一:新会话自动继承历史决策
您在项目中确定了技术栈选型,下次开启新会话时希望Qoder AI自动知晓。
会话1(通过MCP工具或其他方式保存了记忆):
你: 记住:项目使用 Python 3.11 + FastAPI,数据库 PostgreSQL 15,缓存 Redis 7会话2(几天后启动新会话):
你: 帮我添加一个新的 API 端点
← adbpgmem-qoder-userpromptsubmit 自动触发(首条 prompt)
← 双查询搜索用户 prompt 和 "项目名 项目架构 技术栈"
← 将匹配的记忆注入 additionalContext
← 创建会话标记文件,后续消息不再重复触发
Qoder AI: 基于项目的 FastAPI + PostgreSQL 15 技术栈,我来创建新的端点...
[自动使用正确的框架和数据库版本]用户无需手动告知Qoder AI技术栈,历史记忆已在首条消息时自动注入。
场景二:防止记忆分散到本地文件
Qoder AI在对话中尝试将记忆写入本地MEMORY.md文件。
Qoder AI: [尝试调用 Write 工具写入 MEMORY.md]
"让我把这次的架构决策记录到 MEMORY.md..."
← adbpgmem-qoder-pretooluse 自动触发
← 检测到目标路径匹配 "MEMORY.md" 守护模式
← 返回 decision: "block" + permissionDecision: "deny"
← reason: "记忆应通过 add_memory MCP 工具存储到 adbpgmem"
Qoder AI: [收到阻止信号,改为使用 add_memory MCP 工具]
已将架构决策保存到 adbpgmem 记忆库。所有记忆集中存储到 adbpgmem,避免分散在本地文件中导致跨会话无法检索。
场景三:MCP + Hooks组合使用(最完整方案)
您希望获得最完整的记忆能力,同时使用MCP工具和Hooks。
配置步骤:
# 1. 安装Python包(Hooks需要)
pip install -e /path/to/adbpgmem_mcp_selfhosted
# 2. 注册MCP Server(编辑 ~/.qoder/settings.json,添加 mcpServers 配置)
# 3. 注册Hooks
adbpgmem-install-hooks --platform qoder --global
# 4. 配置AGENTS.md(引导Qoder AI主动使用MCP工具)
cat >> AGENTS.md << 'EOF'
# MCP Servers
- **adbpgmem**: 持久记忆服务。每次会话开始时先 search_memories 搜索相关上下文,
发现架构决策、调试经验、编码模式时用 add_memory 保存。宁可多记,不可漏记。
EOF完整的~/.qoder/settings.json示例(MCP + Hooks共存):
{
"mcpServers": {
"adbpgmem": {
"command": "uvx",
"args": ["--from", "/path/to/adbpgmem_mcp_selfhosted", "adbpgmem-mcp-server"],
"env": {
"ADBPGMEM_API_URL": "https://api-longmemory-cn-chengdu.opentrust.net",
"ADBPGMEM_API_TOKEN": "sk-your-token-here",
"ADBPGMEM_USER_ID": "your.username"
}
}
},
"hooks": {
"UserPromptSubmit": [
{
"matcher": "",
"hooks": [
{"type": "command", "command": "adbpgmem-qoder-userpromptsubmit", "timeout": 10}
]
}
],
"Stop": [
{
"matcher": "",
"hooks": [
{"type": "command", "command": "adbpgmem-qoder-stop", "timeout": 30}
]
}
],
"PreToolUse": [
{
"matcher": "*",
"hooks": [
{"type": "command", "command": "adbpgmem-qoder-pretooluse", "timeout": 2}
]
}
]
}
}组合使用效果:
能力 | 来源 | 说明 |
首条消息自动加载记忆 | Hooks(UserPromptSubmit) | 后台自动注入历史上下文(会话级节流) |
会话结束自动保存记忆 | Hooks(Stop) | 后台自动提取并保存会话内容 |
守护本地记忆文件 | Hooks(PreToolUse) | 阻止写入MEMORY.md,集中管理 |
手动保存精确知识 | MCP(add_memory) | 在对话中主动记录重要决策 |
按需搜索历史记忆 | MCP(search_memories) | 在需要时精确检索历史经验 |
记忆CRUD管理 | MCP(update/delete/list) | 更新、删除、浏览记忆 |