<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Pi on yzchen.space</title>
    <link>https://www.yzchen.space/tags/pi/</link>
    <description>Recent content in Pi on yzchen.space</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Thu, 23 Jul 2026 12:00:00 +0800</lastBuildDate>
    <atom:link href="https://www.yzchen.space/tags/pi/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>oh-my-pi 功能详解：Pi 与 omp 的关系及特性</title>
      <link>https://www.yzchen.space/posts/20260723/oh-my-pi-features/</link>
      <pubDate>Thu, 23 Jul 2026 12:00:00 +0800</pubDate>
      <guid>https://www.yzchen.space/posts/20260723/oh-my-pi-features/</guid>
      <description>&lt;h2 id=&#34;pi-和-oh-my-pi-的关系&#34;&gt;Pi 和 oh-my-pi 的关系&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/badlogic/pi-mono&#34;&gt;Pi&lt;/a&gt; 是 Mario Zechner 在 2025 年 8 月创建的编码代理项目，纯 TypeScript。oh-my-pi（omp）是 Can Bölük 从 Pi fork 出来的独立项目，两个项目各自发展。omp 会定期从 Pi 合并上游变更。&lt;/p&gt;&#xA;&lt;h3 id=&#34;规模对比&#34;&gt;规模对比&lt;/h3&gt;&#xA;&lt;p&gt;Pi 至今约 20 万行 TypeScript，没有 Rust，4 个包，4,600 多个 commit。omp 约 112 万行 TypeScript 加 17 万行 Rust，16 个包加 8 个 Rust crate，14,000 多个 commit。&lt;/p&gt;&#xA;&lt;p&gt;两个项目有四个同名包（fork 时的原始包），各自独立发展后规模差距很大：&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th style=&#34;text-align: left&#34;&gt;包&lt;/th&gt;&#xA;          &lt;th style=&#34;text-align: left&#34;&gt;Pi 当前&lt;/th&gt;&#xA;          &lt;th style=&#34;text-align: left&#34;&gt;omp 当前&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;ai（LLM 接口）&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;58K&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;188K&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;agent（运行时）&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;14K&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;26K&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;coding-agent（CLI）&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;104K&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;631K&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;tui（终端 UI）&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;26K&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;61K&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;差距最大的 coding-agent，Pi 那边是 agent 的核心流程（会话管理、工具调度、RPC 模式），omp 在这个基础上加进了下面要介绍的所有功能。&lt;/p&gt;</description>
    </item>
    <item>
      <title>PiAgent 系列 7：pi-subagents 工作流编排</title>
      <link>https://www.yzchen.space/posts/20260719/pi-subagents-workflows/</link>
      <pubDate>Sun, 19 Jul 2026 12:00:00 +0800</pubDate>
      <guid>https://www.yzchen.space/posts/20260719/pi-subagents-workflows/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;上篇介绍了如何自定义 agent 以及 pi-subagents 的三个设计约束：&lt;code&gt;systemPromptMode: replace&lt;/code&gt;、子 agent 不能自由嵌套、以及 &lt;code&gt;contact_supervisor&lt;/code&gt; 反向通道。这些约束决定了 pi-subagents 的编排风格，多 agent 协作主要靠文件交接，复杂流程由父 session 显式编排。本文在此基础上，介绍两种核心编排模式：Parallel 并行与 Chain 链式，以及工作流的保存、复用、管理和诊断。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;parallel并行编排&#34;&gt;Parallel：并行编排&lt;/h2&gt;&#xA;&lt;p&gt;Parallel 是最简单的编排形式：多个 agent 同时跑，互不干扰。&lt;/p&gt;&#xA;&lt;h3 id=&#34;基础并行&#34;&gt;基础并行&lt;/h3&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/parallel \&#xA;  reviewer &amp;#34;审查安全性&amp;#34; \&#xA;  -&amp;gt; reviewer &amp;#34;审查性能&amp;#34; \&#xA;  -&amp;gt; reviewer &amp;#34;审查可维护性&amp;#34;&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;三个 reviewer 同时开始，互不干扰。所有结果汇总后一条消息返回主会话。&lt;/p&gt;&#xA;&lt;h3 id=&#34;共享任务&#34;&gt;共享任务&lt;/h3&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/parallel scout researcher -- 深度分析支付模块&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;scout 扫代码 + researcher 线上搜，同一个任务，两种角度，并行完成。&lt;/p&gt;&#xA;&lt;h3 id=&#34;差异化配置&#34;&gt;差异化配置&lt;/h3&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/parallel \&#xA;  reviewer[model=deepseek-v4-pro,skills=security] &amp;#34;审查安全性&amp;#34; \&#xA;  -&amp;gt; reviewer[model=deepseek-v4-flash] &amp;#34;审查代码风格&amp;#34;&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;同一个 agent 类型，不同模型和技能承担不同子任务。&lt;/p&gt;&#xA;&lt;h3 id=&#34;并行结果的传递&#34;&gt;并行结果的传递&lt;/h3&gt;&#xA;&lt;p&gt;并行步骤的子 agent 结果按以下格式汇总，用分隔线区分：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=== Parallel Task 1 (reviewer) ===&#xA;...审查结果...&#xA;&#xA;=== Parallel Task 2 (reviewer) ===&#xA;...审查结果...&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果 parallel 是 chain 里的一步，汇总文本会作为整步的 &lt;code&gt;{previous}&lt;/code&gt; 传给下一步。&lt;/p&gt;</description>
    </item>
    <item>
      <title>PiAgent 系列 6：pi-subagents 自定义子智能体</title>
      <link>https://www.yzchen.space/posts/20260718/pi-subagents-custom-agents/</link>
      <pubDate>Sat, 18 Jul 2026 12:00:00 +0800</pubDate>
      <guid>https://www.yzchen.space/posts/20260718/pi-subagents-custom-agents/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;上篇介绍了 pi-subagents 的概念、8 个内置角色、fork/fresh 机制与模型/技能继承。本文继续深入：如何定制 agent，以及 pi-subagents 为什么要这样设计——理解这些底层约束，是后续编排工作流的前提。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;自定义-agent&#34;&gt;自定义 Agent&lt;/h2&gt;&#xA;&lt;p&gt;内置的 8 个角色已经覆盖了大多数场景，但实际项目中往往要微调：让 reviewer 用更强的模型、给 scout 关掉网络搜索、或者加一个只负责安全审计的专属角色。pi-subagents 提供了两类自定义方式：一类是通过配置项 &lt;code&gt;agentOverrides&lt;/code&gt; 覆盖内置 agent 的元数据；另一类是通过 &lt;code&gt;.md&lt;/code&gt; 文件创建或覆盖 agent 定义，同名文件会覆盖内置角色，新名字则作为补充角色。&lt;/p&gt;&#xA;&lt;h3 id=&#34;通过配置覆盖agentoverrides&#34;&gt;通过配置覆盖：agentOverrides&lt;/h3&gt;&#xA;&lt;p&gt;&lt;code&gt;agentOverrides&lt;/code&gt; 是 Pi settings 中 &lt;code&gt;subagents&lt;/code&gt; 下的一个配置对象，写在项目 &lt;code&gt;.pi/settings.json&lt;/code&gt; 或用户 &lt;code&gt;~/.pi/agent/settings.json&lt;/code&gt; 里。它用来覆盖内置 agent 的元数据，不需要新建 agent 文件。其特点是：不改 prompt，只调模型、thinking、默认上下文等配置。适合快速对齐不同项目的需求。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;&amp;#34;subagents&amp;#34;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;&amp;#34;agentOverrides&amp;#34;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;&amp;#34;reviewer&amp;#34;&lt;/span&gt;: { &lt;span style=&#34;font-weight:bold&#34;&gt;&amp;#34;model&amp;#34;&lt;/span&gt;: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;deepseek-v4-pro&amp;#34;&lt;/span&gt;, &lt;span style=&#34;font-weight:bold&#34;&gt;&amp;#34;thinking&amp;#34;&lt;/span&gt;: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;high&amp;#34;&lt;/span&gt;, &lt;span style=&#34;font-weight:bold&#34;&gt;&amp;#34;defaultContext&amp;#34;&lt;/span&gt;: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;fork&amp;#34;&lt;/span&gt; },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;&amp;#34;scout&amp;#34;&lt;/span&gt;: { &lt;span style=&#34;font-weight:bold&#34;&gt;&amp;#34;model&amp;#34;&lt;/span&gt;: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;deepseek-v4-flash&amp;#34;&lt;/span&gt; },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;&amp;#34;researcher&amp;#34;&lt;/span&gt;: { &lt;span style=&#34;font-weight:bold&#34;&gt;&amp;#34;disabled&amp;#34;&lt;/span&gt;: &lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;disabled: true&lt;/code&gt; 隐藏不需要的内置 agent。&lt;code&gt;subagents.disableBuiltins: true&lt;/code&gt; 一次性禁用所有内置 agent（如果只用自定义角色）。&lt;/p&gt;&#xA;&lt;h3 id=&#34;通过-md-文件创建或覆盖&#34;&gt;通过 .md 文件创建或覆盖&lt;/h3&gt;&#xA;&lt;p&gt;在项目或用户目录创建 &lt;code&gt;.md&lt;/code&gt; 文件即可定义 agent。如果文件名与内置 agent 同名，就会覆盖内置角色；如果取新名字，就会新增一个补充角色。&lt;/p&gt;</description>
    </item>
    <item>
      <title>PiAgent 系列 5：用 pi-subagents 召唤子智能体</title>
      <link>https://www.yzchen.space/posts/20260716/pi-subagents-introduction/</link>
      <pubDate>Thu, 16 Jul 2026 12:00:00 +0800</pubDate>
      <guid>https://www.yzchen.space/posts/20260716/pi-subagents-introduction/</guid>
      <description>&lt;p&gt;Pi 的 README 里有一段说明他们的 Philosophy，其中关于 sub-agent 的态度明确：&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;No sub-agents.&lt;/strong&gt; There&amp;rsquo;s many ways to do this. Spawn pi instances via tmux, or build your own with [extensions], or install a package that does it your way.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;翻译过来就是：核心不内置 sub-agent，因为做法有很多，有人想要 tmux 协同，有人想自己写扩展，有人喜欢树状分解。Pi 不替用户做选择，而是把扩展系统作为土壤，让社区或者用户长出自己想要的方案。&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;pi-subagents&lt;/code&gt; 就是其中一个实现，它的下载量跟 &lt;code&gt;pi-web-access&lt;/code&gt; 差不多是安装量最多的几个 pi 社区插件之一，一是说明虽然 pi 故意留了白但是社区确实有这方面的需求，另一方面也是因为它的设计足够优秀。&lt;/p&gt;&#xA;&lt;p&gt;举一个实际工作中的场景，在进行某个项目的开发中通常包括：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;理解代码 → 制定计划 → 实施 → 审查 → 修复&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;每一步的输出是下一步的输入，每一步都可能需要不同的&amp;quot;专长&amp;quot;：理解代码要快准狠（低 thinking），审查要严谨全面（高 thinking），实施要精确改动（会写文件但不会越权做决策）。&lt;/p&gt;&#xA;&lt;p&gt;这就是子 agent 的用武之地：&lt;strong&gt;把每一步交给最合适的&amp;quot;分身&amp;quot;去跑，主 agent 负责编排和决策。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;实际效果：你只需要说一句「分析 auth 模块，制定重构方案，然后实施」，Pi 就会自动调起 scout → planner → worker 三条 agent 串行执行，然后坐等结果。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Pi 与沙箱</title>
      <link>https://www.yzchen.space/posts/20260715/pi-sandbox-security/</link>
      <pubDate>Wed, 15 Jul 2026 12:00:00 +0800</pubDate>
      <guid>https://www.yzchen.space/posts/20260715/pi-sandbox-security/</guid>
      <description>&lt;h2 id=&#34;为什么只靠正则拦截命令不够&#34;&gt;为什么只靠正则拦截命令不够&lt;/h2&gt;&#xA;&lt;p&gt;在之前介绍 pi 的扩展系统时，我展示了一个 &lt;code&gt;permission-gate.ts&lt;/code&gt; 的例子，用正则表达式拦截危险命令：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-style:italic&#34;&gt;// permission-gate 的思路：正则匹配，匹配到就弹窗确认&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; rules = [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  { pattern: &lt;span style=&#34;font-style:italic&#34;&gt;/\bfind\s+\/(?![a-zA-Z0-9_./])/i&lt;/span&gt;, label: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;find-root&amp;#34;&lt;/span&gt; },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;];&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这种基于模式匹配的&amp;quot;权限门&amp;quot;看似有用，但在现代大模型面前形同虚设。一个足够聪明的 LLM 可以轻松绕过&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 绕过正则的方式：&#xA;find . -path &amp;#39;*&amp;#39;              # 等价 find /&#xA;x=&amp;#34;f&amp;#34;; y=&amp;#34;ind&amp;#34;; $x$y /        # 变量拼接绕过&#xA;exec 3&amp;lt;&amp;gt;/dev/tcp; ...          # 使用完全不同的原语&#xA;python -c &amp;#34;import os; ...&amp;#34;     # 用解释器写文件&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Claude Code 和 Codex 等主流 agent 的做法是：&lt;strong&gt;在权限规则之外，再加一层操作系统层面的沙箱隔离&lt;/strong&gt;。权限规则控制&amp;quot;能不能执行&amp;quot;，沙箱控制&amp;quot;执行后能碰什么&amp;quot;两者互补。一旦沙箱生效，不管 LLM 想出多诡异的命令，它也破坏不了沙箱允许范围之外的东西。&lt;/p&gt;&#xA;&lt;h2 id=&#34;沙箱做什么&#34;&gt;沙箱做什么&lt;/h2&gt;&#xA;&lt;p&gt;讲沙箱之前，先从最熟悉的 Docker 开始。&lt;/p&gt;&#xA;&lt;h3 id=&#34;从-docker-到沙箱&#34;&gt;从 Docker 到沙箱&lt;/h3&gt;&#xA;&lt;p&gt;Docker 大家应该都用过&lt;code&gt;docker run&lt;/code&gt; 起一个容器，里面有独立的文件系统，端口要显式映射才能访问。这其实就是一个比较重的沙箱实现。&lt;/p&gt;&#xA;&lt;p&gt;但当前主流的 agent 的沙箱一般不用 Docker。原因是 agent 要把你的项目目录挂进去让 LLM 改代码，还要实时拿到 stdout/stderr 反馈给 LLM，每次跑一条命令就起一个容器实在太慢了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>用 Pi 学习 Agent 怎么运行</title>
      <link>https://www.yzchen.space/posts/20260709/learning-agent-harness-with-pi/</link>
      <pubDate>Thu, 09 Jul 2026 12:00:00 +0800</pubDate>
      <guid>https://www.yzchen.space/posts/20260709/learning-agent-harness-with-pi/</guid>
      <description>&lt;h2 id=&#34;pi-是学习-harness-的好帮手&#34;&gt;pi 是学习 harness 的好帮手&lt;/h2&gt;&#xA;&lt;p&gt;想搞懂一个 agent 到底怎么跑起来，最好的办法不是读别人的文章，而是拿一个真正可观察的 agent 自己跑一遍。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;agent = model + harness&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;model&lt;/strong&gt; 做的事很单纯——收到一个 &lt;code&gt;messages&lt;/code&gt; 列表，返回一段文本。它不知道文件系统在哪、不知道你项目里有什么、不知道上一次对话发生了什么。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;harness&lt;/strong&gt;（中文是缰绳还是线束什么的，随便把，反正是把模型和外部环境连起来的那一层）是让模型&amp;quot;变聪明&amp;quot;的关键：它把模型包进一个循环，负责拼装上下文、调用工具、把结果塞回下一轮对话。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;harness 的核心是一个循环：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;拼装 &lt;code&gt;system prompt&lt;/code&gt; + 历史消息 → HTTP 请求体&lt;/li&gt;&#xA;&lt;li&gt;发给模型 API，拿到响应&lt;/li&gt;&#xA;&lt;li&gt;解析响应——是普通文本还是 tool call？是 tool call 就执行&lt;/li&gt;&#xA;&lt;li&gt;把执行结果塞进下一轮的 &lt;code&gt;messages&lt;/code&gt;，回到第 1 步&lt;/li&gt;&#xA;&lt;li&gt;模型不再调工具，结束&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;想理解 agent，就得理解这个循环。而 pi 是学这个最好的工具。&lt;/p&gt;&#xA;&lt;h2 id=&#34;例如可以让它帮你理解-harness-过程因为它极度透明&#34;&gt;例如可以让它帮你理解 harness 过程，因为它极度透明&lt;/h2&gt;&#xA;&lt;p&gt;大多数 agent 工具把和模型的对话过程藏起来，你只能看到最终输出的文本。pi 不一样：它把整个生命周期都暴露成事件——session 启动、消息拼装、API 请求发出去之前、响应回来之后、工具执行……每一个节点你都能插手。&lt;/p&gt;&#xA;&lt;p&gt;换句话说，harness 在 pi 里不是黑盒，而是一组你能监听的事件。理解 agent 怎么运行，本质上就是理解 harness 在那个循环里做了什么——而 pi 让你直接看见它，甚至改写它。&lt;/p&gt;&#xA;&lt;h2 id=&#34;比如我们可以让它展示在请求大模型时发送的-http-内容&#34;&gt;比如我们可以让它展示在请求大模型时发送的 HTTP 内容&lt;/h2&gt;&#xA;&lt;p&gt;一个直接的例子：让 pi 展示它发给大模型 API 的完整请求。我写了一个 extension &lt;code&gt;model-api-inspector&lt;/code&gt; 做这件事——监听 provider 的请求 / 响应事件，把每次调用的 request body 和 response body 都渲染到终端里：&lt;/p&gt;</description>
    </item>
    <item>
      <title>Pi Web Access 介绍</title>
      <link>https://www.yzchen.space/posts/20260706/pi-web-access/</link>
      <pubDate>Mon, 06 Jul 2026 12:00:00 +0800</pubDate>
      <guid>https://www.yzchen.space/posts/20260706/pi-web-access/</guid>
      <description>&lt;h2 id=&#34;这是什么&#34;&gt;这是什么&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;pi-web-access&lt;/strong&gt; 是 Pi 生态里最常用的第三方 package，给 Pi 接入网络。本质上是把 web_search、网页抓取、GitHub 仓库、YouTube/本地视频分析、PDF 提取等能力，封装成 Pi 的 extension + skill，安装后 Pi 可以直接上网查资料。&lt;/p&gt;&#xA;&lt;p&gt;作者是 &lt;a href=&#34;https://github.com/nicobailon&#34;&gt;Nico Bailon&lt;/a&gt;，仓库在 &lt;a href=&#34;https://github.com/nicobailon/pi-web-access&#34;&gt;github.com/nicobailon/pi-web-access&lt;/a&gt;。&lt;/p&gt;&#xA;&lt;h2 id=&#34;安装&#34;&gt;安装&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pi install npm:pi-web-access&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;安装后放在 &lt;code&gt;~/.pi/agent/npm/node_modules/pi-web-access/&lt;/code&gt;，不是 &lt;code&gt;~/.pi/agent/extensions/&lt;/code&gt; 目录。它作为 Pi Package 安装，不需要手动管理扩展文件。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;零配置可用：&lt;/strong&gt; 不需要任何 API key。默认走 Exa MCP（免费），如果你恰好有 Codex 订阅，OpenAI 搜索也能复用认证。&lt;/p&gt;&#xA;&lt;p&gt;如果觉得不如意，可以给别的搜索提供商配 API key。&lt;/p&gt;&#xA;&lt;h2 id=&#34;三个工具&#34;&gt;三个工具&lt;/h2&gt;&#xA;&lt;p&gt;安装后 Pi 会多出三个 LLM 可调用的工具。&lt;/p&gt;&#xA;&lt;h3 id=&#34;1-web_search--联网搜索&#34;&gt;1. web_search — 联网搜索&lt;/h3&gt;&#xA;&lt;p&gt;最常用。支持单条 &lt;code&gt;query&lt;/code&gt; 或批量 &lt;code&gt;queries&lt;/code&gt;（推荐一次搜 2-4 条不同角度，覆盖面更宽）：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;web_search({ query: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;rust async programming&amp;#34;&lt;/span&gt; })&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;web_search({ queries: [&lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;react 性能优化 2025&amp;#34;&lt;/span&gt;, &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;react concurrent mode 原理&amp;#34;&lt;/span&gt;] })&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;web_search({ query: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;...&amp;#34;&lt;/span&gt;, numResults: &lt;span style=&#34;&#34;&gt;10&lt;/span&gt;, recencyFilter: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;week&amp;#34;&lt;/span&gt; })&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;web_search({ query: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;...&amp;#34;&lt;/span&gt;, domainFilter: [&lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;github.com&amp;#34;&lt;/span&gt;, &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;-reddit.com&amp;#34;&lt;/span&gt;] })&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;web_search({ query: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;...&amp;#34;&lt;/span&gt;, provider: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;openai&amp;#34;&lt;/span&gt; })&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;web_search({ query: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;...&amp;#34;&lt;/span&gt;, includeContent: &lt;span style=&#34;&#34;&gt;true&lt;/span&gt; })&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;工作流选项：&lt;/p&gt;</description>
    </item>
    <item>
      <title>Pi Session 管理：tree、fork、clone 与 handoff</title>
      <link>https://www.yzchen.space/posts/20260705/pi-session-management/</link>
      <pubDate>Sun, 05 Jul 2026 12:00:00 +0800</pubDate>
      <guid>https://www.yzchen.space/posts/20260705/pi-session-management/</guid>
      <description>&lt;p&gt;最喜欢 Pi 的特性之一就是对 session 的管理很方便。Pi 的 session 不是线性的——它是树形的。每次回溯到某个历史节点重新发消息，就会在那个点分出一个新分支。&lt;/p&gt;&#xA;&lt;h2 id=&#34;先看-session-长什么样&#34;&gt;先看 session 长什么样&lt;/h2&gt;&#xA;&lt;p&gt;下面是一段典型的对话树：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;user: &amp;#34;帮我写一个排序函数&amp;#34;&#xA;└─ assistant: &amp;#34;这是冒泡排序...&amp;#34;&#xA;   ├─ user: &amp;#34;改成快排&amp;#34; → assistant: &amp;#34;这是快速排序...&amp;#34;&#xA;   │  └─ user: &amp;#34;加注释&amp;#34; → assistant: &amp;#34;已加注释&amp;#34;  ← 当前活跃&#xA;   └─ user: &amp;#34;用 Rust 写&amp;#34; → assistant: &amp;#34;这是 Rust 版本...&amp;#34;&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;你随时可以回到&amp;quot;帮我写一个排序函数&amp;quot;或&amp;quot;改成快排&amp;quot;那个点，走另一条路。走了新路之后，原来的分支不会消失——它还保存在同一个 session 文件里。这就是 Pi 的 &lt;code&gt;/tree&lt;/code&gt; ，目前 Claude Code 和 Codex 都还没有到特性。&lt;/p&gt;&#xA;&lt;h2 id=&#34;tree-同一session内切换分支&#34;&gt;&lt;code&gt;/tree&lt;/code&gt; — 同一Session内切换分支&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;不创建新 session 文件。&lt;/strong&gt; 打开一个树形导航器，显示当前 session 的全部对话节点。&lt;/p&gt;&#xA;&lt;p&gt;在 &lt;code&gt;/tree&lt;/code&gt; 里你可以：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;选一条用户消息&lt;/strong&gt;：光标移到该消息的父节点，编辑器预填那条消息的原文，你可以修改后重新提交——形成新分支&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;选一条 assistant 消息或工具结果&lt;/strong&gt;：光标移到该消息位置，编辑器为空，直接从那个点继续&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;切换分支时&lt;/strong&gt;：Pi 可以（可选）把&amp;quot;被抛弃的分支&amp;quot;总结成一段摘要，附到新位置。这样不用回看旧分支也能知道那边发生了什么&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;常用按键：&lt;code&gt;↑↓&lt;/code&gt; 浏览、&lt;code&gt;Enter&lt;/code&gt; 选择、&lt;code&gt;Esc&lt;/code&gt; 取消、&lt;code&gt;Shift+L&lt;/code&gt; 打标签、&lt;code&gt;Ctrl+O&lt;/code&gt; 切换过滤模式（默认/隐藏工具结果/只看用户消息/只看有标签的）。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Pi Extensions 进阶：从安装社区扩展到自己定制</title>
      <link>https://www.yzchen.space/posts/20260704/pi-extensions-advanced/</link>
      <pubDate>Sat, 04 Jul 2026 12:00:00 +0800</pubDate>
      <guid>https://www.yzchen.space/posts/20260704/pi-extensions-advanced/</guid>
      <description>&lt;p&gt;前一篇笔记讲了 extension 是什么、有什么示例、怎么写。这篇记录实际使用——怎么从官方和社区安装、以及怎么根据需求自己改造。&lt;/p&gt;&#xA;&lt;h2 id=&#34;一先自己写个简单的show-system-prompt&#34;&gt;一、先自己写个简单的：show-system-prompt&lt;/h2&gt;&#xA;&lt;h3 id=&#34;动机&#34;&gt;动机&lt;/h3&gt;&#xA;&lt;p&gt;Agent 的系统提示词由多个来源拼合而成——角色定位、工具列表、AGENTS.md、项目上下文、技能清单。Claude/Openclaw 这样的 Agent 内置系统提示词就能吃掉几千个 token。但是像 Pi 这种我们可以轻松写一个 Extention 调试提示词效果，看一眼&amp;quot;LLM 当前实际收到的 prompt 到底是什么&amp;quot;。一个 &lt;code&gt;/system-prompt&lt;/code&gt; 命令，把完整内容打印到终端。写&lt;/p&gt;&#xA;&lt;p&gt;主要就两步：&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;捕获提示词。&lt;/strong&gt; 通过 &lt;code&gt;before_agent_start&lt;/code&gt; 事件捕获 Pi 发给 LLM 的完整 system prompt，存到变量里。这是&amp;quot;post-chained&amp;quot;的值——即所有 extension 修改之后、实际发送之前的版本。如果命令被调用时还没有 turn 跑过，就降级用 &lt;code&gt;ctx.getSystemPrompt()&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;全屏覆盖层显示。&lt;/strong&gt; 用 &lt;code&gt;ctx.ui.custom()&lt;/code&gt; 打开一个覆盖层，渲染 prompt 全文。&lt;code&gt;handleInput&lt;/code&gt; 监听 &lt;code&gt;Escape&lt;/code&gt; 或 &lt;code&gt;q&lt;/code&gt; 关闭，&lt;code&gt;render&lt;/code&gt; 用 &lt;code&gt;wrapTextWithAnsi&lt;/code&gt; 处理终端宽度换行。加了宽度缓存，只在终端尺寸变化时重新计算。&lt;/p&gt;&#xA;&lt;h3 id=&#34;示例代码&#34;&gt;示例代码&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt; { ExtensionAPI } &lt;span style=&#34;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;@earendil-works/pi-coding-agent&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;import&lt;/span&gt; { Key, matchesKey, wrapTextWithAnsi } &lt;span style=&#34;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;@earendil-works/pi-tui&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;default&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; (pi: &lt;span style=&#34;&#34;&gt;ExtensionAPI&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;let&lt;/span&gt; lastPrompt: &lt;span style=&#34;&#34;&gt;string&lt;/span&gt; | &lt;span style=&#34;font-weight:bold&#34;&gt;undefined&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  pi.on(&lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;before_agent_start&amp;#34;&lt;/span&gt;, (event) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lastPrompt = event.systemPrompt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  pi.registerCommand(&lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;system-prompt&amp;#34;&lt;/span&gt;, {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    description: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;Print the current session&amp;#39;s system prompt&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    handler: &lt;span style=&#34;&#34;&gt;async&lt;/span&gt; (_args, ctx) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; prompt = lastPrompt ?? ctx.getSystemPrompt();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (ctx.mode !== &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;tui&amp;#34;&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ctx.ui.notify(prompt, &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;info&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;await&lt;/span&gt; ctx.ui.custom&amp;lt;&lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt;&amp;gt;((_tui, _theme, _kb, done) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;let&lt;/span&gt; cachedWidth = 0;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;let&lt;/span&gt; cachedLines: &lt;span style=&#34;&#34;&gt;string&lt;/span&gt;[] = [];&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          render(width: &lt;span style=&#34;&#34;&gt;number&lt;/span&gt;): &lt;span style=&#34;&#34;&gt;string&lt;/span&gt;[] {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (width !== cachedWidth) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              cachedWidth = width;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              cachedLines = wrapTextWithAnsi(prompt, width);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; cachedLines;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          handleInput(data: &lt;span style=&#34;&#34;&gt;string&lt;/span&gt;): &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (matchesKey(data, Key.escape) || data === &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;q&amp;#34;&lt;/span&gt;) done();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          invalidate(): &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; { cachedWidth = 0; },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;结果&#34;&gt;结果&lt;/h3&gt;&#xA;&lt;p&gt;输入 &lt;code&gt;/system-prompt&lt;/code&gt; 后，终端全屏显示 Pi 当前 session 的完整系统提示词：&lt;/p&gt;</description>
    </item>
    <item>
      <title>Pi Extensions 入门指南</title>
      <link>https://www.yzchen.space/posts/20260702/pi-extensions-intro/</link>
      <pubDate>Thu, 02 Jul 2026 12:00:00 +0800</pubDate>
      <guid>https://www.yzchen.space/posts/20260702/pi-extensions-intro/</guid>
      <description>&lt;h2 id=&#34;pi-的-extension-是什么&#34;&gt;Pi 的 Extension 是什么&lt;/h2&gt;&#xA;&lt;p&gt;Extension（扩展）是 Pi 的 TypeScript 插件系统，也是它可扩展性体系中最核心的一环。你可以把它理解成给 Pi 写&amp;quot;插件&amp;quot;，用来定制它的行为、添加新能力，或者接入外部系统。&lt;/p&gt;&#xA;&lt;p&gt;Pi 的哲学是&amp;quot;不把工作流强加给你&amp;quot;，所以像权限控制、子代理、plan mode 这些其他工具内置的功能，Pi 全都不做——而是把能力交给 extension，让你自己决定怎么做。写一个 extension、或者装一个别人写好的 Pi Package，就能把 Pi 调整成你想要的形状，不需要 fork 源码。&lt;/p&gt;&#xA;&lt;p&gt;具体来说，extension 能做这些事情：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;注册自定义工具&lt;/strong&gt;，让 LLM 在对话中可以调用 —— 比如一个 &lt;code&gt;deploy&lt;/code&gt; 工具、一个 &lt;code&gt;todo&lt;/code&gt; 工具&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;拦截事件&lt;/strong&gt;，在关键节点插手 —— 比如 LLM 想执行 &lt;code&gt;rm -rf&lt;/code&gt; 的时候弹窗问你要不要放行&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;和用户交互&lt;/strong&gt;，弹确认框、选择列表、输入框、通知&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;构建自定义 UI&lt;/strong&gt;，从简单的状态栏文字，到完全接管编辑器，到游戏覆盖层&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;注册命令&lt;/strong&gt;，添加 &lt;code&gt;/mycommand&lt;/code&gt; 这样的自定义斜杠命令&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;持久化状态&lt;/strong&gt;，让数据跨重启存活，还能随着 session 的分支自动正确还原&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;自定义渲染&lt;/strong&gt;，控制工具调用的结果在终端里怎么展示&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;它还覆盖了 Pi 运行的完整生命周期——从 session 启动、LLM 对话开始、每个 turn、每次工具调用、到 session 关闭，几乎所有环节都可以插入逻辑。所以 extension 不光能&amp;quot;加功能&amp;quot;，也能&amp;quot;改行为&amp;quot;。&lt;/p&gt;&#xA;&lt;h2 id=&#34;快速看一眼代码&#34;&gt;快速看一眼代码&lt;/h2&gt;&#xA;&lt;p&gt;一个最简 extension 长这样。三件事：拦截危险命令、注册一个工具、注册一个命令：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt; { ExtensionAPI } &lt;span style=&#34;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;@earendil-works/pi-coding-agent&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;import&lt;/span&gt; { Type } &lt;span style=&#34;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;typebox&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;default&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; (pi: &lt;span style=&#34;&#34;&gt;ExtensionAPI&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-style:italic&#34;&gt;// 拦截危险 bash 命令&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-style:italic&#34;&gt;&lt;/span&gt;  pi.on(&lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;tool_call&amp;#34;&lt;/span&gt;, &lt;span style=&#34;font-weight:bold&#34;&gt;async&lt;/span&gt; (event, ctx) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (event.toolName === &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;bash&amp;#34;&lt;/span&gt; &amp;amp;&amp;amp; event.input.command?.includes(&lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;rm -rf&amp;#34;&lt;/span&gt;)) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; ok = &lt;span style=&#34;font-weight:bold&#34;&gt;await&lt;/span&gt; ctx.ui.confirm(&lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;危险操作!&amp;#34;&lt;/span&gt;, &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;允许 rm -rf 吗?&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (!ok) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; { block: &lt;span style=&#34;&#34;&gt;true&lt;/span&gt;, reason: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;用户拒绝&amp;#34;&lt;/span&gt; };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-style:italic&#34;&gt;// 注册一个 LLM 可调用的工具&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-style:italic&#34;&gt;&lt;/span&gt;  pi.registerTool({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;greet&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    description: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;向某人打招呼&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    parameters: &lt;span style=&#34;&#34;&gt;Type.Object&lt;/span&gt;({ name: &lt;span style=&#34;&#34;&gt;Type.String&lt;/span&gt;() }),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;async&lt;/span&gt; execute(_id, params) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; { content: [{ &lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;, text: &lt;span style=&#34;font-style:italic&#34;&gt;`Hello, &lt;/span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;${&lt;/span&gt;params.name&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;font-style:italic&#34;&gt;!`&lt;/span&gt; }] };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-style:italic&#34;&gt;// 注册一个用户可用的命令&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-style:italic&#34;&gt;&lt;/span&gt;  pi.registerCommand(&lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;, {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    description: &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;打招呼&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    handler: &lt;span style=&#34;&#34;&gt;async&lt;/span&gt; (args, ctx) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ctx.ui.notify(&lt;span style=&#34;font-style:italic&#34;&gt;`Hello &lt;/span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;${&lt;/span&gt;args || &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;world&amp;#34;&lt;/span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;font-style:italic&#34;&gt;!`&lt;/span&gt;, &lt;span style=&#34;font-style:italic&#34;&gt;&amp;#34;info&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;放在 &lt;code&gt;~/.pi/agent/extensions/my-ext.ts&lt;/code&gt;，或者用 &lt;code&gt;pi -e ./my-ext.ts&lt;/code&gt; 立即测试。&lt;/p&gt;</description>
    </item>
    <item>
      <title>pi System Prompt 构成详解</title>
      <link>https://www.yzchen.space/posts/20260630/pi-system-prompt-internals/</link>
      <pubDate>Tue, 30 Jun 2026 12:00:00 +0800</pubDate>
      <guid>https://www.yzchen.space/posts/20260630/pi-system-prompt-internals/</guid>
      <description>&lt;p&gt;pi 的 system prompt 采用&lt;strong&gt;分层拼装&lt;/strong&gt;机制，启动时按固定顺序叠放各层，最终拼接为发送给 LLM 的完整系统提示。&lt;/p&gt;&#xA;&lt;h2 id=&#34;拼装顺序&#34;&gt;拼装顺序&lt;/h2&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;┌─────────────────────────────────────────────┐&#xA;│  ① 基础系统提示 (pi 内置)                     │&#xA;│     角色、工具说明、行为准则、文档路径           │&#xA;│     ↓ 可被替换                                │&#xA;│  ② SYSTEM.md (如存在)                        │&#xA;│     完全替换①，而非追加                        │&#xA;│     ~/.pi/agent/SYSTEM.md 或 .pi/SYSTEM.md    │&#xA;│     ↓                                        │&#xA;│  ③ APPEND_SYSTEM.md (如存在)                  │&#xA;│     追加在②之后                                │&#xA;│     ↓                                        │&#xA;│  ④ 上下文文件                                 │&#xA;│     AGENTS.md / CLAUDE.md 全部拼接            │&#xA;│     来源：全局 + 沿目录树向上收集                │&#xA;│     ↓                                        │&#xA;│  ⑤ 技能列表 (XML)                             │&#xA;│     仅名称 + 描述，遵循 Agent Skills 规范       │&#xA;│     ↓                                        │&#xA;│  ⑥ 最终 System Prompt → 发送给 LLM            │&#xA;└─────────────────────────────────────────────┘&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;工具-schema-不在-system-prompt-中&#34;&gt;工具 Schema 不在 system prompt 中&lt;/h3&gt;&#xA;&lt;p&gt;工具定义（&lt;code&gt;read&lt;/code&gt;、&lt;code&gt;write&lt;/code&gt;、&lt;code&gt;edit&lt;/code&gt;、&lt;code&gt;bash&lt;/code&gt; 及扩展注册的自定义工具）作为 API 请求的 &lt;code&gt;tools&lt;/code&gt; 参数单独传递，&lt;strong&gt;不进入 system prompt 正文&lt;/strong&gt;。system prompt 中只包含工具的简要描述说明。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
