Pi - 极简又强大的 AI 编码智能体框架

"一个调用 LLM 的 while 循环,加上四个基础工具。" — Armin Ronacher & Mario Zechner

为什么 Pi 有价值

S (情境):当前 AI Agent 平台都在比拼功能复杂度,工具列表越来越长,配置越来越重。

T (任务):Pi 选择反其道而行 —— 用极简架构证明:足够强大的 LLM(如 Claude Sonnet)不需要过度设计的工具链。

A (行动):只做一件事:把 Unix 工具链的威力交给 AI。

R (结果):"Bash 就是你所需要的一切" —— 证明减法比加法更难,但也更有价值。


1. 核心循环:就是一个 while 循环

// packages/agent/src/agent-loop.ts
while (true) {  // 外层循环:处理后续消息
    while (hasMoreToolCalls || pendingMessages.length > 0) {
        // 1. 把用户消息发给 AI
        const message = await streamAssistantResponse(...);
        
        // 2. AI 说"我要用工具" → 执行 → 告诉 AI 结果
        if (toolCalls.length > 0) {
            const results = await executeToolCalls(...);
            currentContext.messages.push(...results);
        }
        
        // 3. AI 继续思考,可能还要用工具 → 重复
    }
    // 没新消息就结束,有就继续
}

人话版

没有状态机,没有工作流引擎,没有递归调用 —— 就是一个简单的"对话-执行-反馈"循环。


2. 四个基础工具

// packages/coding-agent/src/core/tools/index.ts
export const codingTools: Tool[] = [readTool, bashTool, editTool, writeTool];
工具 职责 为什么够用
read 读取文件内容 AI 需要知道代码长什么样
bash 执行 shell 命令 整个 Unix 工具链都是 AI 的延伸
edit 精确修改文件 修改现有代码
write 写入新文件 创建新文件

Pi 的哲学:不要为每个功能写新工具,让 AI 用 Bash 调用现有工具。


3. 自我扩展:技能系统 (Skill System)

核心思想:渐进式披露 (Progressive Disclosure)

// 启动时:扫描 SKILL.md 文件
export function loadSkills(options): LoadSkillsResult {
    // 从 ~/.pi/agent/skills/、.pi/skills/、--skill 参数 加载
}

// 系统提示词中:只告诉 AI"有什么技能"
export function formatSkillsForPrompt(skills: Skill[]): string {
    return `<available_skills>
  <skill>
    <name>pdf-processing</name>
    <description>Extracts text from PDF files</description>
    <location>/path/to/pdf-processing/SKILL.md</location>
  </skill>
</available_skills>`;
}

// AI 按需加载:用 read 工具读取完整 SKILL.md

热重载:Skill 就是 Markdown 文件,读取即生效,没有注册过程,没有重启需求。


4. 实时干预:转向队列 (Steering Queue)

export class Agent {
    private steeringQueue: AgentMessage[] = [];    // 转向队列(紧急)
    private followUpQueue: AgentMessage[] = [];     // 后续队列(非紧急)

    // 发送转向消息:中断当前执行
    steer(m: AgentMessage) {
        this.steeringQueue.push(m);
    }

    // 发送后续消息:等当前轮次结束后处理
    followUp(m: AgentMessage) {
        this.followUpQueue.push(m);
    }
}

区别

可迁移经验:区分"紧急"和"非紧急",给用户"干预权"。


5. 没有外部记忆:代码即真理

拒绝向量数据库、记忆银行

export interface CompactionSettings {
    reserveTokens: number;      // 预留 token 数(默认 16384)
    keepRecentTokens: number;   // 保留最近对话 token 数(默认 20000)
}

// 压缩策略:保留最近 N 个 token 的对话,更早的用 LLM 总结
export function findCutPoint(entries, keepRecentTokens) {
    // 从最新消息开始累积 token,超过限制就切断
    // 更早的内容会被 LLM 总结成摘要
}

摘要格式(结构化信息,不是向量嵌入):

可迁移经验


可迁移经验清单

工具设计

渐进式披露

用户干预

记忆管理


相关笔记