Hindsight 集成 ZCode:为 Z.ai GLM 桌面编程代理接入持久化长期记忆
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
导读
本文介绍如何通过 Hindsight 为 ZCode(Z.ai 推出的 GLM 桌面编程代理)接入持久化长期记忆。ZCode 内嵌 Claude Code 代理运行时并原生支持进程钩子(hooks),因此无需启动任何 MCP 服务器、也无需改变既有工作流——只需安装一次 Python 钩子脚本,Hindsight 就会在每个提示词之前自动召回相关记忆、在每轮对话结束后自动留存对话。读完本文,你将掌握hindsight-zcode的完整安装、卸载、配置、连接模式与运行原理,并了解三个核心钩子(SessionStart / UserPromptSubmit / Stop)的底层调用链。
Quick Start:一分钟接入
Hindsight 为 ZCode 提供了独立的 Python 安装包hindsight-zcode,安装后通过一次性安装器把钩子脚本写入 ZCode 的配置目录。
方式一:Hindsight Cloud(推荐)
注册获取 Hindsight Cloud API Key 后,执行:
# 安装 CLI pip install hindsight-zcode # 安装钩子(默认连接 Hindsight Cloud) hindsight-zcode install --api-url https://api.hindsight.vectorize.io --api-token your-api-key # 重启 ZCode —— 记忆即刻生效方式二:本地自托管(hindsight-embed)
不传任何参数即可让插件连接本地的hindsight-embed守护进程:
hindsight-zcode install卸载
hindsight-zcode uninstall卸载会删除钩子脚本,并从~/.zcode/cli/config.json中剥离 Hindsight 的条目;该文件中其他键与其他第三方钩子,以及~/.hindsight/zcode.json个人配置都会被保留。
安装器到底做了什么
从 install.py 的实现看,hindsight-zcode install依次完成四件事:
- 复制钩子负载:把包内
hindsight_zcode/hooks/scripts/整棵脚本树(含lib/包)复制到~/.zcode/hooks/hindsight/scripts/; - 写入默认配置:把
settings.json部署到~/.zcode/hooks/hindsight/settings.json,并打上安装时的包版本号; - 注册钩子:读取包内的 hooks.json 模板,把
__SCRIPTS_DIR__占位符替换为绝对路径后,合并进~/.zcode/cli/config.json的hooks.events块,同时强制hooks.enabled: true(ZCode 默认关闭配置钩子)并设置maxOutputBytes为 32768(超过该字节数的钩子 stdout 会被丢弃); - 播种用户配置:若
~/.hindsight/zcode.json不存在则创建之(存放hindsightApiUrl与hindsightApiToken),已存在则绝不覆盖。
合并逻辑是幂等的:通过HOOK_MARKER = "hooks/hindsight"识别既有 Hindsight 条目并替换而非重复追加,同时保留 config.json 中的其他键与第三方钩子(见 install.py)。值得强调的是,安装器只会写 ZCode 自己的配置命名空间~/.zcode/cli/config.json,绝不会触碰你的 Claude Code 配置~/.claude/settings.json。
方式三:以 ZCode 插件方式安装(免 pip)
ZCode 支持从插件市场直接安装 Hindsight,钩子脚本以仅含 hooks 的 Claude Code 插件形式(hindsight-zcode)发布:
# 在 ZCode 中:添加 Hindsight 市场,然后安装插件 zcode plugins add-marketplace vectorize-io/hindsight zcode plugins install hindsight-zcode以插件方式安装时,ZCode 会自动注册钩子(无需编辑配置文件)。凭据通过环境变量(HINDSIGHT_API_URL、HINDSIGHT_API_TOKEN)或~/.hindsight/zcode.json提供:
{ "hindsightApiUrl": "https://api.hindsight.vectorize.io", "hindsightApiToken": "hsk_your_token" }功能总览
- 自动召回(Auto-recall):每个提示词提交前,向 Hindsight 查询相关记忆,并作为额外上下文注入(对模型可见,不写入会话转录);
- 自动留存(Auto-retain):每次回复结束后,把该轮对话存入 Hindsight,供未来召回;
- 无需 MCP:纯 Python 钩子脚本直接调用 Hindsight 的 REST API,无需任何常驻旁进程;
- 跨工具记忆:同一 Hindsight bank 可被 Claude Code、Cursor 等其他集成共享,记忆跟随你在工具间流动;
- 动态 Bank ID:支持按工作目录做项目级记忆隔离;
- 零运行时依赖:钩子脚本是纯 Python 标准库实现;
pip install只携带一次性安装器(pyproject.toml中dependencies = [],要求 Python 3.11+,见 pyproject.toml)。
架构:三个钩子事件驱动记忆闭环
ZCode 内嵌 Claude Code 代理运行时,从自己的配置命名空间~/.zcode/cli/config.json读取标准的 Claude Code 钩子 schema(要求hooks.enabled: true)。插件接通三个钩子事件:
| 钩子脚本 | 事件 | 作用 |
|---|---|---|
session_start.py | SessionStart | 预热 —— 验证 Hindsight 是否可达 |
recall.py | UserPromptSubmit | 自动召回—— 查询记忆,作为additionalContext注入 |
retain.py | Stop | 自动留存—— 组装本轮对话,POST 到 Hindsight |
三个钩子注册时的超时配置见 hooks.json:SessionStart 5000ms、UserPromptSubmit 12000ms、Stop 15000ms,全部以python3作为process类型钩子命令运行。
召回:UserPromptSubmit
recall.py在用户点击发送之后、后端请求发出之前触发(实现见 recall.py),流程如下:
- 从 stdin 读取钩子输入(prompt、session_id/sessionId、transcript_path、cwd 等),对
prompt与user_prompt两个字段做防御性兼容; - 把用户提示词暂存到状态文件
last_prompt_<session_id>.json(供后续 Stop 钩子配对); - 解析 API 地址(外部 API / 本地 daemon 二选一);
- 派生 Bank ID 并确保 mission 已设置;
- 当
recallContextTurns > 1时,从transcript_path读取转录并组装多轮查询,再按recallMaxQueryChars(默认 800)截断; - 调用 Hindsight recall API(携带
maxTokens、budget、types、timeout参数); - 格式化记忆并输出符合 Claude Code
UserPromptSubmitschema 的 JSON:hookSpecificOutput.additionalContext。
注入给模型的上下文块形如:
<hindsight_memories> Relevant memories from past conversations (prioritize recent when conflicting). Only use memories that are directly useful to continue this conversation; ignore the rest: Current time - 2026-03-27 09:14 - Project uses FastAPI with asyncpg — not SQLAlchemy [world] (2026-03-26) - Preferred testing framework: pytest with pytest-asyncio [experience] (2026-03-26) </hindsight_memories>无论召回成功与否,该钩子始终以退出码 0 结束(优雅降级,绝不阻塞代理主流程)。
留存:Stop
ZCode 没有提供SessionEnd钩子事件,因此留存寄生在Stop事件上——每轮对话完成后即存储,每一轮是独立的记忆(独立document_id)。实现见 retain.py:
- ZCode 的 Stop 载荷携带完整助手回复
responseText和一个仅含助手消息的临时转录文件(transcript_path,钩子运行后即被删除),不携带用户提示词——所以 retain 依赖 recall 钩子暂存的last_prompt_<session_id>.json来配对完整的一轮对话; - 助手文本按
responseText→ 解析转录中最后一条 assistant 消息 →responsePreview的顺序解析; - 组装
[user, assistant]消息列表,按retainRoles过滤角色,剥离记忆标签后格式化转录; - 应用
retainEveryNTurns频率门控(默认 1,即每轮都存); - 解析 API 地址并派生 Bank ID,生成
document_id = f"{session_id}-{ms_timestamp}"保证每轮独立、旧轮不被覆盖; - 解析标签模板变量(
{session_id}、{conversation_id}、{bank_id}、{timestamp})后,连同retained_at、message_count、session_id等元数据 POST 到 Hindsight retain API。
同样的,retain 失败也只写 stderr 日志并以 0 退出,代理永不阻塞。
连接模式
连接模式的选择由hindsightApiUrl是否配置决定,优先级逻辑在 daemon.py 中清晰可见:外部 API → 已存在的本地服务 → 自动管理的 daemon。
模式一:外部 API(推荐)
通过~/.hindsight/zcode.json连接运行中的 Hindsight 服务(云或自托管):
{ "hindsightApiUrl": "https://api.hindsight.vectorize.io", "hindsightApiToken": "hsk_your_token" }hindsightApiUrl必须是http/https协议(HindsightClient构造时校验),请求带Authorization: Bearer <token>头,并携带自定义User-Agent: hindsight-zcode/<version>(避免自托管环境反向代理按 UA 拦截标准库 urllib 请求,见 client.py)。
模式二:本地 Daemon
本地运行hindsight-embed。session_start.py钩子会在apiPort(默认9077)上检测它。守护进程不会由插件自动启动——需要单独启动:
uvx hindsight-embed然后在配置中留空hindsightApiUrl,插件自动连接http://localhost:9077。
值得注意的是,retain 钩子调用get_api_url(..., allow_daemon_start=True),即没有外部 API 且本地服务不可达时,retain 会尝试自动拉起 daemon;而 recall 钩子allow_daemon_start=False,此时 session_start 钩子会在后台预先预热 daemon(prestart_daemon_background,非阻塞)。Daemon 以zcode命名 profile 启动,支持daemonIdleTimeout空闲退出、macOS 上强制本地 embedding/reranker 使用 CPU 等细节。
配置详解
默认配置随安装部署在~/.zcode/hooks/hindsight/settings.json。需要跨版本稳定的个人覆盖,请在~/.hindsight/zcode.json中配置。绝大多数设置也可通过环境变量覆盖。
加载顺序(后加载者生效,见 config.py):
- 内置默认值
- 插件
settings.json(~/.zcode/hooks/hindsight/settings.json) - 用户配置(
~/.hindsight/zcode.json) - 环境变量
连接配置
| 配置项 | 环境变量 | 默认值 | 说明 |
|---|---|---|---|
hindsightApiUrl | HINDSIGHT_API_URL | "" | Hindsight API 服务器地址。留空 = 本地 daemon。 |
hindsightApiToken | HINDSIGHT_API_TOKEN | null | API 认证令牌。Hindsight Cloud 必填。 |
apiPort | HINDSIGHT_API_PORT | 9077 | 本地hindsight-embeddaemon 端口。 |
daemonIdleTimeout | HINDSIGHT_DAEMON_IDLE_TIMEOUT | 0 | daemon 空闲退出超时(秒)。 |
embedVersion | HINDSIGHT_EMBED_VERSION | "latest" | daemon 模式使用的hindsight-embed版本。 |
记忆 Bank 配置
| 配置项 | 环境变量 | 默认值 | 说明 |
|---|---|---|---|
bankId | HINDSIGHT_BANK_ID | "zcode" | 读写使用的 bank。未开启dynamicBankId时所有会话共享。 |
bankMission | HINDSIGHT_BANK_MISSION | 编码助手提示词 | 描述代理用途,创建/更新 bank 时发送。 |
dynamicBankId | HINDSIGHT_DYNAMIC_BANK_ID | false | 为true时按dynamicBankGranularity字段派生唯一 bank ID,用于项目级隔离。 |
agentName | HINDSIGHT_AGENT_NAME | "zcode" | 动态 bank ID 派生中使用的代理名。 |
dynamicBankGranularity | — | ["agent", "project"] | 动态 bank ID 的构成字段(合法值:agent、project、gitProject、session、user)。 |
bankMission与retainMission的默认值来自 settings.json:前者聚焦技术决策、代码变更、调试会话与项目上下文;后者指导记忆引擎提炼技术决策、代码模式、调试方案、用户偏好与架构选择,忽略例行寒暄与瞬时操作信息。Mission 只在首次使用时通过set_bank_mission写入一次(bank_missions.json状态去重,见 bank.py)。
动态 Bank ID 的项目名解析优先级为:ZCODE_PROJECT_DIR环境变量 →workspace_roots[0]→ 钩子载荷中的cwd(Claude Code 运行时每个钩子都会设置);均缺失时回退为"unknown"。默认粒度会生成形如zcode::my-project的 bank。
自动召回配置
| 配置项 | 环境变量 | 默认值 | 说明 |
|---|---|---|---|
autoRecall | HINDSIGHT_AUTO_RECALL | true | 自动召回总开关。 |
recallBudget | HINDSIGHT_RECALL_BUDGET | "mid" | 搜索深度:"low"(快)、"mid"(均衡)、"high"(彻底)。 |
recallMaxTokens | HINDSIGHT_RECALL_MAX_TOKENS | 1024 | 注入记忆块的 token 预算。 |
recallTimeout | HINDSIGHT_RECALL_TIMEOUT | 10 | recall API 调用超时(秒)。 |
recallTypes | — | ["world", "experience"] | 召回的记忆类型。 |
recallContextTurns | HINDSIGHT_RECALL_CONTEXT_TURNS | 1 | 组成召回查询时参考的历史对话轮数。 |
recallMaxQueryChars | HINDSIGHT_RECALL_MAX_QUERY_CHARS | 800 | 召回查询的最大字符数。 |
recallRoles | — | ["user", "assistant"] | 组装多轮查询时包含的角色。 |
recallPromptPreamble | — | 内置提示语 | 注入上下文块开头的前缀说明。 |
自动留存配置
| 配置项 | 环境变量 | 默认值 | 说明 |
|---|---|---|---|
autoRetain | HINDSIGHT_AUTO_RETAIN | true | 自动留存总开关。 |
retainEveryNTurns | HINDSIGHT_RETAIN_EVERY_N_TURNS | 1 | 每 N 轮留存一次。默认1表示每轮在Stop时都存储。 |
retainRoles | — | ["user", "assistant"] | 留存时包含的消息角色。 |
retainContext | — | "zcode" | 留存时上报的上下文标识。 |
retainTags | — | ["{session_id}"] | 留存标签,支持{session_id}、{conversation_id}、{bank_id}、{timestamp}模板变量。 |
retainMetadata | — | {} | 附加元数据(值同样支持模板变量)。 |
debug | HINDSIGHT_DEBUG | false | 向 stderr 输出调试日志。 |
与 ZCode 内置记忆的关系
ZCode 自带本地的、按项目隔离的记忆(~/.zcode/cli/memories/)。Hindsight 与其是互补关系:Hindsight 把记忆存放在云端(或自托管)的 bank 中,跨工具共享——同一个 bank 同时支撑 Claude Code、Cursor 及其他 Hindsight 集成——因此你的上下文跟随你跨越不同的代理与机器,而不是局限在某个 ZCode 项目的本地目录里。
常见问题排查
- 记忆不出现:开启
debug: true(或HINDSIGHT_DEBUG=true),检查HINDSIGHT_API_URL指向的服务器是否可达;调试日志通过 stderr 输出。 - 钩子不触发:检查
~/.zcode/cli/config.json是否为合法 JSON、hooks.enabled是否为true、hooks.events下是否存在 Hindsight 条目;ZCode 需要重启会话才能加载新钩子;同时确认 shell 的$PATH中能找到python3。 - 本地 daemon 未就绪:确认已单独启动
uvx hindsight-embed,且hindsightApiUrl留空;或直接配置外部 API 地址。
附:仓库中的验证与扩展资源
- 安装/合并/卸载逻辑:install.py
- 三个钩子实现:recall.py、retain.py、session_start.py
- 配置解析与环境变量映射:lib/config.py
- 连接模式与 daemon 生命周期:lib/daemon.py
- Bank ID 派生与 mission 管理:lib/bank.py
- REST API 客户端(纯标准库):lib/client.py
- 完整配置默认值:settings.json、hooks.json
- 测试:
hindsight-integrations/zcode/tests/下的test_hooks.py、test_install.py、test_client.py、test_bank.py等(mock HTTP 客户端与 stdin/stdout 管道,无需真实 Hindsight 服务器即可运行)
集成包本身零依赖、采用 MIT 许可(见 pyproject.toml),其 CLI 入口hindsight-zcode暴露install与uninstall两个子命令(cli.py),其中--api-url与--api-token也支持从环境变量直接读取,方便脚本化安装。
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考