Learn Claude Code Playground 2026.07 – 2026.08 AI 产品经理 · 项目复盘

把「读懂 Agent」做成「用着看懂 Agent」

一个可以真实对话的 Agent 教学台。20 个版本,从「一个循环 + 一个 bash 工具」一路叠到带任务依赖图的完整内核;你一边使唤它干活,右侧「Harness 透视镜」一边实时拆开:哪一步是模型在决策,哪一步是工程代码在兜底。

开源项目github.com/everheart/learn-claude-code-playground

01一句话说清

业务是什么

把「AI 编程 Agent 到底是怎么造出来的」这件抽象的事,做成 20 个可以真实对话的版本:选 s01(一个循环 + 一个 bash 工具)和选 s12(带任务依赖图的完整内核)问同一个问题,你能亲眼看到工程层带来的能力差异。

它服务的是想搞懂 Agent 架构的开发者和产品经理——用「亲手用一遍」替代「读一遍文章」。

AI 输入
用户的自然语言任务(「建一个 Python 项目:写主程序、加测试、写 README」),加上工程层按当前阶段装配出来的上下文:运行时拼装的系统提示、该阶段才解锁的工具 schema、技能目录、跨会话记忆索引、以及可能已被压缩过的历史消息。
AI 输出
两层。对用户是文本回复 + 真实的工具调用——在沙箱里真的写文件、真的跑 bash。对产品是一条 29 类结构化事件流llm_request / permission / hook_fire / todo_update / subagent_start / skill_load / compact / memory_extract / task_event……这条事件流才是真正的核心交付物,前端把它渲染成「模型 vs 工程层」的可视教学。
解决什么
今天关于 Agent 的内容 99% 是「读」出来的——文章、架构图、录屏、脚本化演示。读完你知道「有子 Agent 这个东西」,但你答不上来:它到底省了多少上下文?权限闸门在真实对话里什么时候会触发?上下文压缩是在第几轮启动的?这个产品把「读」变成「用」,并且提供可控变量的对照实验——同一个问题并排跑两个阶段,差异一眼可见。
20课 / 版本
12课实时可交互
625行 单引擎
29类事件协议
5家模型厂商
207KB 分发包
02我为什么做

动机:我发现自己「懂了,但说不出来」

起点是我自己的一个竞品研究项目——横向扒 Claude Code、Codex 及其直接/间接竞品,坚持「装上、真用」而不是看官网材料。研究过程中我反复撞上同一个困难:关于 Agent 的知识几乎全部是「读」来的。

我读完了 shareAI-lab/learn-claude-code 那 20 课,能背出「Agent = 模型(Agency,训练出来的)+ Harness(工具/权限/上下文/记忆,工程造出来的)」,能画出架构图。但真要我说清「子 Agent 到底省了多少上下文」「权限闸门在什么条件下真的会拦住一条命令」,我说不出来。我掌握的是词汇,不是体感。

然后我去核对了上游自带的 Next.js 教学站。它做得很好:20 课文档、每课架构 SVG、逐版本 diff、时间线、分层视图,还有一个「模拟器」。但我把它的源码翻了一遍——在 web/src/componentsweb/src/apppackage.json 里搜 anthropic|api_key|openai零命中。那个「模拟器」的实现是 import("@/data/scenarios/s01.json"),把预先写死的步骤按顺序播出来。

结论很清楚:上游做了一本很好的教材,但缺一个实验台。教材可读,实验台可用、可测、可对照。我要做的就是这个实验台。

03做了什么
为什么
带来什么

九个关键决策

按「产品含量」而非时间排序。前两条是地基,决定了后面所有功能的成本。

架构

一个引擎 + 12 个累进开关,替代 20 个独立后端

做了
上游是 20 份互相独立的 code.py(s01 是 102 行,s20 是 1677 行)。我没有做 20 个后端,而是写了一个 625 行的插桩版引擎,外加一张累进开关表:permission: n≥3hooks: n≥4todo: n≥5subagent: n≥6skills: n≥7compaction: n≥8memory: n≥9prompt_assembly: n≥10error_recovery: n≥11task_system: n≥12。选 s07 就等于「开启前 7 个机制、关掉后 5 个」。
为什么
因为这 20 课的教学主张本身就是「循环不动,每课往循环周围挂一个机制」。如果我做 20 个独立服务,代码结构就在反驳这个主张;而且用户切换阶段时看到的差异会是「两份不同代码的差异」,不是「一个机制的有无」——教学上不成立。
价值
代码结构本身成了教具。用户从 s06 点到 s07,看到的差别恰好只有「技能加载」一项,这是干净的可控变量。副作用是「对比模式」几乎零成本——同一个引擎跑两个 stage 参数而已;维护成本也从 20 份降到 1 份。
本课新增 已累计启用 尚未解锁
累进开关矩阵:横轴为 20 课中实时可交互的 s01–s12,纵轴为 12 个工程机制。对角线即「每课加一个机制」——这张图就是引擎的全部架构。
协议

把工程层的内部动作,定义成一套事件协议

做了
引擎里 39 处埋点全都不 print、不直接写 UI,而是 yield 结构化事件,靠 yield from 逐层委托冒泡(主循环 → 工具分发 → 子 Agent / 压缩 / 权限,每一层都能实时吐事件),再经 SSE 推给前端。引擎吐 25 类,演示回放补 4 类,前端一套渲染器处理 29 类
为什么
教学产品的核心不是「答得对不对」,而是「过程看不看得见」。而工程层的价值恰恰在于它是隐形的——权限检查、上下文压缩、提示装配,用户在正常对话里完全感知不到。要让它可见,必须先把它结构化;如果只是把 stdout 打到页面上,那还是一个「看日志」的产品。
价值
一次定义、三处复用:实时对话、演示回放、对比模式全部走同一条协议、同一套渲染器。这是后面几个功能能低成本落地的根本原因。
范围

切一刀:s01–s12 实时真跑,s13–s20 脚本化回放

做了
明确把 20 课分成两段,前 12 课接真实模型、真实执行;后 8 课用上游自带的 scenarios 回放,并在左侧列表用「实时 / 演示」标签直接告诉用户
为什么
s13–s20 是后台任务、定时调度、多 Agent 组队、团队协议、自组织认领、worktree 隔离、MCP——全部涉及并发、时间跨度、多进程。在一次网页对话里真跑,要么让用户干等,要么必须伪造并发;用户既看不清,体验也差。承认能力边界,比假装全都能做更有产品价值。
价值
把有限工程量压在收益最高的 12 课上,同时后 8 课不缺席。关键手法是 demo.py 只做协议翻译——把 scenarios 转成和实时引擎完全相同的事件协议,所以用户看到的界面、透视镜、教学旁白完全一致,体验不割裂。
增长

「运行本课演示」从降级方案改成第一梯队入口

做了
没配 API key 时不报错,每一课都给一个「▶ 运行本课演示」按钮。后来又把这个按钮加到了已配 key 的实时阶段
为什么
第一版逻辑是「有 key 走实时、没 key 才给演示」,跑起来发现两个问题:(1)拿到分发包的人第一步就卡在申请 key,教学效果为零;(2)更意外的是,已配 key 的用户反而更尴尬——他得自己想提示词,面对空白输入框根本不知道该问什么才能看到本课机制。所以「演示」不该是降级,它是「一键看懂本课」的最短路径。
价值
首次体验门槛从「去申请一个 API key」降到零。这是典型的产品视角修正工程视角:工程上「有 key 走真路径、没 key 走假路径」很自然,产品上「新用户不知道该问什么」才是真瓶颈。
市场

面向国内用户做多厂商兼容,key 只存本地浏览器

做了
抽出一层走 Anthropic 兼容协议的客户端,内置 5 个厂商预设(智谱 GLM / Kimi / DeepSeek / MiniMax / Anthropic 官方),设置面板里选厂商就自动填好 model 和 base_url。key 存浏览器 localStorage,请求时随 body 带上,直连厂商、不落服务端
为什么
目标用户是国内学习者,要求人人有 Anthropic 官方 key 是个硬门槛。反过来,如果由分发者预置 key,分发者要承担所有人的调用费用、还要承担泄露风险——所以必须设计成「每人自带 key」。
价值
分发者零成本、零风险;使用者用手里已有的国产模型额度就能跑。这一条直接决定了这个产品能不能真的发给别人。细节上还踩过一个坑:兼容厂商用 x-api-key 认证,如果本机环境里存着 Anthropic 的 auth token 会串味导致鉴权失败,所以切到兼容 base_url 时要主动把那个环境变量清掉。
安全

真执行,但关进沙箱——并且不为安全牺牲教学

做了
每个「会话 + 阶段」一个独立工作目录;路径逃逸检查;硬拦截清单挡掉 rm -rf /sudomkfsdd if=、fork bomb;命中「潜在破坏性」清单则显示闸门触发的教学时刻但沙箱内放行,并明确标注「真实 Claude Code 会在此暂停等你确认」。Windows 上优先找 git-bash,让 unix 风格命令也能跑。
为什么
教 Agent 就必须真执行,假执行学不到东西;但真执行必须有边界。这里有个很微妙的取舍:s03 教的就是权限——如果网页版把所有危险操作都放行,这一课就失真了;如果全部拦死,用户又走不下去。
价值
最后的解法是「拦死真危险的、放行沙箱内的、但把闸门的判断过程显式展示出来,并说明真实产品在这里会停下等你确认」——安全和教学诚实性同时保住了。公网部署另给了 Docker 方案,并在文档里写明「会真实执行 bash,务必用容器跑、只发给信任的人、不要挂公网任人访问」。
交互

三栏 + 对比模式:熟悉的壳子,新增的价值

做了
左栏 20 课选择(带「实时/演示」标签和「+本课新增机制」),中栏 ChatGPT 式对话,右栏「Harness 透视镜」——机制芯片条 + 5 个常驻组件(计划清单、上下文占用条、子 Agent、已加载技能、系统提示装配、任务图)+ 事件流时间线。对比模式:同一问题并排跑两个阶段。
为什么
中栏刻意做成 ChatGPT 的样子,因为那是用户已经会的东西,认知负担为零;右栏才是新增的价值。用户不需要学新交互,只需要多看一眼右边。对比模式则是把「工程层有什么用」从「我讲给你听」变成「你自己看数据」。
价值
一个刻意的克制:对比模式下只有主列写透视镜,对照列只更新对话气泡。因为一个透视镜同时接两路事件会互相污染,读不出任何东西——宁可只完整展示一路。
内容

「试试看」字段:给例子,还要告诉你该看什么

做了
自建了一份 20 课 × 5 字段的中文教学层:一句中文格言、机制名、本课新增了什么、试试看、是否实时。
为什么
「试试看」是这里产品含量最高的一个字段——它不只是给个例子,而是给例子 + 告诉你观察什么。比如 s02 写的是:「让它『创建一个 hello.py 并写一个 greet 函数』。注意它用的是专用的 write_file,而不是 s01 里的 bash echo——工具越专用,模型用得越准。」没有后半句,用户跑完根本不知道自己刚看到了什么。
价值
这是把「技术仓库」变成「教学产品」的那一层。上游有英文的 keyInsight,但没有「你该输入什么、你该看什么」。前端还会自动从这段文字里正则抓出引号内的示例,点一下就填进输入框。
分发

三条分发路径:零构建、一键跑、可上云

做了
run.bat / run.sh 一键启动(自动建虚拟环境、装依赖、开浏览器);打包脚本产出 207 KB 干净 zip(剔除虚拟环境、沙箱、缓存、.env);Dockerfile + 部署文档覆盖三家云平台,镜像读 $PORT 以兼容平台注入。前端刻意做成免构建单页,整个项目不依赖 Node.js
为什么
目标用户是「想学 Agent 的人」,不一定是「能配环境的人」。教学产品如果第一步就卡在装工具链,内容再好也没人看得到。
价值
收件人只需装一次 Python,其余全自动。1227 行后端 + 785 行前端,压出来 207 KB。
04落地案例

五个有据可查的具体案例

按真实时间排序,每个都能在提交记录里对上。

2026-07-069b9e10765 文件 / 首次落地

案例一:一个引擎,还是二十个引擎

挑战
上游 20 份代码从 102 行长到 1677 行,彼此重复但又都不一样。最省事的做法是每课包一个 HTTP 端点——20 个入口。但这有三个问题:维护 20 份重复逻辑;用户切阶段看到的是「两份不同代码的差异」而非「一个机制的有无」,教学不成立;对比模式做不了。
怎么解
我反过来问了一句:「这 20 课到底在讲什么?」答案是「循环不动,每课往循环周围挂一个机制」。那正确的实现就应该长得像这句话——一个循环 + 一张累进开关表。于是把机制判断收敛成 12 个布尔开关加一份累计工具名单,引擎按开关决定走哪些分支。
结果
625 行一个引擎覆盖 12 课。切换阶段 = 翻开关;对比模式 = 同一引擎跑两个参数。
我的收获当实现方式和产品主张打架时,改实现,别改主张。这个决策的回报不在当时,而在后面每一个功能都变便宜了。
2026-07-06engine.py · 39 处埋点

案例二:怎么让「看不见的东西」看得见

挑战
这些机制发生在调用栈的不同深度:权限在工具分发之前、压缩在 LLM 调用之前、子 Agent 在工具分发里面又套了一层自己的完整循环。如果用回调或者事后收集,实时性和层级关系都会丢——用户看到的就不是「过程」,而是「结果的摘要」。
怎么解
把整条链路写成生成器,用 yield from 逐层委托冒泡:工具分发是生成器、子 Agent 是生成器、压缩流水线是生成器,最深处一次子 Agent 的工具调用也能实时冒到最外层的 SSE 流里。权限那里比较特殊——它既要吐事件、又要返回「允许/拒绝」的决策,所以用生成器的返回值把决策带出来。
再加一层
光吐「发生了什么」不够,还要吐「这意味着什么」。所以每个机制首次触发时,额外弹一条教学注释(机制名 + 中文格言 + 要点),并记下已触发过的机制去重——第一次讲道理,后面不啰嗦。这是把「日志」变成「教学」的关键一笔。
我的收获「可观测性」不是把内部状态倒出来,是按用户的理解顺序把它组织出来。同一份数据,加了「首次触发才解释」这个规则,才从工程调试信息变成教学内容。
2026-07-07009dbcc跨平台分发

案例三:Mac 上「双击打不开」——最隐蔽的一个坑

现象
我在 Windows 上打好 207 KB 的 zip 发给 Mac 用户,对方反馈「打不开、没反应」。这个描述离根因极远——可能是 Python 没装、端口被占、脚本报错闪退,都对得上「没反应」。
根因
Windows 的 NTFS 没有「Unix 可执行位」这个概念,所以 PowerShell 打出来的 zip 里 run.sh 一定不带 +x——不管源文件本身有没有设置过。在 Windows 端毫无影响(run.bat 双击就跑,不需要可执行位),所以我在本机怎么测都测不出来。但 Mac 用户按老习惯「把 run.sh 拖进终端回车」,等价于 ./run.sh,缺可执行位就报 permission denied,表现就是「打不开」。
怎么解
分两层。工程层:run.sh 补上可执行位并记进 git,让 git clone 的场景不受影响。产品层(更重要):我认清了「只要分发形式还是 Windows 打包 zip,这个可执行位就没法保证」——这是工具链的硬限制,修不掉。所以我改的是说明书:把 Mac/Linux 的首选启动写法从「拖进终端回车」改成 bash run.shbash 直接读文件内容执行,不依赖可执行位,两个平台都稳)。
我的收获工程师的本能是继续找「修 zip 权限位」的办法;产品的判断是——用户要的是「能跑起来」,不是「权限位正确」,那就把最稳的那条路径写成默认路径。我还把这个坑的成因、影响面、以及「为什么在 Windows 上永远测不出来」完整写进了分发说明,避免下一个人重踩。
2026-07-075234ad53 行 CSS

案例四:滚动条 bug——3 行 CSS 决定核心价值成不成立

现象
中间栏和右侧栏内容超过一屏时无法下拉,后面的内容直接看不到。
为什么是 P0
这个产品的价值全在右侧透视镜的事件流。而事件流天生是「越用越长」的。滚不动 = 用户跑完一个多步骤任务,恰好看不到最关键的那几条机制事件 = 核心价值直接失效。这不是 UI 瑕疵,是功能性缺陷。
根因与修复
布局容器只定义了 grid 的没定义;在 body{overflow:hidden} 之下,隐式 grid 行按内容高度撑开、直接溢出屏幕,于是各栏内部的 overflow-y:auto 根本不生效——父容器没有确定高度,子元素的滚动就无从计算。修复是给行加 minmax(0,1fr),并给三栏加 min-height:0。写 minmax(0,1fr) 而不是 1fr 是关键:grid 项默认 min-height:auto,不显式压到 0 就还是会被内容撑开。
我的收获教学类产品的「信息密度」和「容器约束」是一对天然矛盾——右侧要塞尽量多的事件才有教学价值,塞得多就必然溢出。凡是「越用越长」的面板,布局约束必须在设计阶段就定死,不能等内容长起来再补。
2026-08-24d27d691独立成库

案例五:拆成独立仓库,同一个坑又咬了一次

为什么做
这个项目原本是研究仓库下的一个子目录。它已经是能独立分发的完整产品,混在研究笔记里既不方便给别人看,也不方便单独迭代。
怎么做
git subtree split 把动过这个目录的 6 个提交抽出来、路径重写到仓库根,保留完整演进历史和作者信息,再推到独立仓库。
意外
拆完立刻发现 run.sh 又变成 CRLF 了。根因是外层仓库根目录的 .gitattributes 里有 *.sh text eol=lf 这条规则,但它在父仓库根、不在 app 目录里,所以没跟着 subtree 拆出来;本机 core.autocrlf=true,clone 时就把它转成了 CRLF——这正是案例三那个坑的另一条路径,这次的报错是 bad interpreter: /usr/bin/env bash^M
怎么收
.gitattributes 带进新仓库并重新 checkout 规范化;同时把原先靠外层仓库覆盖的忽略规则(.claude/.vscode/.DS_Store.env*)全部补齐——独立成库意味着所有隐式依赖都要显式化。
我的收获同一类问题在相隔七周后以另一种形态复现,说明它不是一次性 bug,而是只要分发链路里有 Windows 环节就会反复出现的结构性风险。分清「结构性」和「偶发」,是技术判断的分水岭——偶发的修一次就好,结构性的必须写进规则和文档。
05诚实划线

哪些是复用的,哪些是我做的

这个项目建立在一个优秀的开源教学仓库 shareAI-lab/learn-claude-code 之上,所以有必要先把边界划清楚——下面这张表可以对着两个仓库自行核对。而看清上游缺了什么,本身就是这个项目的起点。

复用自上游本项目新建
教学内容 20 课 code.py 源码本体、自动抽取的英文元数据、20 个脚本化场景、12 篇中文长文、4 个技能包 20 课 × 5 字段的中文教学层(格言 / 机制名 / 本课新增 / 试试看 / 是否实时)
运行内核 625 行插桩引擎、累进开关层、沙箱工具箱、多厂商模型封装、协议翻译层(1227 行后端)
交互 静态架构 SVG、逐版本 diff、脚本化模拟器(无模型调用) 三栏免构建单页、Harness 透视镜、29 类事件渲染器、对比模式(785 行前端)
分发 双平台一键启动脚本、207 KB 打包脚本、Dockerfile、部署文档

一句话概括贡献:上游做了「教材」,我做了「实验台」。教材可读;实验台可用、可测、可对照。

06关键判断

三个最能说明产品判断的取舍

九个决策里如果只挑三个,我会挑这三个——它们都不是技术选型,而是「先把问题定义对」。

  • 把演示回放也给已配 key 的用户。真瓶颈不是没有 key,而是不知道该问什么。这一步区分开的是「我以为的门槛」和「用户真实的门槛」。
  • Mac 可执行位:修不掉,就改用法。判断出这是工具链的硬限制之后,把目标从「实现正确」换回「能跑起来」——改的是说明书,而不是继续跟权限位较劲。
  • s01–s12 / s13–s20 切一刀。承认能力边界,同时用协议翻译让被砍掉的 8 课「不缺席」,而不是为它们另做一套体验。