AI

小林AI 编程课

请输入账号密码访问课程

课程资料仅供学员使用

AI

小林AI 编程课

工具基础 + L1/L2 大模型 + Agent 构建 + L3 定制

L0编程基础
终端 CLI Git 版本控制 Node 与 npm Python 基础 环境与路径
工具Vibe Coding
Vibe Coding 场景 Cursor 怎么用 Claude Code 怎么用 名词速查
L1基础认知
Token 是什么 Transformer 推理 Prompt 工程 结构化输出 幻觉与规避 采样参数
L2工程实践
Memory 策略 RAG 检索增强 成本计算器 Agent 架构全景 LLM 协议与接入 从 0 搭建 Agent 渐进融入扩展
L3Cursor 定制
Plugins 生态概览 Rules Skills Subagents Hooks MCP
Hands-on Course · 2026 · 独立 HTML

Vibe Coding:用人话写代码,AI 帮你动手

Vibe Coding = 用自然语言描述「想要什么」,AI Agent 负责读代码、改文件、跑命令。 重点搞清:什么场景用什么工具、工具主要帮你干什么、怎么简单上手。

Vibe Coding 场景地图:什么情况下用什么?

核心循环:你说人话 → Agent 改代码 / 跑命令 → 你看结果 → 再说下一句。 下面按「你想干嘛」选工具,不用全学,用到再查。

你想干嘛用什么工具最简上手
从零做网页 / AppCursor打开项目 → Cmd+I Agent → 说「做个登录页」→ 看 diff 点 Accept
改现有项目、调 UICursor@file 引用文件 → 说「把按钮改成红色」→ Accept
大功能怕 AI 乱改Cursor Plan ModeShift+Tab 切 Plan → 确认计划 → 点 Build
远程服务器 / 没界面Claude CodeSSH 进服务器 → claude → 说任务
修构建报错、跑脚本Claude Codeclaude "fix build error" 或会话里粘贴报错
Git 提交、开 PR两者都行说「帮我 commit,message 用中文」→ 自己看 git status 再确认
写 AI 脚本 / 调 APICursor 或 Claude Code说「写个 Python 调 MiniMax API,Key 放 .env」
项目跑不起来你 + Agent自己跑 npm install → npm run dev,把报错贴给 Agent
L0 基础Vibe Coding 里主要干嘛你只需要会
CLI 终端Agent 替你跑命令,你看输出对不对cd · ls · Ctrl+C 停服务
Git存档、回滚、看 AI 改了什么git status · git diff
npm装依赖、启动项目、跑测试npm install · npm run dev
PythonAI 脚本、数据处理pip install -r requirements.txt · python3 script.py
.env存 API Key,别泄露复制 .env.example → 填 Key → 别 commit
L0 · 编程基础

0. 终端 CLI 是什么?

CLI = Command Line Interface,用「打字下命令」代替「点鼠标」。Vibe Coding 里 Agent 大量在终端跑命令——你看得懂输出就行。

⚡ Vibe Coding 最少知识
  • 什么时候用到:Agent 在后台跑命令,终端输出是它判断「成没成」的依据
  • 主要干嘛:进项目目录、装依赖、启动服务、看报错
  • 你要会:cd 项目路径 · ls 看文件 · Ctrl+C 停卡住的程序 · 看懂「成功 / 报错」两行字就够
🤖 AI 场景关联 · 为什么 LLM 偏爱 CLI?

大模型和 CLI 是天然搭档,这不是巧合,而是结构决定的:

  • 指令明确、可验证:npm run test 成功或失败,Agent 立刻知道下一步——GUI 点按钮很难描述「点哪个、有没有生效」
  • 输出结构化:终端返回纯文本/退出码(0=成功),模型容易解析;比截图、界面状态可靠得多
  • 可脚本化、可重复:同一条命令跑 100 次结果一致,适合 Agent 循环「执行→看结果→修正」
  • Claude Code 的本质就是 CLI Agent:它在终端里替你跑 git、npm、cat、rm,你用人话下任务,它翻译成明确命令
  • Cursor Agent 同理:内置终端面板,Agent 自动执行 shell 命令并读 stdout/stderr 决定下一步

课堂记忆点:学 CLI 不是学「老程序员习惯」,而是学和 AI 协作的共同语言——你说「帮我启动项目」,Agent 实际执行的是 npm run dev。

为什么要学终端?

类比:终端就像「直接跟电脑说话」。GUI 是菜单点菜,CLI 是直接报菜名——更快、可自动化、AI Agent 默认用这个方式操作文件和 Git。

Mac 打开:Cmd + Space 搜「终端 / Terminal」。Windows 打开:搜「PowerShell」或「Windows Terminal」。

pwdPrint Working Directory — 我在哪个文件夹?
例:输出 /Users/nic/projects/my-app
lsList — 列出当前目录文件(Mac/Linux)
Windows 用 dir。加 ls -la 看隐藏文件和详情
cd 路径Change Directory — 进入某个文件夹
cd .. 返回上一级 · cd ~ 回到家目录
mkdir 名字创建文件夹。例:mkdir my-project
cat 文件查看文件内容(小文件)。例:cat README.md
cp / mv复制 / 移动(改名)文件。例:mv old.txt new.txt
rm 文件删除文件。⚠️ 没有回收站,删了找不回来!
删文件夹:rm -rf 文件夹名(极度危险,Claude Code 有时会问你能不能执行)
clear清屏。或 Ctrl+L
↑ 方向键调出上一条命令,不用重复打
Ctrl + C强制中断正在运行的程序(比如卡住的 dev server)
🧪 模拟:你在项目里常用的命令序列
$ cd ~/projects/my-app # 进入项目
$ ls # 看看有什么文件
$ npm install # 安装依赖
$ npm run dev # 启动开发服务器
点击步骤按钮,模拟终端输出…
L0 · 编程基础

1. Git 版本控制

Git 是代码的「时光机」。Vibe Coding 里 Agent 会帮你改很多文件——Git 让你能看清改了什么、改坏了能回滚。

⚡ Vibe Coding 最少知识
  • 什么时候用到:AI 改完一批文件后,你要存档;改错了要回滚;协作时要 push
  • 主要干嘛:记录每次改动、对比 diff、安全网
  • 你要会:git status 看改了啥 · git diff 看具体改动 · 让 Agent 帮你 commit 前先自己扫一眼
🤖 AI 场景关联 · Git 是 Agent 的「安全网」
  • Claude Code 常见能力:自动建分支、commit、甚至开 PR——但你要能看懂 git status 输出,才知道它改了什么
  • Agent 改代码前的 checkpoint:大改之前先 commit,改坏了 git checkout . 一键回滚
  • 给 AI 提供上下文:git diff 的输出可以直接贴给模型:「这是本次改动,帮我 review」
  • Cursor / Claude Code 读历史:git log 帮助 Agent 理解「这个功能是谁、什么时候、为什么加的」
  • 权限边界:在 settings 里限制 Agent 能否 git push——push 是不可逆的远程操作,需要人确认

核心概念(先搞懂名词)

仓库 Repository项目的完整历史记录,通常存在 .git 隐藏文件夹里
工作区 Working Tree你正在编辑的文件(还没保存到 Git 历史)
暂存区 Stage用 git add 选中的、准备提交的文件
提交 Commit一次「存档点」,有说明 message,永久记录在历史里
分支 Branch平行时间线。主分支通常叫 main,新功能在 feature/xxx 分支开发
远程 RemoteGitHub / GitLab 上的云端副本,团队共享用

日常必会命令

git status看哪些文件改了、哪些还没提交。最常用,遇事不决先 status
git add .把所有改动放进暂存区。单个文件:git add src/App.tsx
git commit -m "说明"提交存档。说明要写清楚「为什么改」,例:git commit -m "fix: 修复登录按钮样式"
git log --oneline看提交历史(简洁版)
git diff看具体改了什么(红色删、绿色加)
git branch列出分支。新建:git checkout -b feature/login
git pull从远程拉最新代码到本地
git push把本地提交推到远程。首次:git push -u origin HEAD
git clone URL把远程仓库下载到本地。例:从 GitHub 克隆项目
标准工作流:改代码 → git status 确认 → git add . → git commit -m "..." → git push
Claude Code 可以帮你执行这些,但你要看得懂它在做什么,尤其是 push 和 rm 操作。
🧪 Playground:模拟 Agent 改代码后的 Git 流程

观察文件在工作区 → 暂存区 → 提交历史之间怎么移动:

工作区 Working Tree
(干净)
暂存区 Stage
(空)
提交历史 Commits
a1b2c3d init: project setup
点击按钮,模拟 Vibe Coding 里 Agent 改完代码后的 Git 操作…
L0 · 编程基础

2. Node.js 与 npm

Node 让 JavaScript 能在电脑上跑;npm 装依赖、跑脚本。大部分 Web 项目和 Claude Code 本身都靠它。

⚡ Vibe Coding 最少知识
  • 什么时候用到:克隆项目后第一次跑、Agent 改完要验证、安装新库
  • 主要干嘛:读 package.json 知道怎么启动,把依赖装进 node_modules
  • 你要会:npm install → npm run dev;报错整段复制给 Agent
🤖 AI 场景关联 · npm 是 Agent 的「项目说明书执行器」
  • Agent 启动项目的标准动作:读 package.json → 跑 npm install → 跑 npm run dev/test/build
  • Claude Code 安装方式:本身就是 npm install -g @anthropic-ai/claude-code,Node 是 AI 工具链底座
  • 验证 Agent 成果:你说「改完跑一下测试」,Agent 执行 npm test,看 exit code 和输出判断对错
  • Cursor TDD 工作流:先写测试 → Agent 跑 npm test 看失败 → 写实现 → 再跑直到通过
  • 报错排查:npm install 失败、依赖冲突——Agent 会读 stderr 并尝试 fix,你要看得懂它在装什么

安装与验证

$ node -v # 查看 Node 版本,需要 18+
$ npm -v # 查看 npm 版本
npm install读取 package.json,安装项目所有依赖到 node_modules/
npm install 包名安装单个包。例:npm install axios
npm install -g 包名全局安装(全电脑可用)。例:npm install -g @anthropic-ai/claude-code
npm run dev运行 package.json 里 scripts 定义的命令。每个项目不同,常见还有 build test lint
npm init初始化新项目,生成 package.json
npx 工具不全局安装,临时运行。例:npx create-vite@latest my-app
📦 package.json 是什么?

项目的「说明书」:项目名称、依赖列表、可运行脚本。AI 工具读这个文件就知道用什么框架、怎么启动项目。

{ "name": "my-app", "scripts": { "dev": "vite", "build": "vite build" }, "dependencies": { "react": "^19.0.0" } }
🔒 package-lock.json 是什么?

锁定每个依赖的精确版本,保证团队装出来的包一模一样。一般要提交到 Git,不要删。

🧪 Playground:模拟 npm 项目启动流程
① 读 package.json
② npm install
③ npm run dev
④ npm test
Agent 接手新项目时的标准 npm 流程…
L0 · 编程基础

3. Python 基础(AI 方向常遇到)

写 AI 脚本、调 API、做数据处理时常用。Vibe Coding 里你说需求,Agent 写 .py 文件并帮你装依赖。

⚡ Vibe Coding 最少知识
  • 什么时候用到:调 LLM API、批量处理文件、RAG 脚本、Jupyter 实验
  • 主要干嘛:AI 生态示例多、写脚本快
  • 你要会:python3 script.py 运行 · pip install -r requirements.txt 装依赖 · 有 venv 就先 source .venv/bin/activate
🤖 AI 场景关联 · Python 是 AI 生态的「母语之一」
  • LLM 应用开发主流语言:LangChain、LlamaIndex、OpenAI SDK 示例大量是 Python——Agent 写 AI 脚本时常用
  • 数据处理 / RAG 脚本:文档切块、embedding、批量调 API,Python 一行顶 JS 十行
  • venv 防 Agent 搞乱环境:Agent 装包前先 source .venv/bin/activate,避免污染全局 Python
  • Claude Code / Cursor 都会写 Python:你说「写个脚本调 MiniMax API」,它创建 .py + requirements.txt + venv
  • Jupyter Notebook:AI 教学、实验性 Prompt 调试常用,Cursor 也能直接编辑 .ipynb
python3 -v查看 Python 版本(Mac 通常用 python3,不是 python)
pip install 包名安装 Python 库。例:pip install openai
pip install -r requirements.txt批量安装(类似 npm install)
python3 script.py运行 Python 脚本
python3 -m venv .venv创建虚拟环境(隔离项目依赖,避免版本冲突)
source .venv/bin/activate激活虚拟环境(Mac/Linux)。Windows:.venv\Scripts\activate
venv 类比:每个项目一个独立「工具箱」,A 项目用 openai 1.0,B 项目用 openai 2.0,互不干扰。 AI Agent 写 Python 时经常会自动创建 venv。
📄 requirements.txt

Python 项目的依赖清单,相当于 npm 的 package.json dependencies 部分:

openai>=1.0.0 langchain>=0.1.0 python-dotenv>=1.0.0
🧪 Playground:模拟 Python AI 脚本环境搭建
① 创建 venv
② activate
③ pip install
④ 运行脚本
Agent 写 Python AI 脚本时的典型命令序列…
L0 · 编程基础

4. 环境变量、路径与配置文件

API Key 不能写死在代码里。Vibe Coding 里 Agent 会读 .env 调模型——别把 Key 贴进对话或 commit 到 Git。

⚡ Vibe Coding 最少知识
  • 什么时候用到:项目要调 OpenAI / MiniMax 等 API;多人协作要统一配置
  • 主要干嘛:密钥抽屉——代码里写 process.env.KEY,值在 .env 里
  • 你要会:复制 .env.example 为 .env → 填 Key → 确认 .gitignore 里有 .env
🤖 AI 场景关联 · 环境变量是 Agent 的「密钥抽屉」
  • API Key 不进 Prompt、不进代码:ANTHROPIC_API_KEY 放 .env,Claude Code / 你的脚本自动读取——避免 Key 泄露进 Git 或对话记录
  • Agent 读 .env.example 知道要配什么:CLAUDE.md 里写「复制 .env.example 为 .env.local」,Agent 能引导新成员 onboarding
  • .gitignore 是安全护栏:Agent 有时会建议 commit 文件——你要确认 .env、node_modules 已被 ignore
  • 多环境切换:.env.development / .env.production,Agent 部署时读对应变量
  • 路径问题 Agent 常踩坑:相对路径 vs 绝对路径——CLAUDE.md 里写清楚项目根目录和常用路径,减少 Agent 找错文件
环境变量操作系统级别的「全局设置」。例:ANTHROPIC_API_KEY=sk-xxx 告诉 Claude Code 你的密钥
.env 文件项目根目录的密钥配置文件。格式:KEY=value 一行一个。永远不要提交到 Git!
.env.example示例模板(不含真实密钥),提交到 Git 告诉队友需要配哪些变量
.gitignore告诉 Git 哪些文件不要跟踪。通常包含 .env node_modules/ .venv/
绝对路径从根目录写全:/Users/nic/projects/app(Mac)或 C:\Users\nic\app(Windows)
相对路径从当前位置算:./src/App.tsx(当前目录下)· ../(上一级)
~用户家目录的简写。Mac 上 ~ = /Users/你的用户名
🧪 .env 文件示例(AI 项目常见)
# .env — 不要提交到 Git! ANTHROPIC_API_KEY=sk-ant-xxxxxxxx OPENAI_API_KEY=sk-xxxxxxxx MINIMAX_API_KEY=sk-cp-xxxxxxxx DATABASE_URL=postgresql://localhost:5432/mydb
🧪 Playground:.env 会不会被 commit?

模拟 Agent 执行 git add . 时,检查 .gitignore 是否保护了密钥:

📁 .gitignore 内容
📋 git status 预览
勾选 .gitignore 后点「模拟 git add .」
Vibe Coding 安全必查:commit 前确认 .env 被 ignore…
工具 · Vibe Coding

什么是 Vibe Coding?

用自然语言描述意图,AI Agent 负责写代码、改文件、跑命令。你是「产品经理 + 验收员」,不是逐行敲代码的人。

一句话:传统编程 = 你写语法;Vibe Coding = 你说「要什么」,Agent 写语法,你在 IDE 里看 diff、点 Accept 或说「不对,改成 xxx」。

典型工作流(5 步)

1
说目标

「给登录页加个忘记密码链接」「修 npm run build 报错」——说结果,不说怎么写代码。

2
给上下文

Cursor 用 @file 指定文件;Claude Code 会自动读项目里的 CLAUDE.md 和当前目录。

3
Agent 动手

搜索代码 → 改文件 → 跑 npm test / npm run dev → 看终端输出决定下一步。

4
你验收

浏览器里点一点、看 diff、跑几个用例。不对就继续说:「按钮太靠左了」「报错还在」。

5
存档

git status 扫一眼 → 让 Agent commit 或自己提交。大改前先 commit 当安全网。

Cursor vs Claude Code:怎么选?

对比CursorClaude Code
长什么样带 AI 的代码编辑器(像 VS Code)终端里的对话 Agent
最适合做界面、改多文件、课堂演示、看 diffSSH 远程、纯命令行、脚本自动化、修构建
你怎么用打字聊天 + 点 Accept/Reject终端打字,Agent 自己跑 bash
入门门槛更低——有可视化界面稍高——要习惯终端
💬 怎么说才好用?(Prompt 最小模板)
【做什么】给设置页加一个深色模式开关 【约束】用现有 Tailwind,别加新 UI 库 【验收】切换后整页颜色要变,偏好存 localStorage 【参考】@SettingsPage.tsx
🧪 Playground:Vibe Coding 五步循环

点击每一步,看 Agent 协作循环怎么转:

① 说目标
② 给上下文
③ Agent 动手
④ 你验收
⑤ 存档 Git
点「开始循环」模拟一次完整的 Vibe Coding 任务…
工具 · Cursor

Cursor:Vibe Coding 主战场

在 IDE 里用人话指挥 Agent 改代码。适合从零做项目、改 UI、课堂演示——看得见 diff,点一下就能接受或拒绝。

什么场景用 Cursor?

场景主要干嘛最简用法
快速改一段代码选中代码,局部修改选中 → Cmd+K → 说「加 error handling」
问问题 / 讨论方案理解代码,不直接改Cmd+L 开 Chat → 「这个函数干什么用的?」
让 AI 自主改项目读文件、改多文件、跑终端Cmd+I Agent → 描述任务 → 看 diff Accept
大功能怕改乱先出计划,你确认再动手Agent 里 Shift+Tab 切 Plan → 改计划 → Build
AI 老犯同样的错持久化项目规范写 .cursor/rules/:「commit 用中文」「别 force push」
项目太大,AI 找错文件手动指定上下文对话里 @file 或 @codebase

3 分钟上手

1
打开项目文件夹

File → Open Folder,选你的项目根目录(有 package.json 那层)。

2
开 Agent

Cmd+I(Mac)或 Ctrl+I(Windows),输入:「读一下项目结构,告诉我入口文件在哪」——先让 AI 熟悉代码库。

3
下第一个任务

例:「给首页加一个欢迎 banner,样式跟现有页面一致」。Agent 改完会显示 diff,绿色是新增、红色是删除,点 Accept 接受。

快捷键速查(只记这 6 个)

Cmd+KInline Edit — 选中代码,快速改当前片段
Cmd+LChat — 问问题、讨论,不一定改代码
Cmd+IAgent — 自主读文件、改代码、跑终端(Vibe Coding 主力)
Shift+TabAgent 内切换 Plan Mode(大任务先用这个)
@file对话里引用某个文件当上下文
@codebase让 Agent 搜索整个代码库
Vibe Coding 心法:任务拆小、说清验收标准、大改用 Plan Mode、改完自己点两下页面验证。 Agent 不是魔法——你说得越具体,它越不乱改。

进阶:把 Agent 从「通用助手」变成「团队定制工作流」→ L3 · Cursor 定制扩展 (Plugins / Rules / Skills / Subagents / Hooks / MCP)

🧪 Playground:Cursor Agent 改代码

模拟 Cmd+I Agent 收到任务 → 出 diff → 你 Accept 的全过程:

💬 Agent 对话
等待任务…
📝 Diff 预览 · SettingsPage.tsx
(暂无改动)
工具 · Claude Code

Claude Code:终端里的 Vibe Coding

没有图形界面,纯终端 Agent。适合SSH 远程服务器、修构建报错、跑脚本和 Git——你说任务,它在 bash 里闭环执行。

什么场景用 Claude Code?

场景主要干嘛最简用法
本地项目日常开发和 Cursor 类似,但在终端里cd 项目 → claude → 说任务
SSH 远程 / 云服务器没有 IDE,只有终端SSH 登录 → claude → 「部署并重启 nginx」
构建 / 测试失败读 stderr,改代码,再跑粘贴报错 → 「fix this build error」
Git 操作commit、建分支、开 PR「帮我 commit,message 写清楚改了什么」
复杂任务怕乱改先列计划等你批准会话里输入 /plan
对话太长、变慢变贵压缩历史省 Token/compact
一次性任务问一句答一句,不进交互claude -p "解释 src/auth.ts"

3 分钟上手

安装(只需一次)
$ npm install -g @anthropic-ai/claude-code
$ cd ~/projects/my-app
$ claude # 首次浏览器登录
1
进项目目录

cd 到项目根(和 Cursor 打开的是同一文件夹)。

2
写 CLAUDE.md(推荐)

项目根放一份「AI 说明书」:技术栈、怎么启动、编码规范。每次 claude 启动自动读,不用重复说。

3
说任务,看它跑

例:「跑 npm test,有失败就修到全过」。Agent 会自己执行命令,问你权限时看清楚再批。

会话里常用命令(只记这 5 个)

/plan先分析、列计划,等你批准再执行(大任务必用)
/compact对话太长时压缩历史,省 Token
/clear清空对话,换一个新任务
/cost看当前会话花了多少 Token
exit退出 Claude Code
📄 CLAUDE.md 示例(复制改改就能用)
# 项目说明 - 技术栈:React 19 + TypeScript + Vite + Tailwind - 启动:npm run dev(端口 1420) - 规范:函数组件 + Tailwind,不引入新 UI 库 - 测试:npm run test - Git:commit 用中文,不 force push main
和 Cursor 怎么配合? Cursor 做界面、看 diff;Claude Code 跑脚本、SSH 部署、批量 Git。 同一个项目可以两边都用——CLAUDE.md 和 Cursor Rules 写清楚规范,Agent 行为就一致。
🧪 Playground:Claude Code 终端 Agent

模拟 Claude Code 收到任务后,在终端里自动跑命令的闭环:

$ claude
# 等待任务…
附录

名词与工具速查表

Vibe Coding 课堂常遇到的术语,支持搜索过滤。

搜索术语时,留意每个词在 Agent 工作流里出现在哪一环。

── 以下进入 L1 大模型基础认知 ──
Hands-on Course · 2026

大模型基础:从「会说话」到「能干活」

这节课用大白话 + 动手实验,带你理解大模型(LLM)的核心概念。 涵盖 Token、Prompt、幻觉、采样参数等 L1 主题,以及 Memory、RAG 等 L2 工程实践——理解这些,你就知道 Vibe Coding 里 Agent「为什么胡说、怎么调、怎么防」。

L1 · 基础认知

1. Token 是什么?

模型不读「字」,它读的是 Token——一种切分后的小片段。

🤖 AI 场景关联 · Token 决定 Agent 能「看」多少、花多少钱
  • 上下文窗口 = Agent 的工作台面:CLAUDE.md + 打开的文件 + 对话历史 + 检索结果,全部占 Token,超出就「失忆」或截断
  • 代码库越大,越需要 RAG/@codebase:不可能把整个 repo 塞进 Prompt,要靠检索只送相关片段(见 L2 RAG)
  • /compact 和「新对话」:Claude Code 的 /compact 是主动压缩短期记忆;Cursor 开新 Chat 是清空当前会话上下文
  • 成本直接相关:Agent 每次读大文件、跑长对话都在烧 Token——学会精简 Prompt 和 CLAUDE.md 能省钱
  • 思考 Token(reasoning):MiniMax M2.7 等模型「想」的过程也计费,回答短不代表便宜

一句话解释

类比:Token 就像乐高积木。模型把你说的话拆成一块块积木(Token), 再一块块拼出回答。中文通常 1 个字 ≈ 1~2 个 Token,英文大约 4 个字母 ≈ 1 个 Token。

为什么要关心 Token?因为 API 按 Token 收费,而且模型有上下文窗口上限(比如 128K Token ≈ 一本中等长度的小说)。

🔍 深入理解:上下文窗口 Context Window

模型一次能「看到」的最大 Token 数。包括:你的 system prompt + 历史对话 + 检索到的文档 + 它的回答。超出会被截断或报错。

  • Claude Code:最高约 100 万 Token 代码库上下文
  • MiniMax M2.7:204,800 Token(约 20 万字)
  • 对话太长时:Claude Code 用 /compact 压缩;Cursor 可开新对话
💰 Token 与成本的关系

输入 Token 和输出 Token 分开计费。输出通常更贵。M2.7-highspeed 有「思考 Token」(reasoning tokens),也会计入账单——这就是为什么有时模型「想很久」但回答很短,费用却不低。

🧪 交互实验:Token 切分器

📝 小测验:同样 100 个字符,哪种语言通常消耗更多 Token?

A. 纯英文
B. 纯中文
C. 一样多
L1 · 基础认知

2. Transformer 与推理原理

Token 切完只是第一步——模型用向量 + Transformer理解上下文,再逐个预测下一个 Token。搞懂这条链路,后面的采样、幻觉、RAG 向量都有根了。

🤖 AI 场景关联 · 推理链路决定 Agent「怎么思考、怎么接话」
  • 不是查数据库:每次生成都是「读上下文 → 算概率 → 抽一个词 → 拼上去 → 再算」的循环
  • Embedding 两处用途:模型内部把 Token 变向量做理解;RAG 把文档变向量做检索——概念相同,用途不同
  • 上下文窗口限制:Transformer 要对所有 Token 做 Attention,太长算不动也塞不下
  • Tool Use / Agent:在「接龙预测」之上,产品层让模型输出结构化工具调用——本质仍是 Transformer 输出 logits,只是约束了格式

从文字到下一个 Token:全链路

类比:Transformer 像一条流水线——原材料是 Token,每站加工一层理解,最后一站「猜下一个词该是什么」,猜完拼到句尾,整条线再跑一遍。
① 分词
Token IDs
② Embedding
Token → 向量
③ Transformer ×N
Self-Attention
④ 输出头
→ logits
⑤ 采样
temperature
⑥ 拼回上下文
循环
阶段输入输出你在工程里关心的
分词 Tokenize文本字符串整数 ID 序列Token 数 = 计费单位
Embedding 查表每个 Token ID高维向量(如 4096 维)语义相近的词,向量距离近
Transformer 层向量序列融合上下文后的向量层数越多,抽象理解越深
LM Head 输出头最后一个位置向量词表大小维的 logits(原始分数)每个候选 Token 一个分
Softmax + 采样logits选中 1 个 Tokentemperature / top_p 在这里生效(见第 6 节)

Transformer 核心:Self-Attention 在干什么?

不用怕公式——抓住直觉就够:每个 Token 都会「看一遍」上下文里所有 Token,按相关程度加权吸收信息。

🔑 三个角色:Q / K / V
Query 查询「我现在想找什么信息?」——当前 Token 发出的提问
Key 键「我这边有什么标签?」——每个 Token 可被匹配的索引
Value 值「我实际携带的内容」——被加权汇总的信息

Attention 分数 = Query 和 Key 的相似度 → Softmax 变权重 → 对 Value 加权求和。多头 Attention(Multi-Head)= 多组 Q/K/V 并行,从不同角度理解同一句话。

🏗️ 一层 Transformer Block ≈ 两步
  1. Self-Attention:Token 之间互相交流,「import」能关联到「react」,「函数」能关联到「return」
  2. Feed-Forward(FFN):每个 Token 向量单独过一个小网络,做非线性变换

现代 LLM 堆叠几十到上百层(如 32/64/80 层)。推理(inference) = 输入固定上下文,前向计算一次 logits;训练(training) = 用海量文本反复调整权重——你调 API 用的是已经训好的权重,不会再在线学习。

🧪 Playground A:向量 Embedding 与语义距离

Embedding 把词变成高维向量。下面投影到 2D 平面示意——语义相近的词会聚在一起(真实模型通常是上千维):

语义轴 Y → → 语义轴 X
点击两个词,再点「计算相似度」。RAG 检索就是用同样思路:问题向量 ↔ 文档向量,距离近 = 语义相关。
🧪 Playground B:逐步模拟「预测下一个 Token」

上下文:import React from —— 点「下一步」看 Transformer 推理链路怎么选出下一个词:

① 分词
② Embedding
③ Transformer
④ logits
⑤ 采样
⑥ 拼接
当前上下文(已生成 Token)
📊 候选 Token logits(简化)
📝 推理日志
点「下一步」开始…
🔗 和后面章节的关系
  • 第 6 节 采样参数:作用在 logits → 概率 → 选 Token 这一步
  • 第 5 节 幻觉:模型只是在接龙猜词,不是在验证事实——链路里没有任何「真理检查器」
  • 第 8 节 RAG:用 Embedding 在向量库里检索,把结果塞进 Transformer 的输入上下文
L1 · 基础认知

3. Prompt 工程

同样的问题,不同的问法,回答质量天差地别。

🤖 AI 场景关联 · Prompt 是你和 Agent 的「施工图纸」
  • System Prompt = CLAUDE.md / Rules:一次写好,每次会话自动加载,相当于给 Agent 定人设和规矩
  • User Prompt 要可验证:别说「优化代码」,说「跑 npm test 直到全绿」——Agent 需要明确的成功标准(exit code 0)
  • 多轮对话 = messages 数组:每一轮 user/assistant 都占 Token,废话越多 Memory 压力越大
  • Cursor @ 引用 = 精准 Prompt:手动告诉 Agent「只看这几个文件」,比让它全库搜索更准、更省 Token
  • TDD 套路:Prompt 里写「先写 failing test,再写实现,test 过才算完」——给 Agent 明确的完成定义

三条消息结构

每次调用模型,本质上是在发一组「消息」:

system → 你是 Python 老师,用简单例子解释概念
user → 什么是列表推导式?
assistant → (模型的回答)
  • System:设定角色和规则(「你是谁、怎么回答」)
  • User:用户的问题
  • Assistant:模型的历史回答(多轮对话靠它)
🧪 交互实验:好 Prompt vs 烂 Prompt

点击按钮,看看同样的任务,不同 Prompt 会得到什么效果:

你发送的 Prompt
点击上方按钮开始
模型可能的回答(模拟)
—
好 Prompt 公式:角色 + 任务 + 格式 + 约束 + 示例(可选)
例:「你是资深产品经理。用 3 个 bullet 对比 RAG 和微调。每点不超过 30 字。不要废话。」
📋 Cursor / Claude Code 里的 Prompt 技巧
  • 给上下文:在 Cursor 里用 @file 引用文件;Claude Code 会自动读 CLAUDE.md 和当前目录
  • 分步骤:大任务拆成小步,每步可验证。原则:「Start with a plan」
  • 明确约束:「只改 src/ 下的文件」「不要动 package.json」「用中文 commit」
  • 要它自查:「改完后 run npm test,失败就修到通过为止」
  • Few-shot:给一个输入输出示例,模型会模仿格式
⚠️ 常见 Prompt 翻车
  • 太模糊:「优化一下代码」→ 改成「优化 src/utils.ts 的 tokenize 函数,减少循环次数」
  • 一次塞太多:「重构 + 加测试 + 写文档 + 部署」→ 拆成 4 个独立任务
  • 没给验证标准:加上「完成后 npm run build 必须通过」
L1 · 基础认知

4. 结构化输出

让模型输出程序能直接用的 JSON,而不是自由发挥的散文。

🤖 AI 场景关联 · 结构化输出 = Agent 能「动手」的前提
  • Tool Use 就是结构化输出:Agent 不是输出散文,而是输出 {"tool":"Edit","file":"..."},程序解析后执行——L1 和 Agent 是一回事
  • 为什么不用纯文本:「把第 3 行改成 xxx」模型可能数错行;JSON Schema 约束字段,程序可靠解析
  • MCP 工具调用:查数据库、发 Slack 消息,都靠结构化 JSON,不是让模型「描述一下要做什么」
  • Strict Mode 在生产环境:支付、权限类操作必须 100% 符合 schema,否则拒绝执行而非瞎猜
  • 你看到的 diff 界面:Cursor 把 Agent 的结构化 Edit 操作渲染成可视化对比,底层仍是 Tool Use

为什么需要结构化?

程序看不懂「我觉得这个产品不错,功能挺全的,价格还行吧……」

但程序能直接解析:

{ "name": "Claude Code", "score": 9, "tags": ["Agent", "CLI"] }
🧪 交互实验:自由文本 vs JSON Schema
自由文本输出
点击执行
JSON Schema 输出
点击执行
  • JSON Schema:给模型一张「表格」,规定字段名和类型
  • Strict Mode:强制 100% 遵守格式,否则报错
  • Tool Use / Function Calling:模型输出结构化的「函数调用」而非纯文本——Claude Code 和 Cursor Agent 的核心机制
🔗 与 Agent 的关系

Cursor Agent 和 Claude Code 不是「输出一段文字」,而是输出结构化的工具调用:

{ "tool": "Edit", "file": "src/App.tsx", "changes": "..." } { "tool": "Bash", "command": "npm run test" }

程序解析这些 JSON → 执行操作 → 把结果反馈给模型 → 模型继续下一步。这就是 Agent 循环。详见 L2 Agent 架构全景 →

L1 · 基础认知

5. 幻觉:为什么 AI 会「胡说」?

模型不是在「查资料」,而是在「接龙猜下一个词」——猜得很像真的,但不等于真的。

🤖 Vibe Coding 场景 · 幻觉在写代码时长什么样?
  • 编造不存在的 API:「用这个库的 fetchUserV2()」——项目里根本没有这个函数
  • 记错文件路径:改 src/utils/auth.ts,实际项目在 src/lib/auth.ts
  • 假装跑过测试:说「测试已通过」,其实没执行 npm test
  • 引用过时的写法:React 17 的写法套在 React 19 项目上
  • 编造配置项:在 vite.config.ts 里加一个不存在的 plugin 选项

原理:模型在干什么?

核心机制 = 下一个 Token 预测(Next Token Prediction)。 模型读你给的上下文,在词表里算「下一个字最可能是什么」,选一个,拼上去,再预测再一个——循环直到结束。 它没有内置的数据库、搜索引擎或事实校验器;目标是生成流畅、合理的续写,不是保证每一句可验证为真。
为什么会「像真的但错的」解释
训练数据混杂网上有对有错、有新有旧、有教程有谣言,模型学到的是「语言模式」不是「真理表」
必须回答的压力RLHF 等对齐训练鼓励「有帮助」,模型倾向给答案而不是说「我不知道」
上下文不够没读过你的代码库,却要用「常见项目长什么样」来猜——猜错就幻觉
自信≠正确语气越肯定,不代表越可靠;概率高只代表「像训练数据里的说法」
长链推理累积误差Agent 多步执行,早期一步猜错,后面越修越偏——像传话游戏
🧠 一句话记忆

LLM 是概率接龙机器,不是知识检索器。它擅长「看起来像对的」,你要用工程手段验证「到底对不对」。

怎么尽量规避?(个人 → 工程)

层级做法原理
给依据RAG、@file、@codebase、贴报错原文把「猜」变成「看着材料写」——开卷比闭卷准
可验证跑 npm test / build / linter;TDD用编译器、测试当「地面真理」,不靠模型自说自话
结构化JSON Schema、Tool Use、Strict Mode限制输出格式,程序校验字段,减少自由发挥空间
要它引用「只根据 @xxx 回答,找不到就说不知道,并引用行号」强制溯源,无依据则 abstain(拒答)
降随机性事实/代码任务用低 temperature(见下一节)少「创意发挥」,多选高概率、保守的续写
人机分工Plan Mode 先审计划;diff 逐块 Accept;push 前人工看关键节点人把关,Agent 干体力活

业界怎么处理?

方案谁在用 / 典型场景思路
RAG 检索增强企业知识库、客服、Copilot @codebase先检索文档片段,再生成;答案可附出处
联网 / GroundingChatGPT 浏览、Gemini、Perplexity实时查网页,把搜索结果塞进 Prompt
Tool Use 接地Cursor / Claude Code Agent不猜文件内容——Read 真读;不猜测试结果——真跑 bash
双模型 / 评审CI 里 reviewer bot、Self-Refine一个模型写,另一个查;或同一模型多轮自查
Guardrails 护栏NVIDIA NeMo、Llama Guard、Azure Content Safety输出前后过滤:有害内容、无依据断言、PII 泄露
评测基准TruthfulQA、HaluEval、代码 HumanEval用固定题库测幻觉率,迭代 Prompt / RAG / 微调
微调 + 拒答训练部分企业定制模型训练模型在不确定时说「不知道」,减少瞎编
Citation 强制引用NotebookLM、部分 legal/medical 产品每句结论必须对应文档 chunk,点击可跳转

Coding 环节最佳实践(Vibe Coding 必做)

1
先读再改

让 Agent 先 grep / Read 相关文件,别上来就写。「这个函数在哪定义的?先找到再改。」

2
小步 + 可验证

每步带验收:npm run build 必须过。模型说「好了」不算,终端 exit code 0 才算。

3
不信新 import

Agent 加的 import xxx from 'yyy'——确认 package.json 里真有 yyy,或让它跑 install。

4
CLAUDE.md / Rules 写真相

技术栈、目录结构、常用命令写进项目说明,减少 Agent 靠「常见项目模板」瞎猜。

5
大改前 commit

git commit 当存档点。幻觉改乱了,git checkout . 能救回来。

6
对「已完成」保持怀疑

尤其「我已运行测试并通过」——自己再跑一遍,或 Prompt 里写「贴测试输出原文」。

📝 小测验:下面哪种做法最能减少 Coding 幻觉?

A. 把 temperature 调到 1.5 让 AI 更有创意
B. 改完后跑 npm test,失败就让 Agent 修到通过
C. 一次 Prompt 里塞 10 个需求让 AI 一次做完
🧪 Playground:Agent 说 vs 你验证

对比「模型自说自话」和「跑测试验证」——哪个更可信?

🤖 Agent 说
点击左侧按钮…
🔍 实际验证
—
L1 · 基础认知

6. 采样参数:temperature、top-p 怎么调?

模型算出 logits 后还要「抽签」选一个——参数控制这根签有多随机。(接上一节 Transformer 输出 logits 之后的步骤。)

🤖 Vibe Coding 场景 · 参数什么时候 matters?
  • 自己写 API 调模型时:temperature、top_p 在请求体里显式设置——直接影响代码生成稳不稳
  • Cursor / Claude Code Agent 里:多数情况下 IDE 已设好默认值(偏稳定),你在 UI 里不一定能调——但懂原理才知道何时换模型 / 模式
  • 创意 vs 精确:写营销文案可略高;改生产代码、生成 JSON 应偏低
  • 和幻觉的关系:temperature 越高,越容易选出低概率 token → 更容易「跑偏」和编造

生成流程(接 Transformer 推理链路)

1. Transformer 输出 logits
每个候选 Token 一个分数
→
2. 采样策略
temperature / top-p 等
→
3. 选中一个 token
拼到输出里
→
4. 重复
直到结束

核心参数速查

参数干什么Coding 推荐
temperature控制随机性。越低越「选最高概率」;越高越敢选冷门词
范围通常 0~2,0 ≈ 确定性(greedy)
0 ~ 0.3 写代码 / 修 bug
0.5~0.7 讨论方案
0.8+ 头脑风暴(慎用)
top_p(nucleus)只从「累计概率达到 p」的最小词集合里抽
0.1 很窄,1.0 几乎不限制
0.9 ~ 1.0 常用默认
要更稳可试 0.85
top_k只考虑概率最高的 k 个词
现在多用 top_p 代替
若 API 支持:40~50 或留默认
max_tokens限制输出最长 Token 数,防废话和超支按任务设:简短 JSON 256,长代码 4096+
stop遇到指定字符串就停
例:["```\n"] 控制代码块结束
结构化提取时有用
presence / frequency_penalty惩罚重复,鼓励换词写长文摘要时可略加;写代码一般 0
seed固定随机种子,同样输入尽量同样输出(部分模型支持)回归测试、对比 Prompt 时用
类比:temperature = 抽签时的「冒险程度」——低温只抽最大牌,高温小牌也可能中; top_p = 「只从累计 90% 概率的牌堆里抽」——把极离谱的尾巴切掉。 两者常一起用;不要同时把 temperature 和 top_p 都压到极端,留一个主调即可。
📡 API 请求示例(OpenAI 兼容格式)
{ "model": "MiniMax-M2.7-highspeed", "messages": [{ "role": "user", "content": "写一个 TS 函数解析 query string" }], "temperature": 0.2, "top_p": 0.95, "max_tokens": 1024 }

写代码 / 结构化 JSON:temperature 0~0.3。聊天 / 创意:0.7~1.0。事实问答 + RAG:0~0.5。

🧪 交互实验:拖动 temperature / top-p 看概率怎么变

模拟「下一 token 选哪个」——假设候选词是代码里常见的开头。注意 temperature 升高后,低概率词也会变大。

0.7
0.95
拖动滑块查看变化…

场景对照表(最佳实践)

任务temperaturetop_p其他
Agent 改代码 / 修 bug0 ~ 0.20.9 ~ 1.0靠 test/build 验证,不靠高温
JSON / Schema 输出0 ~ 0.10.85 ~ 0.95开 Strict Mode;解析失败重试
RAG 问答(要准确)0 ~ 0.30.9Prompt 要求引用来源
写注释 / 文档 / 命名0.3 ~ 0.50.95略有一点变化可接受
头脑风暴 / 多种方案0.8 ~ 1.00.95 ~ 1.0只讨论不写库;别直接 merge
代码补全(IDE Tab)低(产品内置)—Copilot/Cursor 已调优,用户一般不改

📝 小测验:生产环境让模型输出严格 JSON,最合适的设置是?

A. temperature=0.1, top_p=0.9, 开 Strict Schema
B. temperature=1.2, top_p=1.0, 自由发挥
C. temperature=0.8, 不加 Schema 约束
L2 · 工程实践

7. Memory 策略

模型本身「记不住」上次聊天——你看到的记忆,都是应用层帮它拼出来的。

🤖 AI 场景关联 · Memory 让 Agent 从「金鱼记忆」变「有上下文」
  • 模型本身无状态:每次 API 调用都是全新的;「记得你叫什么」靠的是把历史 messages 再发一遍
  • 短期记忆 = 当前对话上下文:本会话里的 user/assistant 消息,占上下文窗口;太长就 /compact,开新对话则清空
  • 长期记忆 = 持久配置:CLAUDE.md、Rules、User Rules 等——跨会话保留,启动时注入 System Prompt;不会自动从聊天里学,需主动写入
  • 情景记忆 = 检索召回:从历史存档、文档向量库里找回「某次具体片段」——「上次你说过…」是搜出来的,不是模型 weights 里真记得
  • Agent 产品的核心竞争力:短期怎么压缩、长期怎么持久、情景怎么检索——Memory 管得好,Agent 才好用
📌 为什么不用「工作记忆」?

认知科学里,工作记忆是「边记边算」的临时加工台(比如心算时暂存数字); LLM 工程里说的「当前聊天记录」,更准确叫短期记忆 / 会话上下文——它只是 messages 数组,不是模型的认知加工过程。

三种记忆

类比:短期记忆 = 桌面上的便签(关窗就扔) · 长期记忆 = 抽屉里的笔记本(跨天还在) · 情景记忆 = 翻日记找某页(按关键词检索)
短期记忆
当前会话 messages
(开新对话即清空)
长期记忆
CLAUDE.md / Rules
(需主动写入,跨会话)
情景记忆
历史片段检索
(RAG / 对话存档)
类型存什么工程实现典型操作
短期记忆本会话聊过的内容messages 数组拼进 API/compact · 开新 Chat
长期记忆项目规范、稳定偏好CLAUDE.md · .cursor/rules改 md 文件 · User Rules
情景记忆某次具体经历/文档片段向量检索历史对话或文档RAG · @codebase · 搜存档
🧪 交互实验:模拟多轮对话记忆

依次点击,观察信息落在哪个记忆槽——注意第 2 轮仍在短期记忆,不会自动变长期:

等待交互…
🛠️ 工程里的 Memory 实现
对话历史短期记忆:直接塞进 messages。Claude Code 的 /compact 是压缩它,不是变长期
CLAUDE.md / Rules长期记忆:项目规范、技术栈;每次启动自动加载,换对话也不丢
向量数据库情景记忆 + RAG:embedding 存片段,按语义检索「上次相关的那一段」
Cursor MemoryUser Rules 记个人偏好(「用中文回答」)——也是长期记忆的一种
L2 · 工程实践

7. RAG 检索增强生成

模型不知道你的公司内部文档——RAG 帮它「开卷考试」。

🤖 AI 场景关联 · RAG = Agent 的「开卷考试能力」
  • 私有知识进 Agent:公司文档、API 文档、课程材料——模型训练时没见过,必须 RAG 检索后塞进 Prompt
  • Cursor @codebase:本质是代码库 RAG,embedding 搜索相关文件片段再回答
  • Claude Code 读 repo:大项目不能全塞上下文,Agent 用 grep/glob 搜索 + 读文件,也是检索的一种
  • 减少幻觉:有检索依据的回答可溯源(「根据 xxx.md 第 3 节…」),纯靠模型记忆容易编造
  • 你的 Knowledge OS 知识库:就是 RAG 产品的 UI 层——树形文档 + 侧边 AI 助手 = 检索 + 生成

RAG 四步流程

1. 用户提问
→
2. 检索文档
→
3. 拼进 Prompt
→
4. 模型回答
类比:闭卷考试 = 纯靠模型训练记忆 · 开卷考试 = RAG(先翻书找资料,再答题)
🧪 交互实验:模拟文档检索
点击检索查看结果
🏗️ RAG 工程组件(L2 深入)
文档加载读 PDF / Markdown / 网页,切成 chunks(通常 500~1000 字一块)
Embedding把文字变成向量(一串数字),语义相近的文字向量距离近
向量数据库存 embedding,支持相似度搜索。常见:Chroma、Pinecone、pgvector
检索 Retriever用户提问 → 找 top-K 最相关 chunks。可混合关键词(BM25)+ 向量搜索
重排序 Rerank用专门模型对检索结果二次排序,提高精度
生成 Generator把检索到的 chunks + 用户问题拼成 Prompt,交给 LLM 回答

Cursor 的 @codebase 和 Claude Code 读整个 repo,本质上也是一种 RAG(代码库检索)。

L2 · 工程实践

8. 成本计算器

Token 用量 × 单价 = 你的 API 账单。提前算清楚,避免「惊喜」。

🤖 AI 场景关联 · 成本 = Agent 能不能「随便跑」
  • Agent 比普通聊天贵很多:一次任务可能调 10+ 次模型(读文件、思考、改代码、跑测试),Token 累加很快
  • Claude Code /cost:会话内实时看 burn rate,Agent 多轮调用费用需要监控
  • 省 Token = 省 Memory 压力:精简 CLAUDE.md、用 @file 代替全库搜索、/compact 压缩历史,一箭双雕
  • 模型选型:简单任务用 Haiku/mini,复杂推理用 Sonnet/Opus——Agent 编排层可以做路由
  • Highspeed vs Standard:Token Plan 按请求次数 + Token 双计,Agent 高频调用时要选合适套餐

成本公式

公式:成本 = (输入 Token 数 × 输入单价 + 输出 Token 数 × 输出单价) / 1,000,000
🧪 交互实验:估算一次 API 调用的费用
项目Token 数费用

📝 小测验:要降低成本,以下哪个策略最有效?

A. 换更大的模型
B. 减少输入 Token(精简 Prompt / 用 RAG 代替全量文档)
C. 让模型多输出一些
L2 · Agent 构建

Agent 架构全景:从聊天到「能动手」

下面用个人助理 Agent贯穿全文:读待办、写邮件草稿、查日历——和 Cursor 编程 Agent 架构相同,只是工具不同。先跑通最小版,再进 渐进融入扩展 →

一句话:Chatbot = 只会说 · Agent = 会说 + 会调工具 + 会看结果再决定下一步。

Chatbot vs Agent

Chatbot(纯聊天)Agent(智能体)
输入用户消息用户消息 + 工具列表 + 历史 + Memory
输出一段文本文本 或 结构化工具调用(JSON)
后续结束,等下一句程序执行工具 → 结果塞回上下文 → 再调 LLM → 循环
例子「上海明天天气怎么样?」「今日简报」→ 读 todos.md → 查天气 MCP → 起草邮件

Agent 五层架构(你要设计的「整体」)

① 编排层
Orchestrator 循环
→
② LLM 层
推理 / 决策
→
③ 协议层
HTTP / SSE / JSON
→
④ 工具层
函数 / MCP / API
→
⑤ 记忆层
短期 + 长期
层级干什么Cursor / 自建对应
编排层while 循环:调 LLM → 解析输出 → 执行工具 → 追加 messages → 再调Cursor Agent 内核 · 你的 agent.py 主循环
LLM 层根据上下文决定「直接回答」还是「调哪个工具、传什么参数」Claude / DeepSeek / MiniMax 等模型 API
协议层怎么发请求、怎么传 tools、怎么收流式响应OpenAI 兼容 Chat API · Anthropic Messages API · SSE
工具层读待办、写草稿、发邮件、查日历——LLM 本身做不到的事read_file · write_draft · send_email · MCP 日历/天气
记忆层短期:对话 messages 数组 · 长期:CLAUDE.md / RAG / 向量库见 Memory 策略 · RAG

Agent 核心循环(所有产品共用)

用户: "/morning-brief 帮我准备今日简报" ┌─────────── Orchestrator ───────────┐ │ messages = [system, user, ...] │ │ ↓ │ │ POST /chat/completions + tools │ ← 协议层 │ ↓ │ │ LLM 返回: tool_call read_file │ ← LLM 决策 │ ↓ │ │ 执行 read_file("data/todos.md") │ ← 工具层 │ ↓ │ │ messages += tool_result │ ← 记忆层 │ ↓ │ │ 再调 LLM → MCP 天气 → 输出简报 │ └────────────────────────────────────┘

L1 的 结构化输出 就是为这个循环服务的——LLM 输出 JSON,程序才能可靠执行。

🧪 Playground:走一遍 Agent 循环

任务:「读取 data/todos.md,告诉我今天有哪些待办」

提问
LLM
Tool
回传
回答
点击步骤按钮,看 messages 数组怎么一步步变长…
L2 · Agent 构建

LLM 协议与接入:HTTP 里到底传什么?

Agent 和 LLM 之间靠协议对话——不是魔法。搞懂请求 / 响应格式,换 DeepSeek、Claude、MiniMax 只是换 endpoint 和字段细节。

三层协议栈

层协议 / 格式干什么
传输层HTTPS + JSONPOST 发请求,Authorization 带 API Key
对话层Chat Completions / Messages APImessages[] 数组:system · user · assistant · tool
能力层Tool Use · JSON Schema · MCP告诉模型「你能调哪些函数」;MCP 是工具的标准化「USB 口」

messages 数组:Agent 的「短期记忆」载体(OpenAI 格式)

DeepSeek · GPT · MiniMax 等 OpenAI 兼容 API 都用这套 role 体系:

[ { "role": "system", "content": "你是个人助理,可以用 read_file、write_draft、send_email。" }, { "role": "user", "content": "今天有哪些待办?" }, { "role": "assistant", "content": null, "tool_calls": [{ "id": "call_abc123", "type": "function", "function": { "name": "read_file", "arguments": "{\"path\":\"data/todos.md\"}" } }] }, { "role": "tool", "tool_call_id": "call_abc123", "content": "- [ ] 15:00 和小李开会\n- [ ] 回复客户邮件" }, { "role": "assistant", "content": "今天有 2 项:15:00 和小李开会;回复客户邮件。" } ]
role谁产生关键字段
system你写死content 字符串 · 长期规则 / 人设
user用户输入content 字符串
assistantLLM 返回content 文本 或 tool_calls[](二者常互斥)
tool你的程序tool_call_id 必须对上 · content 是工具执行结果(字符串)

Claude Messages API:同一任务,格式不同

Claude 没有 role: tool。工具结果塞进 user 消息的 content 数组,类型是 tool_result:

// 请求体顶层有独立 system 参数,不在 messages 里 { "model": "claude-sonnet-4-20250514", "max_tokens": 1024, "system": "你是个人助理,可以用 read_file、write_draft 工具。", "messages": [ { "role": "user", "content": "今天有哪些待办?" }, { "role": "assistant", "content": [ { "type": "tool_use", "id": "toolu_01", "name": "read_file", "input": { "path": "data/todos.md" } } ]}, { "role": "user", "content": [ { "type": "tool_result", "tool_use_id": "toolu_01", "content": "- [ ] 15:00 和小李开会\n- [ ] 回复客户邮件" } ]} ] } // LLM 最终回复也是 content 数组,不是单一字符串: { "role": "assistant", "content": [ { "type": "text", "text": "今天 2 项待办:15:00 和小李开会;回复客户邮件。" } ]}

Tool 定义格式对比

OpenAI / DeepSeek · tools[]
{ "type": "function", "function": { "name": "read_file", "description": "读取 data/ 下待办、笔记等文本文件", "parameters": { "type": "object", "properties": { "path": { "type": "string" } }, "required": ["path"] } } }
Claude · tools[]
{ "name": "read_file", "description": "读取文本文件", "input_schema": { "type": "object", "properties": { "path": { "type": "string" } }, "required": ["path"] } }

字段名不同:function.parameters vs input_schema。LLM 返回参数也不同:OpenAI 是 arguments JSON 字符串,Claude 是 input 对象。

完整两轮 HTTP 往返(同一任务)

Agent 第一次调 LLM → 拿到 tool 调用 → 执行 → 第二次调 LLM → 拿到最终文本。点按钮看 OpenAI 和 Claude 各轮请求 / 响应:

选择上方按钮,查看具体 HTTP 报文…

协议字段对照表(写适配器时查这张)

概念OpenAI / DeepSeekClaude (Anthropic)
EndpointPOST /v1/chat/completionsPOST /v1/messages
鉴权 HeaderAuthorization: Bearer sk-...x-api-key: sk-ant-... + anthropic-version: 2023-06-01
System Promptmessages 里 {role:"system"}顶层 system 字段(字符串或 block 数组)
工具定义{type:"function", function:{name, parameters}}{name, description, input_schema}
模型决定调工具finish_reason: "tool_calls"stop_reason: "tool_use"
工具调用 IDtool_calls[].id 如 call_abccontent[].id 如 toolu_01
工具参数function.arguments(JSON 字符串,需 json.loads)input(已是 object,直接用)
回传工具结果新 message:{role:"tool", tool_call_id, content}新 user message:content:[{type:"tool_result", tool_use_id, content}]
assistant 历史含 tool_calls 的 assistant message 必须原样保留含 tool_use block 的 assistant message 必须原样保留
最终文本choices[0].message.content 字符串content 数组里 type:"text" 的块
Python SDKpip install openaipip install anthropic

流式响应 SSE

ChatGPT / Cursor 打字效果 = Server-Sent Events。请求加 stream: true,服务端逐 chunk 推送 token,前端边收边渲染。Agent 内部通常非流式等完整 tool_call JSON 解析完再执行——UI 层才流式给用户看。

MCP 在协议栈里的位置

MCP(Model Context Protocol)不替代 LLM API——它在工具层标准化「怎么发现、怎么调外部工具」。Agent 编排层可以:内置函数 + MCP Server 暴露的工具,统一注册进 tools[] 给 LLM 选。详见 L3 MCP 节。

🧪 Playground:DeepSeek vs Claude 接入差异

两家都能做 Agent,但 API 格式不同——看懂差异就知道怎么「换模型不改架构」。

请求示例
选择提供商…
关键差异
—
L2 · Agent 构建

从 0 搭建个人助理 Agent(完整可运行代码)

下面是一套复制就能跑的最小个人助理:read_file 读待办 · write_draft 写邮件草稿 · send_email 发送(需确认)。DeepSeek 版 + Claude 版对照协议差异。

① 创建项目 & 安装依赖

mkdir personal-assistant && cd personal-assistant python3 -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate mkdir -p data drafts cat > data/todos.md << 'EOF' - [ ] 15:00 和小李开项目会 - [ ] 回复张总邮件 - [ ] 买周末机票 EOF cat > data/contacts.json << 'EOF' {"小李": "xiaoli@company.com", "张总": "zhang@company.com"} EOF # requirements.txt echo 'openai>=1.40.0 anthropic>=0.34.0 python-dotenv>=1.0.0' > requirements.txt pip install -r requirements.txt # .env(不要 commit) cat > .env << 'EOF' DEEPSEEK_API_KEY=sk-your-deepseek-key ANTHROPIC_API_KEY=sk-ant-your-claude-key EOF

② tools.py — 个人助理工具层

# tools.py — 个人助理三个核心工具 import json from pathlib import Path from datetime import datetime ROOT = Path(".").resolve() DATA = ROOT / "data" DRAFTS = ROOT / "drafts" def read_file(path: str) -> str: """读 data/ 下待办、笔记、联系人。""" target = (ROOT / path).resolve() if not str(target).startswith(str(ROOT)): return json.dumps({"error": "只能读项目内文件"}) if "private" in target.parts: return json.dumps({"error": "禁止读取 private 目录"}) if not target.is_file(): return json.dumps({"error": f"不存在: {path}"}) return json.dumps({"path": path, "content": target.read_text(encoding="utf-8")[:8000]}) def write_draft(to: str, subject: str, body: str) -> str: """写邮件草稿到 drafts/,不真正发送。""" DRAFTS.mkdir(exist_ok=True) ts = datetime.now().strftime("%Y%m%d_%H%M%S") path = DRAFTS / f"draft_{ts}.json" draft = {"to": to, "subject": subject, "body": body, "draft_approved": False} path.write_text(json.dumps(draft, ensure_ascii=False, indent=2), encoding="utf-8") return json.dumps({"ok": True, "draft_path": str(path), "preview": draft}) def send_email(to: str, subject: str, body: str, draft_approved: bool = False) -> str: """模拟发邮件(Demo 只 print;生产接 SMTP / API)。""" if not draft_approved: return json.dumps({"error": "邮件未确认,请先 write_draft 并让用户批准"}) # 生产环境:smtp.sendmail(...) 或调 SendGrid API print(f"[SEND] To:{to} | {subject}") return json.dumps({"ok": True, "to": to, "subject": subject, "sent_at": datetime.now().isoformat()}) TOOL_HANDLERS = { "read_file": lambda a: read_file(a["path"]), "write_draft": lambda a: write_draft(a["to"], a["subject"], a["body"]), "send_email": lambda a: send_email(a["to"], a["subject"], a["body"], a.get("draft_approved", False)), } def execute_tool(name: str, args_json: str) -> str: if name not in TOOL_HANDLERS: return json.dumps({"error": f"未知工具: {name}"}) try: args = json.loads(args_json) if isinstance(args_json, str) else args_json return TOOL_HANDLERS[name](args) except Exception as e: return json.dumps({"error": str(e)})

③ agent_openai.py — DeepSeek 完整 Agent(OpenAI 协议)

# agent_openai.py — DeepSeek / GPT / MiniMax 通用 import json, os from dotenv import load_dotenv from openai import OpenAI from tools import execute_tool load_dotenv() client = OpenAI( api_key=os.environ["DEEPSEEK_API_KEY"], base_url="https://api.deepseek.com", # GPT 改 api.openai.com ) TOOLS = [ {"type": "function", "function": { "name": "read_file", "description": "读取 data/ 下待办、笔记、联系人", "parameters": { "type": "object", "properties": {"path": {"type": "string", "description": "如 data/todos.md"}}, "required": ["path"], }, }}, {"type": "function", "function": { "name": "write_draft", "description": "写邮件草稿到 drafts/,不发送", "parameters": { "type": "object", "properties": { "to": {"type": "string"}, "subject": {"type": "string"}, "body": {"type": "string"}, }, "required": ["to", "subject", "body"], }, }}, {"type": "function", "function": { "name": "send_email", "description": "发送邮件,仅 draft_approved=true 时可用", "parameters": { "type": "object", "properties": { "to": {"type": "string"}, "subject": {"type": "string"}, "body": {"type": "string"}, "draft_approved": {"type": "boolean"}, }, "required": ["to", "subject", "body"], }, }}, ] SYSTEM = "你是个人助理。用 read_file 读 data/ 下文件,write_draft 写邮件草稿,send_email 仅在用户确认后发送。基于工具真实返回回答,不要编造。" def run_agent(user_input: str, max_steps: int = 8) -> str: messages = [ {"role": "system", "content": SYSTEM}, {"role": "user", "content": user_input}, ] for step in range(max_steps): print(f"\n--- Step {step + 1}: 调 LLM ---") resp = client.chat.completions.create( model="deepseek-chat", messages=messages, tools=TOOLS, tool_choice="auto", temperature=0.2, ) msg = resp.choices[0].message # OpenAI SDK 返回的对象要转成 dict 才能 append messages.append(msg.model_dump(exclude_none=True)) if not msg.tool_calls: print("--- 完成:LLM 不再调工具 ---") return msg.content or "" # 有 tool_calls → 逐个执行 for call in msg.tool_calls: name = call.function.name args = call.function.arguments print(f" → 工具: {name}({args})") result = execute_tool(name, args) print(f" ← 结果: {result[:120]}...") messages.append({ "role": "tool", "tool_call_id": call.id, "content": result, }) return "超过 max_steps,强制停止" if __name__ == "__main__": q = "读一下 data/todos.md,总结今天待办,并给小李起草一封下午会议的提醒邮件" print("用户:", q) print("\n=== 助理回答 ===") print(run_agent(q))

运行:python3 agent_openai.py。终端会看到每一步 tool 调用和最终回答。

④ agent_claude.py — Claude 完整 Agent(Anthropic 协议)

# agent_claude.py — 注意 tool_result 回传方式不同! import json, os from dotenv import load_dotenv import anthropic from tools import execute_tool load_dotenv() client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"]) TOOLS = [ { "name": "read_file", "description": "读取 data/ 下待办、笔记", "input_schema": { "type": "object", "properties": {"path": {"type": "string"}}, "required": ["path"], }, }, { "name": "write_draft", "description": "写邮件草稿", "input_schema": { "type": "object", "properties": { "to": {"type": "string"}, "subject": {"type": "string"}, "body": {"type": "string"}, }, "required": ["to", "subject", "body"], }, }, { "name": "send_email", "description": "发送已确认的邮件", "input_schema": { "type": "object", "properties": { "to": {"type": "string"}, "subject": {"type": "string"}, "body": {"type": "string"}, "draft_approved": {"type": "boolean"}, }, "required": ["to", "subject", "body"], }, }, ] SYSTEM = "你是个人助理。读 data/ 文件,写邮件草稿,用户确认后才 send_email。不要编造。" def run_agent(user_input: str, max_steps: int = 8) -> str: messages = [{"role": "user", "content": user_input}] for step in range(max_steps): print(f"\n--- Step {step + 1}: 调 Claude ---") resp = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=4096, system=SYSTEM, messages=messages, tools=TOOLS, ) # 把 assistant 回复追加进历史(必须保留 tool_use block) messages.append({"role": "assistant", "content": resp.content}) tool_uses = [b for b in resp.content if b.type == "tool_use"] if not tool_uses: texts = [b.text for b in resp.content if b.type == "text"] print("--- 完成 ---") return "\n".join(texts) # Claude:tool 结果放在 user 消息的 tool_result block 里 tool_results = [] for block in tool_uses: print(f" → 工具: {block.name}({json.dumps(block.input)})") result = execute_tool(block.name, block.input) # input 已是 dict print(f" ← 结果: {result[:120]}...") tool_results.append({ "type": "tool_result", "tool_use_id": block.id, "content": result, }) messages.append({"role": "user", "content": tool_results}) return "超过 max_steps,强制停止" if __name__ == "__main__": q = "今天有哪些待办?" print("用户:", q) print("\n=== 助理回答 ===") print(run_agent(q))

⑤ 运行示例:终端实际输出

$ python3 agent_openai.py 用户: 读一下 data/todos.md,总结今天待办,并给小李起草会议提醒邮件 --- Step 1: 调 LLM --- → 工具: read_file({"path": "data/todos.md"}) ← 结果: {"path":"data/todos.md","content":"- [ ] 15:00 和小李开项目会... --- Step 2: 调 LLM --- → 工具: write_draft({"to":"xiaoli@company.com","subject":"下午会议提醒",...}) ← 结果: {"ok":true,"draft_path":"drafts/draft_20260321_0900.json"... --- Step 3: 调 LLM --- --- 完成:LLM 不再调工具 --- === 助理回答 === 今天 3 项待办:15:00 和小李开会、回复张总邮件、买周末机票。 已给小李起草会议提醒,草稿在 drafts/draft_20260321_0900.json。 回复「确认发送」我再帮你发邮件。

⑥ 两家代码差在哪?(只有协议层 4 处不同)

#代码位置agent_openai.pyagent_claude.py
1SDK 初始化OpenAI(api_key, base_url=...)anthropic.Anthropic(api_key=...)
2System Prompt放在 messages[0] role=system独立 system=SYSTEM 参数
3工具定义{type:"function", function:{parameters}}{name, input_schema}
4解析 tool 调用msg.tool_calls[].function.arguments(字符串)block.input(dict)· 从 content 数组找 type=tool_use
5回传 tool 结果{role:"tool", tool_call_id, content}{role:"user", content:[{type:"tool_result",...}]}

tools.py 和 while 循环逻辑完全一样——这就是为什么要做 LLMClient 适配器(见下)。

🔌 进阶:统一适配器(换模型只改一行)
# llm_client.py — 抽象接口 class LLMClient: def chat(self, messages, tools) -> tuple[str | None, list]: """返回 (最终文本或None, 待执行的tool_calls列表)""" raise NotImplementedError class OpenAIClient(LLMClient): def __init__(self, api_key, base_url, model): from openai import OpenAI self.client = OpenAI(api_key=api_key, base_url=base_url) self.model = model self.messages = [] def chat(self, messages, tools): resp = self.client.chat.completions.create( model=self.model, messages=messages, tools=tools) msg = resp.choices[0].message if msg.tool_calls: return None, [(c.id, c.function.name, c.function.arguments) for c in msg.tool_calls] return msg.content, [] # agent.py 主循环只写一次: # text, calls = llm.chat(messages, TOOLS) # if calls: execute & append results; continue # else: return text

设计 checklist:搭一个「整体 Agent」要想清楚的 6 件事

#设计决策例子
1LLM 选哪家 / 哪个模型DeepSeek 便宜快速 · Claude 工具调用稳 · 本地 Ollama 离线
2工具有哪些read_file · write_draft · send_email · MCP 天气/日历
3Memory 策略messages 截断 · data/ 本地文件 · 后续可加 RAG 搜历史笔记
4安全边界邮件先 draft · Hook 拦截 private/ · 发送需用户确认
5终止条件无 tool_call · 达到 max_steps · 超时 · 用户打断
6可观测性每步 log messages · 计 Token 成本 · 报错重试策略
🧪 Playground:组装你的 Agent 配置

选 LLM + 工具组合,看生成的架构摘要(模拟设计阶段):

选一个配置方案…
下一步:跑通上面最小助理后,继续 渐进融入 Rules / Skills / Hooks / MCP →,把「别乱发邮件」「/morning-brief」「日历 MCP」逐步挂上。

延伸阅读:渐进融入 Rules / Skills / Hooks / MCP → · Memory · RAG · Cursor Plugins 生态

L2 · Agent 构建

渐进融入扩展:Rules → Skills → Hooks → MCP

Cursor 的 Rules / Skills / Hooks / MCP 不是魔法——自建 Agent 也能逐步加。下面用大家熟悉的「个人助理」场景,分 5 个 Stage 演进:读待办、查天气、起草邮件——每 Stage 只加一层、能跑、能测。

为什么用个人助理?人人都理解「帮我查日程、写邮件、别乱发」——比部署服务器更直观,但架构完全一样:LLM + 工具 + 循环 + 扩展模块。

Cursor 概念 → 自建 Agent 落点

Cursor 模块在 Agent 里是什么插入循环的位置Cursor 文档
Rules启动时加载的 .md 规则 → 拼进 system调 LLM 之前(build_system_prompt)L3 Rules
Skills按需加载 SKILL.md 工作流 → 注入 user 上下文收到用户输入 之后、调 LLM 之前L3 Skills
Hooks事件脚本:执行工具前/后拦截、审计execute_tool 前后L3 Hooks
MCP外部 MCP Server 的工具 → 合并进 tools[]启动时注册 · 执行时分发L3 MCP
Plugins上面全部打包成一个目录 + manifest项目初始化时一次性加载L3 Plugins

五 Stage 演进路线(同一实战:个人助理)

贯穿任务:用户发 /morning-brief ——「汇总我今天的待办、查一下上海天气、给同事小李起草一封下午会议的提醒邮件,先给我看草稿,别直接发。」

Stage 0 最小助理只有本地文件工具;逐 Stage 加上规矩、流程、安全拦截、日历/天气 MCP,最后变成「能用的私人秘书」。

Agent
Rules
Skills
Hooks
MCP
点 Stage 按钮,看每步加什么文件、改哪行代码…
📁 Stage 0 起点:个人助理最小目录
personal-assistant/ ├── data/ │ ├── todos.md # - [ ] 15:00 和小李对需求 │ ├── notes.md # 会议要点、联系人 │ └── private/ # 身份证、银行卡(Stage 3 Hook 保护) │ └── secrets.txt ├── drafts/ # 邮件草稿目录 ├── tools.py # read_file · write_draft · send_email └── agent.py # while 循环调 LLM

Stage 1 · 加 Rules(助理的「职业操守」→ system prompt)

不用每次重复「用中文」「别乱发邮件」——写进 rules/,启动时拼进 system。

personal-assistant/ ├── rules/ │ ├── always.md # 每次都带(= Always Apply) │ └── email.md # 提到「邮件/发送」时带上(= Apply Intelligently) ├── rules_loader.py └── agent.py # rules/always.md --- always: true --- - 始终用中文、简洁回复 - 读取 data/ 下文件可以,禁止读 data/private/ - 任何 send_email 必须先 write_draft,等用户确认后再发 # rules/email.md --- keywords: [邮件, 发送, 提醒, 请假, email] --- - 称呼用「您好」,正文不超过 200 字 - 邮件末尾加「此致 / 助理代笔」 - 绝不编造收件人邮箱,从 data/contacts.json 查 # rules_loader.py(同前,略) def build_system(user_input: str) -> str: base = "你是个人助理,可用 read_file / write_draft / send_email。" rules = load_rules(user_input) return base + ("\n\n## 助理守则\n" + rules if rules else "")

验证:说「帮我发邮件提醒小李」→ system 自动带上 email.md,Agent 会先 draft 而不是直接 send。

Stage 2 · 加 Skills(固定流程 → /morning-brief)

每天早晨同一套动作——封装成 Skill,用户打 /morning-brief 就注入完整 checklist。

personal-assistant/ ├── skills/ │ └── morning-brief/ │ └── SKILL.md ├── skills_loader.py └── agent.py # skills/morning-brief/SKILL.md --- name: morning-brief description: 生成每日早晨简报:待办 + 天气 + 需跟进邮件 --- ## 步骤(按顺序执行) 1. read_file("data/todos.md") — 提取今日待办 2. (Stage 4 起)MCP 查用户城市天气 3. (Stage 4 起)MCP 查今日日历事件 4. 若有需提醒他人的事项 → write_draft 邮件到 drafts/ 5. 输出 Markdown 简报:## 待办 / ## 天气 / ## 日程 / ## 待确认邮件 # skills_loader.py def resolve_skill(user_input: str) -> str | None: if user_input.strip().startswith("/"): name = user_input.split()[0][1:] # "/morning-brief" → "morning-brief" p = Path(f"skills/{name}/SKILL.md") return p.read_text() if p.exists() else None return None

实战:每天输入 /morning-brief,不用重新描述「先看待办再查天气再…」——和 Cursor 里 /deploy-app 一个逻辑。

Stage 3 · 加 Hooks(助理的「安全护栏」)

个人助理最怕两件事:乱发邮件、读隐私文件。Hook 在工具执行前拦截。

personal-assistant/ ├── hooks.json ├── hooks/ │ ├── confirm_send_email.sh │ └── block_private_read.sh ├── hooks_runner.py └── tools.py # hooks.json { "beforeSendEmail": [{ "script": "hooks/confirm_send_email.sh" }], "beforeReadFile": [{ "script": "hooks/block_private_read.sh" }] } # hooks/confirm_send_email.sh #!/bin/bash # stdin: {"to":"...","subject":"...","draft_approved":false} input=$(cat) if echo "$input" | grep -q '"draft_approved":false'; then echo '{"decision":"block","reason":"邮件尚未经用户确认,请先 write_draft 并等待批准"}' else echo '{"decision":"allow"}' fi # hooks/block_private_read.sh #!/bin/bash input=$(cat) if echo "$input" | grep -q 'data/private'; then echo '{"decision":"block","reason":"Rules 禁止读取 private 目录"}' else echo '{"decision":"allow"}' fi # tools.py — execute_tool 入口 def execute_tool(name, args_json): args = json.loads(args_json) if isinstance(args_json, str) else args_json if name == "read_file": d = run_hooks("beforeReadFile", {"path": args["path"]}) if d.get("decision") == "block": return json.dumps({"error": d["reason"]}) if name == "send_email": d = run_hooks("beforeSendEmail", args) if d.get("decision") == "block": return json.dumps({"error": d["reason"]}) return TOOL_HANDLERS[name](args)

实战:Agent 若跳过草稿直接 send_email → Hook block → LLM 改为先展示 drafts/ 里的内容请你确认。

Stage 4 · 加 MCP(接日历、天气等外部能力)

待办在本地 markdown,但天气和日历在外部——MCP 把它们的 API 变成 Agent 可调的工具。

personal-assistant/ ├── mcp.json ├── mcp_client.py └── agent.py # mcp.json { "mcpServers": { "weather": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-weather"] }, "google-calendar": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-google-calendar"], "env": { "GOOGLE_CALENDAR_CREDENTIALS": "${GOOGLE_CALENDAR_CREDENTIALS}" } } } } # agent.py 启动时合并工具 BUILTIN = [read_file, write_draft, send_email] # 本地 MCP = load_mcp_tools("mcp.json") # mcp_weather_get_forecast # mcp_google-calendar_list_events TOOLS = BUILTIN + MCP # morning-brief Skill 第 2、3 步就可以调 MCP 了

实战:简报里出现「上海今日 18°C 多云 · 15:00 和小李会议(来自 Google Calendar)」——纯 read_file 做不到。

Stage 5 · 完整个人助理(全部合流)

# agent_full.py def run_agent(user_input: str) -> str: system = build_system(user_input) # ① Rules messages = [{"role": "system", "content": system}] skill = resolve_skill(user_input) # ② Skills if skill: messages.append({"role": "user", "content": "【Skill】\n" + skill}) messages.append({"role": "user", "content": user_input}) tools = BUILTIN_TOOLS + get_mcp_tools() # ③ 内置 + MCP for _ in range(MAX_STEPS): msg = llm.chat(messages, tools) if not msg.tool_calls: return msg.content for call in msg.tool_calls: result = execute_tool(call.name, call.arguments) # ④ Hooks 在内 messages.append(tool_result(call.id, result)) return "步数超限" # 目录 = 可分享的「助理 Plugin 包」 personal-assistant/ ├── data/ drafts/ rules/ skills/ hooks/ mcp.json ├── rules_loader.py skills_loader.py hooks_runner.py mcp_client.py ├── tools.py agent_full.py

实战 Walkthrough:/morning-brief 走一遍

步骤模块发生什么
1用户/morning-brief(或「帮我准备今日简报」)
2Skills加载 morning-brief/SKILL.md → 待办→天气→日程→草稿 顺序
3Rulesalways.md 拼进 system → 中文 · 禁读 private · 邮件先 draft
4LLMtool_call: read_file("data/todos.md")
5HooksbeforeReadFile → allow(不是 private 目录)
6MCPtool_call: mcp_weather_get_forecast(city="上海")
7MCPtool_call: mcp_google-calendar_list_events(today)
8LLMtool_call: write_draft(to="小李", subject="下午会议提醒", ...)
9LLM输出 Markdown 简报 + 「邮件草稿在 drafts/,回复「确认发送」我再发」
10用户「确认发送」→ send_email(draft_approved=true) → Hook allow → 发出
🧪 Playground:这个扩展该在哪一步加?

个人助理场景下,该先加哪个模块?

点场景按钮…
📋 渐进路线建议(实战顺序)
顺序加什么理由工作量
1Stage 0 最小 Agent先跑通 LLM + 工具循环1 小时
2+ Rules立刻减少重复叮嘱,ROI 最高+30 分钟
3+ Hooks安全护栏,生产必备+1 小时
4+ Skills固定流程标准化(晨间简报、周报)+1 小时
5+ MCP接外部系统,按需加+2 小时
6打包 Plugin团队分发 · 对齐 Cursor Marketplace 思路+30 分钟
和 Cursor / 编程 Agent 的关系:架构完全相同。个人助理用「邮件/日历/天气」,编程 Agent 用「读代码/跑 test/部署」——换工具和 Rules 而已。 L3 教 Cursor 里怎么配;本节教自建里怎么实现。目录对齐 rules/ skills/ hooks.json mcp.json,可迁到 Cursor Plugin。
L3 · Cursor 定制

Plugins 生态概览

参考 Cursor Plugins 文档——把 Rules、Skills、Subagents、Hooks、MCP 等能力打包、分发、复用。自建 Agent 里怎么逐步实现?见 L2 渐进融入扩展 →

一句话:Plugin = 插件包 · Rules = 长期规矩 · Skills = 可复用技能 · Subagents = 分身干活 · Hooks = 自动化钩子 · MCP = 接外部工具。

六大模块一览

模块干什么放哪 / 怎么触发本章跳转
Plugins把下面所有组件打包成可安装的分发包Marketplace 一键装 · .cursor-plugin/plugin.json本节 ↓
Rules持久 AI 行为规则、编码标准.cursor/rules/*.mdcRules →
Skills封装领域工作流(脚本 + 说明).cursor/skills/ · /skill-nameSkills →
Subagents子 Agent 分身,独立上下文并行干活.cursor/agents/*.md · /verifierSubagents →
HooksAgent 循环各阶段的自动化脚本.cursor/hooks.jsonHooks →
MCP接 GitHub、数据库、浏览器等外部工具.cursor/mcp.jsonMCP →
📦 Plugin 目录结构(自建插件)
my-plugin/ ├── .cursor-plugin/plugin.json # 只需 name 字段,其余自动发现 ├── rules/coding-standards.mdc ├── skills/code-reviewer/SKILL.md ├── agents/verifier.md # Subagent 定义 ├── hooks.json └── mcp.json

本地调试:放到 ~/.cursor/plugins/local/my-plugin,重启 Cursor。发布:cursor.com/marketplace

🧪 Playground:这个场景该用哪个模块?

选一个 Vibe Coding 场景,看该用 Rules / Skills / Subagents / Hooks / MCP 中的哪些:

Rules
Skills
Subagents
Hooks
MCP
Plugins
点上方场景按钮…
🔗 和 Claude Code 的对应关系
CursorClaude Code说明
Rules (.cursor/rules)CLAUDE.md + Rules都是长期 Memory / System 约束
Skills (.cursor/skills)Skills (.claude/skills)开放标准,目录可互通
Hooks (.cursor/hooks.json)HooksCursor 还支持 Claude Code hooks 兼容
SubagentsTask / 子 AgentCursor 内置 Explore/Bash/Browser
MCPMCP同一协议,配置路径不同
Plugins—Cursor 特有:Marketplace 打包分发
L3 · Cursor 定制

Rules — 持久 AI 规矩

不用每次重复「commit 用中文」「别 force push」——写进 Rules,Agent 自动遵守。

规则写在 .cursor/rules/*.mdc(必须 .mdc 扩展名)。简单替代方案:项目根 AGENTS.md。

四种生效模式

模式何时注入上下文适用
Always Apply每次对话都带全项目通用规范(版权头、禁止改 dist/)
Apply IntelligentlyAgent 读 description 判断相关「RPC 服务规范」「数据库迁移规范」
Apply to Specific Files打开/编辑匹配 glob 的文件时src/components/**/*.tsx 的 React 规范
Apply Manually聊天里 @rule-name 手动引用偶尔用的专项规范

优先级:Team Rules → Project Rules → User Rules(团队覆盖个人)。

🧪 Playground:Rules 生效模式模拟
选择一种 Rules 模式…
L3 · Cursor 定制

Skills — 可复用工作流

把「生成 changelog」「按模板建 PR」等重复任务封装成一键技能。

每个 Skill 是一个文件夹 + SKILL.md(YAML frontmatter + 步骤说明)。Agent 自动判断何时用,或你输入 /deploy-app 手动触发。

.cursor/skills/deploy-app/ ├── SKILL.md # name + description + 步骤 ├── scripts/deploy.sh # Agent 可执行的脚本 └── references/ # 按需加载的参考文档
和 Subagents 怎么选?Skills 适合短、可重复的任务(格式化、生成文档);Subagents 适合长调研、并行、要独立上下文的任务。详见 Subagents 节 →
L3 · Cursor 定制

Subagents — 分身并行

主 Agent 委派子任务给独立窗口的分身,各自上下文不互相污染。

内置三个:Explore(搜代码库)、Bash(跑命令)、Browser(浏览器 MCP)。自定义放 .cursor/agents/verifier.md,用 /verifier 调用。

Subagents 适合Skills 适合
长调研、要独立上下文单次、可重复的小任务
多路并行(改 API + 写文档)生成 changelog、格式化 import
独立验收(Verifier 跑测试)不需要单独上下文窗口
🧪 Playground:Subagent 委派
🧠 主 Agent 上下文
等待委派…
👤 Subagent 独立窗口
(空)
L3 · Cursor 定制

Hooks — Agent 循环里的自动化

在 Agent 读文件、改代码、跑命令、调 MCP 的各阶段插入脚本——格式化、拦截、审计。

在 .cursor/hooks.json 注册脚本,在特定事件前后执行(JSON 进 stdout 出)。

Hook 事件典型用途
afterFileEdit改完自动跑 Prettier / ESLint
beforeShellExecution拦截 git push --force、SQL 写操作
beforeMCPExecution审计 / 审批 MCP 工具调用
subagentStart / subagentStop控制、审计 Subagent 行为
workspaceOpen打开项目时加载 Plugin 路径
L3 · Cursor 定制

MCP — 接外部世界

@codebase 只能看本地代码——MCP 让 Agent 调 GitHub、Figma、Linear、浏览器等外部系统。

Model Context Protocol — Agent 的「USB 接口」。配置在 .cursor/mcp.json(项目)或 ~/.cursor/mcp.json(全局)。

{ "mcpServers": { "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_TOKEN": "${env:GITHUB_TOKEN}" } } } }

Settings → Features → MCP 可单独开关每个 Server。Agent 调用前默认要你批准(可配置 allowlist)。

🧪 Playground:MCP 工具调用链
提问
选工具
批准
回答
模拟「查 GitHub Issue #42 的状态」…
大模型 + AI 编程工具 · L0~L3 交互课