Coding Agent都需要做上下文(Context)管理。
Pi的Context管理方案逻辑很简单,其中很大一部分,就是用文档系统给Agent持久化指引。 你可以告诉它这项目里哪些代码不要乱碰、代码注释中要写你的名字等等。
其实这些东西也不只是Pi的特性,而是市面上多数Coding Agent都会遵循的行业共识。 把这些微操玩明白,你Vibe Coding水平会更上一层楼。
提示词是怎么拼出来的
我们在输入框里打出来的是用户提示词。
在用户提示词之前,模型还会收到一段系统提示词。 本文主要讨论的,就是如何控制系统提示词。
Pi的系统提示词默认按下面的顺序拼装:
flowchart LR
A["基础提示词"]
B["追加提示词"]
C["AGENTS.md"]
D["可用Skills列表"]
E["当前工作目录"]
A --> B --> C --> D --> E整个提示词结构形如:
全局与局部文档
Pi的资源可以分成两层:
- 全局:所有项目都会加载使用。核心位置是
~/.pi/agent/ - 局部:Pi的工作目录及其上层目录
在终端上cd到哪里启动pi,那pi的工作目录就是哪里。 一般推荐在项目根目录(有.git的目录)启动pi
替换基础提示词:SYSTEM.md
基础提示词是系统提示词的根基,用于讲明Agent的身份,所有工作都需要遵守的规则和用户常驻需求和偏好。
Pi的基础提示词可以直接替换,这是别的Coding Agent难以做到的。
我们只需要准备一份SYSTEM.md,把你对Pi的个人要求写进去,然后把这份文档放在Pi的扫描路径上。
Pi启动时,如果在扫描路径上扫到SYSTEM.md,就会用这份基础提示词替换自己默认的基础提示词。
SYSTEM.md 的扫描路径
Pi默认会按照如下顺序查找SYSTEM.md:
flowchart TD
C{"工作目录/.pi/SYSTEM.md 存在?"}
C -- 是 --> D["使用该局部SYSTEM.md"]
C -- 否 --> E{"~/.pi/agent/SYSTEM.md 存在?"}
E -- 是 --> F["使用全局SYSTEM.md"]
E -- 否 --> G["使用 Pi 默认系统提示词"]这里有三个细节:
-
项目级和全局级
SYSTEM.md不会一起拼接,项目级存在时,项目级胜出; -
项目级
SYSTEM.md需要项目已经被信任; -
Pi只检查
工作目录/.pi/SYSTEM.md,不会向父目录寻找。
应用
我不创建全局的SYSTEM.md,只在项目里创建局部的SYSTEM.md。
这样,每个项目都有不同的指示,让Pi的行动更有偏向、更精准。
比如一个专门用于创建web动画的仓库里,我在web-animation/.pi/SYSTEM.md里写了
你是一个web动画工程师。
你需要为用户创建高质量的html动画。
每个动画占用一个单独的子目录,入口是index.html。
用GSAP......
不要滥用圆形光晕......
追加提示词:APPEND_SYSTEM.md
大多数情况下,我们没有必要把 Pi 的默认系统提示词整个换掉。
Pi 的默认 Prompt 已经包含:
- Coding Agent 的基础身份
- 一些基础响应原则
- 安全原则
- 用户偏好
我们可以用APPEND_SYSTEM.md来写一段额外的指令,添加到基础提示词的后面。
同基础提示词一样,Pi会从两个入口扫描。 如果发现,则追加之。
全局:
~/.pi/agent/APPEND_SYSTEM.md
局部:
工作目录/.pi/APPEND_SYSTEM.md
需要有印象的是:和SYSTEM.md一样,
- 项目级存在时,不再自动拼接全局级文件;
- 它只检查当前
cwd下的.pi/,不会向父目录扫描; - 项目级文件需要项目受信任。
所以如果你不愿意再每个项目维护一个SYSTEM.md,可以用一个全局SYSTEM.md,然后在每个项目提供一个局部的APPEND_SYSTEM.md。
| 需求 | 方式 |
|---|---|
| 调整部分默认行为 | APPEND_SYSTEM.md |
| 重写Agent的基础身份与工作方式 | SYSTEM.md |
关于协作:我不建议把.pi添加到git去跟踪。 因为大家用的都是不一样的Agent。我用Pi,你用Codex,他用Trae。不是所有Agent都会扫描.pi/目录。
所以.pi/其实更应该放一些更符合个人工作流的东西。 但是如果你的团队已经拥抱pi生态,上述忽略。
指示:AGENTS.md
大多数Coding Agent都会默认注入AGENTS.md的内容,这已经成为行业约定。
一个使用多种Agent的团队需要遵守共同的规则时,往往写入项目根目录的
AGENTS.md。
所以它适合保存那些每次工作都应该知道的内容,例如:
- 项目的启动、构建和测试命令;
- 编码约定和代码风格;
- 架构边界;
- 禁止修改的文件;
- 提交前必须完成的检查。
例如:
# Project Instructions
- 使用 `uv` 管理 Python 依赖。
- 修改后运行 `uv run pytest`。
- `backend/main-agent` 是当前协议的唯一事实来源。
- 不要读取旧版文档。
- 除非需求明确要求,否则不要引入新的抽象层。
这比每次开新Session都重新提醒Agent有效得多。
Pi去哪里寻找AGENTS.md
Pi 会先加载全局指示:
~/.pi/agent/AGENTS.md
然后从当前工作目录以及一级一级的父目录里寻找:
AGENTS.override.md
AGENTS.md
CLAUDE.md
每个目录最多选中一份,优先级是:
AGENTS.override.md > AGENTS.md > CLAUDE.md
注意:大家都喜欢用AGENTS.md来当作Agent指示。Claude用自己的产品名来定义行业标准已经受到社区的口诛笔伐。
找到以后,Pi 会按“从宽泛到具体”的顺序排列:
flowchart LR
G["全局规则<br/>~/.pi/agent/AGENTS.md"]
R["更高层父目录"]
P["更近的父目录"]
C["当前目录 cwd"]
G --> R --> P --> C也就是:
- 先加载全局习惯;
- 再加载祖先目录里的大范围规则;
- 最后加载离当前工作目录最近的具体规则。
当前实现会一直向上走到文件系统根目录,并不会自动停在 Git 仓库根目录。
所以说没事别在一个范围巨大的父目录里乱放AGENTS.md。否则下面一大片项目都会继承它。
AGENTS.override.md到底覆盖谁
AGENTS.override.md并不会破坏上面所有规则。
AGENTS.override.md只是在同一个目录内,代替该目录下的AGENTS.md或CLAUDE.md。
AGENTS.md 不要写成项目百科
AGENTS.md 的正文会整份进入系统提示词。
因此它适合放:
- 几乎每次任务都用得上
- 值得长期占用上下文窗口
的项目规范。
技能:Skills
渐进式批露
Skill和之前的SYSTEM.md,AGENTS.md的区别是,之前的文档只要Pi扫描到,必定会完整添加到上下文中。
而skill只会在系统提示词中先添加摘要(描述信息),让AI只知道“有这个Skill”。
在实际工作中发现可能用得到某个skill时,Agent才会去读这个skill的完整内容。
Skills组装
Pi启动时会扫描Skill目录,读取每个Skill的元信息,并把下面这些信息组成索引:
name;description;location。
系统提示词里出现的内容大致长这样:
<available_skills>
<skill>
<name>simplify-code</name>
<description>
审查并简化过度工程化的代码。用于减少无意义抽象、
防御性分支、重复封装和未被需求支持的扩展点。
</description>
<location>
/Users/you/.pi/agent/skills/simplify-code/SKILL.md
</location>
</skill>
</available_skills>
Skill扫描路径
Pi会从下面几类位置加载Skills。
全局
~/.pi/agent/skills/
~/.agents/skills/
局部
工作目录/.pi/skills/
以及
.agents/skills/
但两者扫描方式不同:
.pi/skills/只检查当前当前工作目录下的.pi目录;.agents/skills/会从当前工作目录向祖先目录扫描,在Git仓库中通常停在仓库根目录;不在Git仓库时,可以继续到文件系统根目录。
项目级Skills也需要当前项目已经被信任。
整个过程大致为:
flowchart TD
A["Pi启动"] --> B["扫描Skill目录"]
B --> C["提取 name、description、location"]
C --> D["把 XML 索引写入 system prompt"]
D --> E{"大模型思考:当前任务是否匹配某个Skill?"}
E -- 否 --> F["正常处理任务"]
E -- 是 --> G["读取完整SKILL.md"]
G --> H["按需读取scripts/references/assets"]
H --> I["按照Skill工作流执行"]一个最小Skill
目录结构
Skill 通常是一个包含 SKILL.md 的目录:
simplify-code/
├── SKILL.md
├── scripts/
│ └── measure-complexity.sh
└── references/
└── rules.md
必须要有SKILL.md才能被检测到,其余的scripts/,references/是附加的引用补充,不是必须的。
SKILL.md头部
SKILL.md需要在头部放入放入元信息才能被识别
---
name: simplify-code
description: 审查并简化过度工程化的代码。用于减少无意义抽象、防御性分支、重复封装和未被需求支持的扩展点。
---
# Simplify Code
开始修改前,先识别:
1. 没有实际调用方的抽象层;
2. 只处理理论边缘情况的代码;
3. 重复的数据结构与转换流程;
4. 可以直接表达,却被包装了很多层的逻辑。
修改完成后运行项目测试。
其中 description 非常关键。
它不是展示给人看的装饰语,而是模型判断“这次要不要加载这个 Skill”的路由信息。
总结
越干净的上下文,往往意味着Agent更高的思考深度和更好的任务完成质量。
所以上下文管理是Vibe Coding进阶不得不品的一环。
掌握上面的技巧可以让你的Agent提示词更加精简,也可以定制针对细分任务的专用Agent。




评论
正在读取讨论…