news 2026/9/8 23:59:02

MemPalace Hooks 自动保存全指南:为 Claude Code / Cursor 等编码 Agent 配置“永久记忆“

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MemPalace Hooks 自动保存全指南:为 Claude Code / Cursor 等编码 Agent 配置“永久记忆“

MemPalace Hooks 自动保存全指南:为 Claude Code / Cursor 等编码 Agent 配置"永久记忆"

【免费下载链接】mempalaceThe best-benchmarked open-source AI memory system. And it's free.项目地址: https://gitcode.com/GitHub_Trending/me/mempalace

MemPalace Hooks 是 MemPalace 面向终端 AI 编码工具(Claude Code、Cursor、Codex CLI、Google Antigravity)提供的"自动保存"能力:无需手工执行任何保存命令,AI 在对话过程中就会把新事实、决策、代码与工具输出持续写入宫殿(palace)。本文将基于仓库内 examples/HOOKS_TUTORIAL.md 与 hooks/README.md 的文档骨架,结合真实 hook 脚本源码,完整讲解 hook 的安装接线、触发机制、配置参数、历史会话回填、多平台扩展与调试方法。读完你既能三分钟给 Claude Code 装上自动记忆,也能深入理解其防死循环、双层捕获与静默模式背后的实现原理。

一、Hook 家族总览:它们到底在什么时机做什么

MemPalace 目前提供三支"扁平安装"于仓库hooks/目录下的通用 hook 脚本,各自对应一个生命周期事件:

Hook 脚本触发时机行为
mempal_save_hook.sh(Save Hook)每 15 条人类消息(SAVE_INTERVAL)后的 Stop 事件自动挖掘对话 JSONL 转写稿(含工具输出),并按配置决定是否短暂"阻断"AI,提示其把主题 / 决策 / 引语写入结构化记忆
mempal_precompact_hook.sh(PreCompact Hook)上下文窗口即将被压缩(compaction)之前同步挖掘转写稿做一次"最终保存",兜底保住压缩前的一切细节
mempal_session_end_hook.sh(SessionEnd Hook)会话正常退出后台化执行一次最终挖掘,避免短会话被遗漏,立即返回、绝不拖慢退出

正如 hooks/README.md 开头所说:Save Hook 是定时器,PreCompact Hook 是安全网。Save Hook 依赖消息计数阈值,可能几次消息都没触发;而 PreCompact 发生在 AI 即将丢失详细上下文之前,无论是否到点都必须保存。二者的区别在源码里体现得淋漓尽致——PreCompact 钩子对转写稿执行的是**同步(前台阻塞)**挖掘(见 mempal_precompact_hook.sh),因为压缩不可逆,一旦 Cursor / Claude Code 摘要了对话,逐字的原文就再也取不回来了;而 Save Hook 的挖掘是在后台&执行的(见 mempal_save_hook.sh),绝不阻塞 AI 的正常停步。

版本说明:本教程针对v3.1.0+的 hook 行为撰写。更早版本只依赖"AI 在聊天窗口里写日记",而 v3.1.0+ 引入了下文要讲的双层捕获机制。

二、Claude Code 安装接线(全局 / 项目级)

MemPalace 的 Claude Code hook 通过 Claude Code 的settings.local.json挂载。可以放在全局~/.claude/settings.local.json,也可以放在项目级.claude/settings.local.json。把完整 JSON 写入其中之一:

{ "hooks": { "Stop": [ { "matcher": "*", "hooks": [{ "type": "command", "command": "/absolute/path/to/hooks/mempal_save_hook.sh", "timeout": 30 }] } ], "SessionEnd": [ { "hooks": [{ "type": "command", "command": "/absolute/path/to/hooks/mempal_session_end_hook.sh", "timeout": 10 }] } ], "PreCompact": [ { "hooks": [{ "type": "command", "command": "/absolute/path/to/hooks/mempal_precompact_hook.sh", "timeout": 30 }] } ] } }

随后为脚本添加执行权限:

chmod +x hooks/mempal_save_hook.sh hooks/mempal_session_end_hook.sh hooks/mempal_precompact_hook.sh

注意:/absolute/path/to/hooks/替换成你实际克隆 MemPalace 仓库的目录(例如~/projects/mempalace/hooks/)。脚本自身能从所在路径解析仓库根目录,因此仓库装在哪里都能工作,但command字段必须是绝对路径。

三个字段值得说明:

  • StopPreCompacttimeout30,因为挖掘(mine)可能需要一点时间;SessionEnd10即可——它把重活丢给后台进程后立即返回,见 mempal_session_end_hook.sh。
  • matcher: "*"表示对所有消息生效。
  • 若只想要"最小可用"版本,仅保留Stop一节即可(对应下文 Cursor 的 hooks.minimal.json 思路)。

必须重启会话。Claude Code 只在会话启动时加载settings.json中的 hooks。安装或改动 hook 配置后,请完全重启 Claude Code 再验证,否则不会触发(这是 Claude Code 的固有限制,见 hooks/README.md 的 Known Limitations)。

三、Hook 工作原理:源码级剖析

3.1 Hook 协议:stdin JSON 是唯一的输入

Claude Code 在触发 hook 时会把一个 JSON 对象写入脚本的 stdin,关键字段包括:

  • session_id—— 会话唯一标识;
  • stop_hook_active—— 是否已处于"保存循环"中(防死循环的关键标志);
  • transcript_path—— 本次会话的 JSONL 转写稿路径。

脚本读取 stdin 后,把解析、清洗与计数工作委托给 Python,而不是在 shell 里裸写正则。这个分工沉淀在 mempalace/hook_shell.py 中,命令有三种:

子命令职责实现位置
parse-stop解析并清洗 Stop 载荷,输出session_id/stop_hook_active/transcript_pathhook_shell.py
parse-precompact同上,面向 PreCompact 载荷hook_shell.py
count-human-messages数 JSONL 中人类消息条数hook_shell.py

以人类消息计数为例(hook_shell.py):它逐行解析 JSONL,统计message.role == "user"的条目;特别地,把内含<command-message>的内容排除在外,避免把命令类消息也算成"人类对话"。它对"路径存在但不是普通文件"的情况直接返回 0——因为打开 FIFO 读取会阻塞在内核上且没有超时。这也是脚本先[ -f "$TRANSCRIPT_PATH" ]判定的原因。

值得一提的安全细节:脚本通过"哨兵 +sed -n 'Np'逐行取值"的方式从 Python 输出还原变量,全程eval生成代码session_id会被清洗到[a-zA-Z0-9_-]字符集、transcript_path会被去除控制字符并把\规整为/(兼容 Windows 路径)。若解析失败且输入非空,脚本会把不超过 4 KB 的原始载荷写入last_input.log并以chmod 600锁定权限——fail-loud 契约由 tests/test_hooks_bash_compat.py 钉死。之所以用sed -n 'Np'而非mapfile/readarray,是因为 macOS 自带的 bash 3.2.57(Apple 在 2006 年 GPLv3 冻结时封存的版本)没有数组读取内建命令——见脚本内注释引用的回归记录。

3.2 Save Hook:计数 → 触发 → 后台挖掘 → 阻断(可选)

mempal_save_hook.sh 的执行主流程可以归纳为一张图:

用户发消息 → AI 回复 → Claude Code 触发 Stop hook ↓ 脚本用 Python 数 JSONL 里的人类消息数 ↓ ┌── 距上次保存 < SAVE_INTERVAL ──→ echo "{}"(放行,AI 正常停止) │ └── 距上次保存 ≥ SAVE_INTERVAL ↓ 后台自动挖掘转写稿 → 宫殿(原始工具输出被捕获) ↓ MEMPAL_VERBOSE=true → {"decision":"block","reason":"..."} (默认静默) → echo "{}"(纯后台保存,不打扰聊天) ↓ AI 尝试再次停止 ↓ stop_hook_active = true → 脚本放行(防死循环)

几个关键实现点:

  • 触发判定(mempal_save_hook.sh):EXCHANGE_COUNT(本次人类消息数)减去LAST_SAVE(记录在~/.mempalace/hook_state/<session_id>_last_save的计数)≥SAVE_INTERVAL才触发。状态文件按 session 隔离,所以会话各自独立计时。
  • 防死循环(mempal_save_hook.sh):一旦stop_hook_active为真(说明 AI 正在执行上一轮"请保存"的指令),脚本直接echo "{}"放行。协议上是"block 一次 → AI 保存 → 再次尝试停止 → 放行",天然不成环。
  • 双层捕获的第 1 层(Auto-mine)(mempal_save_hook.sh):触发保存时,hook 对转写稿所在目录执行mempalace mine <transcript-dir> --mode convos(后台运行)。这一步把Bash 结果、搜索结果、构建报错等原始工具输出直接 upsert 进宫殿——这些正是 AI 在摘要时通常会"总结掉"的细节。
  • 双层捕获的第 2 层(阻断提示)(mempal_save_hook.sh):当MEMPAL_VERBOSE=true时,hook 返回decision: "block",并把 reason 作为系统消息喂给 AI:
MemPalace save checkpoint. Write a brief session diary entry covering key topics, decisions, and code changes since the last save. Use verbatim quotes where possible. Continue after saving.

注意 reason 的措辞是"verbatim quotes"(逐字引语)——与 v3.1.0 之前的"只记主题和决策"不同,它显式要求 AI 原样保存工具输出。两条路径互为保险:即使 AI 偷懒只做摘要不引原文,Auto-mine 那层也已经把逐字工具输出落库了(hooks/README.md 称之为 "belt and suspenders")。

3.3 PreCompact Hook:同步最终保存

与 Save Hook 不同,mempal_precompact_hook.sh不计数、不阻断

  1. 解析出session_idtranscript_path
  2. 同步执行mempalace mine <transcript-dir> --mode convos(必要时再加MEMPAL_DIR --mode projects),必须等挖掘完成、记忆落库后才返回;
  3. 打印{},让压缩正常进行。

正如脚本头注释所强调的:压缩是破坏性的——它把 AI 的详细上下文摘要掉之后,逐字信息就丢了。因此"压缩前必保存"这一保证由同步挖掘承载,而不是 Stop 钩子的 block 协议(PreCompact 场景下decision: "block"会把"保存"伪装成一次普通续写,语义并不合适,且 Claude Code 对 PreCompact 的协议约束与此不同)。同样的工程决策也体现在 Cursor 版 preCompact 的注释里:宁可让大转写稿的同步挖掘超过 hook 超时被 Cursor 杀掉,也不截断挖掘——因为mempalace mine增量、仅追加的,中断只会让下次挖掘续上,不会损坏宫殿。

3.4 SessionEnd Hook:干净退出的收尾

当一次 Claude Code 会话正常退出时,若会话很短、还没走到 Save Hook 的 15 条阈值,这段对话可能整个丢失。SessionEnd Hook 解决这个问题:它捕获 stdin 的 JSON 载荷后,把真正的逻辑丢进detached 子进程执行:

printf '%s' "$payload" | run_mempalace_hook --hook session-end --harness claude-code

run_mempalace_hook依次尝试mempalace命令、MEMBAL_PYTHON -m mempalacepython -m mempalace(见 mempal_session_end_hook.sh)。之所以必须后台化,是因为 Claude Code 文档给的 SessionEnd 默认超时只有 1.5 秒,而一次冷启动mempalace本身就可能超过这个预算;脚本立即返回{},让退出流程永远不被拖延。其业务逻辑全部收敛在 mempalace/hooks_cli.py 的hook_session_end,便于跨 harness 复用。

四、配置参数全解

Hooks 的全部行为由脚本头部变量与环境变量控制。核心参数如下:

参数默认值说明
SAVE_INTERVAL15每 N 条人类消息保存一次。调小 = 更频繁保存、更多打断;调大 = 更少打断
STATE_DIR~/.mempalace/hook_state/hook 状态目录:会话计数、.pending标记、hook.log日志、诊断转储都在这里
MEMPAL_DIR可选的项目目录(代码 / 笔记 / 文档),每次保存触发时额外以--mode projects挖掘。纯增量——对话转写稿无论如何都会以--mode convos挖掘,此选项绝不取代它
MEMPAL_PYTHON自动探测指定 hook 内部 Python 调用的解释器,见下文解析顺序
MEMPAL_VERBOSE关闭true/1时 Save Hook 阻断 AI 并展示日记提示(开发模式);默认静默后台保存
MEMPALACE_HOOKS_AUTO_SAVE开启false/0/no时全局停用自动保存阻断(kill switch)
hooks.auto_save(config.json)true与上一条等效的文件式开关,见 4.2 节

参数命名勘误:文档写的是MEMPALACE_PYTHON,但脚本源码实际读取的是MEMPAL_PYTHON(见 mempal_save_hook.sh 与 mempal_precompact_hook.sh),Cursor 版本亦然(lib/common.sh)。以源码为准,设置MEMPAL_PYTHON才生效。

4.1 Python 解释器解析顺序

为何解析解释器如此重要?GUI 启动的 Claude Code(macOS 下经open -a、Spotlight 或 Dock 启动)继承的是launchd的最小 PATH(/usr/bin:/bin:/usr/sbin:/sbin),往往找不到你装了 mempalace 的那个python3(比如你在 venv 或 pyenv 里)。解析顺序(首个命中即胜出):

  1. $MEMPAL_PYTHON—— 显式覆盖(绝对路径,且必须可执行);
  2. $(command -v python3)—— PATH 上第一个python3
  3. python3—— 最后兜底。

注意:hook 内部用于解析 JSON / 计数的解释器只需要标准库jsonsys,不要求装 mempalace;真正执行挖掘的是mempalace mine这条 CLI,因此mempalace本身也需要位于 hook 环境的 PATH 上。建议用pipx install mempalaceuv tool install mempalace把它装到稳定的全局位置,否则要手动把 venv 的bin/加进 hook 环境 PATH。

4.2 如何彻底停用自动保存(静默模式)

想让 hook 保持安装但不打扰会话?两种方式二选一:

方式一:配置文件~/.mempalace/config.json):

{ "hooks": { "auto_save": false } }

方式二:环境变量

export MEMPALACE_HOOKS_AUTO_SAVE=false

停用后,Save Hook 与 PreCompact Hook 都会直接echo "{}"放行、不再阻断;手动保存依然可用:mempalace mine <dir> --mode convos

五、一次性回填历史会话(Backfill)

Hooks 只对未来的对话生效——你过去几个月堆积的会话记录不会自动进入宫殿。请对历史会话执行一次回填:

mempalace mine ~/.claude/projects/ --mode convos

这条命令会扫描~/.claude/projects/下所有历史会话的 JSONL 转写稿,把它们归入conversationswing。按文档估计,典型开发者机器上数月的会话历史可产出数万条抽屉记录(drawers)。Codex CLI 用户对应执行:

mempalace mine ~/.codex/sessions/ --mode convos

回填只需一次,此后 Save / PreCompact / SessionEnd 三支 hook 会随会话自动挖掘。

六、把 Auto-Save 扩展到其他编码工具

6.1 Cursor(IDE 专用 hook 集)

Cursor 的 hook 生态与 Claude Code 不同,仓库在 hooks/cursor/ 下维护了一整套专用脚本,并共享 hooks/cursor/lib/common.sh(提供状态目录、Python 解析、kill switch、wing 推断等公共逻辑)。推荐用安装器一键接线:

bash hooks/cursor/install.sh

它会把脚本复制到~/.mempalace/hooks/cursor/并合并写入你的~/.cursor/hooks.json。完整接线示意见 examples/cursor/hooks.json:

{ "version": 1, "hooks": { "sessionStart": [ { "command": "$HOME/.mempalace/hooks/cursor/mempal_wake_hook_cursor.sh" } ], "stop": [ { "command": "$HOME/.mempalace/hooks/cursor/mempal_save_hook_cursor.sh", "loop_limit": 1 } ], "preCompact": [ { "command": "$HOME/.mempalace/hooks/cursor/mempal_precompact_hook_cursor.sh" } ] } }

Cursor 集成有三点与 Claude Code 显著不同,均可在源码中找到依据:

  1. sessionStart→ Wake Hook:Cursor 独有的"会话开始即召回"能力。Claude Code 的第三方 hooks 兼容层没有等价事件。mempal_wake_hook_cursor.sh 在会话启动时从workspace_roots[0]推断 wing(basename(workspace)归一化为[a-z0-9_-]),返回additional_context,让 AI 在回答任何涉及既往工作的问题前先mempalace_search+mempalace_diary_read(MCP 工具名与 mempalace/mcp_server.py 中实现一一核对)。
  2. followup_message默认开启:Cursor 的转写格式未公开,normalize.py没有 Cursor parser,因此后台挖掘只是best-effort,无法产出干净的逐字 drawers。真正承担"逐字捕获"的是默认开启的followup_message(引导 Agent 用mempalace_checkpoint一次调用完成去重归档 + 写日记)。这与 Claude Code hook 默认静默的策略相反——理由见 mempal_save_hook_cursor.sh 头注释:Cursor 默认关掉 followup 就等于默认零捕获。
  3. loop_limit: 1.pending标记:Cursor 的防循环信号是loop_count(等价于 Claude 的stop_hook_active),loop_limit: 1是纵深防御。而 preCompact 在 Cursor 里是只读观察型事件(仅支持user_message输出,不能阻断压缩),所以 preCompact hook 只能做同步挖掘 + 丢一个.pending标记文件,由下一次 stop hook 消费标记、强制触发一次保存提示(见 hooks/cursor/lib/common.sh)。

想回到 Claude 式"聊天窗口零打扰",可用MEMPAL_CURSOR_SILENT=1MEMPAL_VERBOSE=false关闭 followup。Cursor 的完整配置手册见 hooks/cursor/README.md 与渲染版 website/guide/cursor-hooks.md。

6.2 Codex CLI(OpenAI)

把同一套通用脚本挂到.codex/hooks.json

{ "Stop": [{ "type": "command", "command": "/absolute/path/to/hooks/mempal_save_hook.sh", "timeout": 30 }], "PreCompact": [{ "type": "command", "command": "/absolute/path/to/hooks/mempal_precompact_hook.sh", "timeout": 30 }] }

6.3 Google Antigravity

Antigravity 的接线格式(camelCase JSON、injectSteps[]输出)与事件名(StopPreInvocation)都是专用方言,集成代码独立维护在 hooks/antigravity/ 子目录。使用专用安装器:

bash hooks/antigravity/install.sh

该安装器把内容装到~/.gemini/config/plugins/mempalace/,注册 MCP 服务器、附带mempalaceskill,并接线 Stop + PreInvocation hooks。完整指南见 hooks/antigravity/README.md,对所用 Antigravity 各表面能力的审计见 hooks/antigravity/INVESTIGATION.md。由于 Antigravity 不暴露专用的会话结束事件(其生命周期钩子为 PreToolUse/PostToolUse/PreInvocation/PostInvocation/Stop,且 MemPalace 已通过 Stop 保存),该 harness 暂无 session-end 接线——clean-exit 保存统一走 harness 无关的mempalace hook run --hook session-end入口(hooks/README.md "Other harnesses" 一节)。

七、调试与故障排查

7.1 看日志

Save / PreCompact 每次触发都会追加一行到状态目录:

cat ~/.mempalace/hook_state/hook.log

典型输出:

[14:30:15] Session abc123: 12 exchanges, 12 since last save [14:35:22] Session abc123: 15 exchanges, 15 since last save [14:35:22] TRIGGERING SAVE at exchange 15 [14:40:01] Session abc123: 18 exchanges, 3 since last save

Cursor 系列则写到~/.mempalace/hook_state/cursor_hook.log,行格式为 ISO8601 时间戳 +event=+conv=,便于跨时区 grep。

7.2 常见故障定位

现象排查方向
hook 从不触发是否改了配置后没重启会话?Claude Code 只在会话启动时加载 hooks
Session unknown刷屏查看~/.mempalace/hook_state/last_input.loglast_python_err.log(解析失败时,脚本会 dump 至多 4 KB 原始载荷并chmod 600
GUI 启动下无法计数macOS GUI 启动路径不含你的 shell PATH → 显式export MEMPAL_PYTHON="/usr/bin/python3"(或你的 venv)
后台挖掘静默失败mempalace mine需在 PATH 上;用pipx/uv tool安装到全局,或把 venvbin/加入 hook PATH
状态目录无限膨胀Cursor 钩子带每日节流、默认 30 天 TTL 的 GC(cursor_last_sweep标记 +find -mtime),可通过MEMPAL_STATE_TTL_DAYS调整

7.3 成本与打扰

按文档口径,v3.1.0+ 的设计目标是零额外 token:Auto-mine 层在后台直接把原始工具输出落库,AI 不必在聊天里誊写内容;MEMPAL_VERBOSE=true的阻断式提示是可选的开发模式。早期版本让 AI 在聊天窗口写日记与抽屉内容,每个会话约额外耗费约 $1 的重传 token——这正是新架构把它变成默认静默的原因(hooks/README.md "Cost" 一节)。

八、小结

从本教程出发,你可以按图索骥完成三层落地:

  1. 接线:把 mempal_save_hook.sh 挂到Stop、mempal_precompact_hook.sh 挂到PreCompact、mempal_session_end_hook.sh 挂到SessionEnd,重启会话生效;
  2. 调参:用SAVE_INTERVAL控制保存节奏,用MEMPAL_DIR顺带挖掘项目文件,用MEMPAL_PYTHON修正解释器解析,用MEMPALACE_HOOKS_AUTO_SAVE=false随时静默;
  3. 回填与扩展:一次性执行 mempalace-mine 回填历史会话,再按需把同一套能力铺到 Cursor、Codex、Antigravity。

想进一步深挖,推荐继续阅读同仓库的 hooks/README.md(含流程图与技术细节)、website/guide/claude-code-retention.md(现网会话保护的快速检查清单)、hooks/cursor/README.md(Cursor 完整手册),以及核心实现 mempalace/hook_shell.py 与配套测试 tests/test_hooks_bash_compat.py、tests/test_save_hook_mines.py、tests/test_save_hook_verbose.py。多读几遍脚本里那些"为什么这样做"的长注释——它们本身就是一份非常诚实的工程笔记。

【免费下载链接】mempalaceThe best-benchmarked open-source AI memory system. And it's free.项目地址: https://gitcode.com/GitHub_Trending/me/mempalace

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 23:58:54

直播切片怎么做?从直播回放到短视频成片的完整流程清单

直播切片怎么做&#xff1f;从直播回放到短视频成片的完整流程清单 四个小时的直播回放躺在硬盘里&#xff0c;你记得第三个小时有一段效果炸了——弹幕刷屏、在线人数冲上峰值&#xff0c;但你不知道它在第几秒&#xff0c;只能拖进度条碰运气。拖了二十分钟终于找到&#xff…

作者头像 李华
网站建设 2026/9/8 23:58:32

2026最新亲测!盘点5款好用的降ai率工具(附3大免费降ai率技巧)

为了能找到靠谱的润色文章助手&#xff0c;我一开始试过不少免费降ai率工具。结果试下来才发现&#xff0c;有些免费工具只适合局部优化&#xff0c;有些用完后还需要花更多时间精力调整格式。 今天就把我折腾的半个月以来&#xff0c;压箱底的经验亮出来。本文分享3个实用的手…

作者头像 李华
网站建设 2026/9/8 23:57:36

ComfyUI 工作流导入导出完整指南:3 步保存、分享与复现

ComfyUI 工作流导入导出完整指南&#xff1a;3 步保存、分享与复现 【免费下载链接】ComfyUI The most powerful and modular diffusion model GUI, api and backend with a graph/nodes interface. 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI ComfyUI …

作者头像 李华
网站建设 2026/9/8 23:55:47

Python人脸识别系统实战:从OpenCV到face_recognition的完整指南

简介&#xff1a;一套基于Python的人脸识别系统完整工程&#xff0c;适合Python初学者、计算机视觉入门者以及需要快速搭建人脸识别Demo的开发者。资源覆盖从摄像头人脸采集、特征提取、数据库建库到实时识别比对的整套流程&#xff0c;并配有tkinter图形界面与运行说明文档&am…

作者头像 李华
网站建设 2026/9/8 23:51:47

业务分析师快速了解陌生项目:从认知清单到干系人地图的实操路径

接到通知去支援一个新项目&#xff0c;第一天坐进工位&#xff0c;面对一堆陌生的系统名称、业务术语、项目文档&#xff0c;开发催着要需求&#xff0c;业务方等着确认流程&#xff0c;直属领导问“你了解得怎么样了”。这种场景&#xff0c;做过BA的朋友多半都经历过。BA全称…

作者头像 李华