1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pi Agent のシステムプロンプトは短い。でも組み立て方は参考になる

1
Posted at

初めに

最近、コーディングエージェントの pi(@earendil-works/pi-coding-agent)をよく使っています。

使い続けていて、あるとき疑問に思うようになりました。

「このエージェントのシステムプロンプト、一体どこに何が入っているんだろう。」

そこで pi のソースコードを掘り下げて、プロンプトの組み立て部分まで分解してみました。

結果は意外でした。

pi のシステムプロンプトは、長い固定テキストではないんです。
固定部分は 20 行ちょっとの小さなテンプレートで、残りは各ツールやプロジェクトファイルがそれぞれ「寄与」して、起動ごとに動的に組み立てられています。

この記事では、次の 3 つを整理します。

1. pi のシステムプロンプトの組み立て機構(コードベースで)
2. システムプロンプトの原文(英語)と日本語訳
3. 自分のエージェントのプロンプトを書くときに使える設計パターン

対象読者は、AI エージェントの開発をしていて、自前エージェントのシステムプロンプトを書きたい(あるいは見直したい)技術者です。
単なる概要ではなく、組み立てコード、プロンプト原文、実装上で効いてくる判断ポイントまで書きます。

結論

先に結論を書くと、pi のプロンプト設計は「小さいテンプレート + ツール単位の寄与」です。

システムプロンプト =
  1. 固定テンプレート(persona + ツール欄 + ガイドライン欄 + docs ポインタ)
+ 2. 各ツールの 1 行紹介        (promptSnippet)
+ 3. 各ツールの利用ルール       (promptGuidelines)
+ 4. 追記テキスト               (APPEND_SYSTEM.md)
+ 5. プロジェクト指示           (AGENTS.md / CLAUDE.md)
+ 6. スキル・インデックス       (名前 + 説明 + パスのみ)
+ 7. 作業ディレクトリ

設計上の大事な点は 4 つあります。

- 固定テンプレートは小さくする。強調すべき詳細はツール側へ寄せる
- ツール紹介・ルールはツール定義本体に持つ(単一の真実の情報源)
- プロンプトは有効なツールに合わせて条件分岐する
- ナレッジ(スキル)は全文ではなくインデックスだけ載せて、必要時に読む

先に組み立てコードを見てから、原文と日本語訳をゆっくり読みます。

1. 出所: 1 つの関数 buildSystemPrompt がプロンプトを組む

pi のシステムプロンプトは、pi-coding-agent 内の 1 関数、buildSystemPrompt が生成しています。

GitHub:  earendil-works/pi(packages/coding-agent)
npm:     @earendil-works/pi-coding-agent(この記事執筆時は 0.84.2)
関数:    src/core/system-prompt.ts の buildSystemPrompt

オプションの形は次です。

export interface BuildSystemPromptOptions {
  /** Custom system prompt (replaces default). */
  customPrompt?: string;
  /** Tools to include in prompt. Default: [read, bash, edit, write] */
  selectedTools?: string[];
  /** Optional one-line tool snippets keyed by tool name. */
  toolSnippets?: Record<string, string>;
  /** Additional guideline bullets appended to the default system prompt guidelines. */
  promptGuidelines?: string[];
  /** Text to append to system prompt. */
  appendSystemPrompt?: string;
  /** Working directory. */
  cwd: string;
  /** Pre-loaded context files. */
  contextFiles?: Array<{ path: string; content: string }>;
  /** Pre-loaded skills. */
  skills?: Skill[];
}

一言で言うと、呼び出し側が「どのツール・どのコンテキスト・どのスキルを使うか」を決めて渡すと、関数側が最終プロンプトを組み立てる、という形です。

セッション側(agent-session.ts)がこれをどう呼び出しているかというと、ツールレジストリから各ツールの snippet と guidelines を収集し、リソースローダから SYSTEM.md・APPEND_SYSTEM.md・AGENTS 系ファイル・スキルを読み込んで、まとめて buildSystemPrompt に渡しています。

2. アセンブリのパイプライン

組み立て順は固定です。

buildSystemPrompt(options)
  │
  ├─ customPrompt がある?
  │    ├─ ある → それをベースにする(既定テンプレートを丸ごと置き換え)
  │    └─ なし → 既定テンプレート(persona + tools + guidelines + docs)
  │
  ├─ + appendSystemPrompt        (追記テキスト)
  ├─ + <project_context>         (プロジェクト指示ファイル)
  ├─ + <available_skills>        (スキル・インデックス、read ツール有効時のみ)
  └─ + Current working directory

2 つ、押さえておきたい点があります。

1 つ目は、customPrompt で既定テンプレートを置き換えても、後半の付加セクション(コンテキスト・スキル・cwd)はそのまま追加されることです。つまり「テンプレートを差し替える」と「プロジェクトコンテキストの挙動を変える」は別のレイヤになっています。

2 つ目は、スキル・インデックスは read ツールが有効なときだけ載ることです。モデルに全文を読める手段(read)がないなら、インデックスを載せても意味がない、という判断がコードにそのまま書かれています。

3. 1 層目: 固定テンプレート(原文 + 日本語訳)

既定テンプレートは、この組み立てロジック全体の中で唯一ハードコードされたテキストです。以下がその全文です。

3.1 原文(英語)

You are an expert coding assistant operating inside pi, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.

Available tools:
${toolsList}

In addition to the tools above, you may have access to other custom tools depending on the project.

Guidelines:
${guidelines}

Pi documentation (read only when the user asks about pi itself, its SDK, extensions, themes, skills, or TUI):
- Main documentation: ${readmePath}
- Additional docs: ${docsPath}
- Examples: ${examplesPath} (extensions, custom tools, SDK)
- When reading pi docs or examples, resolve docs/... under Additional docs and examples/... under Examples, not the current working directory
- When asked about: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), pi packages (docs/packages.md), environment variables (docs/environment-variables.md)
- When working on pi topics, read the docs and examples, and follow .md cross-references before implementing
- Always read pi .md files completely and follow links to related docs (e.g., tui.md for TUI API details)

${toolsList}${guidelines} の 2 つの穴(スロット)に、次の層が埋め込まれます。

3.2 日本語訳

あなたは pi(コーディングエージェントのハネス)内で動作するエキスパートのコーディングアシスタントです。ファイルの読み取り、コマンドの実行、コードの編集、新規ファイルの作成を通じて、ユーザーを支援します。

利用可能なツール:
${toolsList}

上記のツールに加え、プロジェクトによって、その他のカスタムツールにアクセスできる場合があります。

ガイドライン:
${guidelines}

pi ドキュメント(ユーザーが pi 自体、その SDK、エクステンション、テーマ、スキル、TUI について質問した場合にのみ読むこと):
- メインドキュメント: ${readmePath}
- 追加ドキュメント: ${docsPath}
- サンプル: ${examplesPath}(エクステンション、カスタムツール、SDK)
- pi のドキュメントやサンプルを読む場合、docs/... は「追加ドキュメント」配下、examples/... は「サンプル」配下を解決すること。現在の作業ディレクトリを参照しないこと
- 質問の受け答え先: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), pi packages (docs/packages.md), environment variables (docs/environment-variables.md)
- pi 関連の作業をする場合、実装前にドキュメントとサンプルを読み、.md 間の相互参照を追うこと
- pi の .md ファイルは必ず全文を読み、関連ドキュメントへのリンクも追うこと(例: TUI の API 詳細は tui.md)

3.3 意外なほど少ないテンプレート

このテンプレートを眺めると、かなり引き締まっていることに気づきます。

テンプレートに入っているもの:
- 1 文の persona(誰であるか)
- ツール欄・ガイドライン欄の 2 つのスロット
- docs ポインタ(しかも「pi 自体の質問に答える時だけ読め」と限定済み)

テンプレートに入っていないもの:
- ツールの使い方          → ツール側が寄与(4, 5 章)
- プロジェクトのルール     → AGENTS.md 系(6.3 章)
- ナレッジ・ノウハウ      → スキル(6.4 章)
- 出力フォーマットやトーン → 一切ない

テンプレートは「persona + スロット + docs ポインタ」だけを担当し、詳細はすべて動的レイヤに押し出しています。
固定テキストを小さく保つことで、プロンプトの修正・レビューコストを下げている、というのが pi の設計思想です。

4. 2 層目: ツール一覧は各ツールの promptSnippet

Available tools 欄はテンプレートに書かれていません。ツール側が 1 行紹介(promptSnippet)を出し、それが組み込まれます。

const tools = selectedTools || ["read", "bash", "edit", "write"];
const visibleTools = tools.filter((name) => !!toolSnippets?.[name]);
const toolsList =
  visibleTools.length > 0
    ? visibleTools.map((name) => `- ${name}: ${toolSnippets![name]}`).join("\n")
    : "(none)";

組み込まれる実際のテキストはこうなっています。

ツール promptSnippet(原文) 日本語
read Read file contents ファイル内容を読み取る
bash Execute bash commands (ls, grep, find, etc.) bash コマンドを実行する(ls, grep, find など)
edit Make precise file edits with exact text replacement, including multiple disjoint edits in one call 正確なテキスト置換による精密なファイル編集を行う(1 回の呼び出しで複数の離れた箇所の編集を含む)
write Create or overwrite files ファイルを作成または上書きする

ここで 1 つ、大事な条件があります。

promptSnippet があるツールだけがプロンプトに表示される、というルールです。説明のないツールは素通りで、リストに出ません。

これは「単一の真実の情報源(single source of truth)」の設計です。

ツール定義 1 つの中に:
  - 呼び出し仕様   (JSON Schema 相当)
  - 自己紹介       (promptSnippet)
  - 利用ルール     (promptGuidelines)

が同居するので、ツール実装とプロンプトが別ファイルで
別々に管理されてズレる、ということが構造的に起きにくい。

ツールを増やしても減らしても、プロンプト側を別途編集する必要はありません。

5. 3 層目: ガイドラインは各ツールの promptGuidelines

Guidelines 欄も同じ仕組みです。ツールごとに利用ルールを複数寄与できます。

ツール promptGuidelines(原文) 日本語要約
read Use read to examine files instead of cat or sed. ファイル閲覧は cat や sed の代わりに read を使う
bash You can inspect PI_* environment variables for current model and session details. 現在モデル・セッション詳細は PI_* 環境変数を見ればよい
edit Use edit for precise changes (edits[].oldText must match exactly) 精密な変更は edit を使う(oldText は完全一致必須)
edit When changing multiple separate locations in one file, use one edit call with multiple entries in edits[] instead of multiple edit calls 1 ファイル内の複数箇所を変更するなら edit 呼び出し 1 回に edits[] を複数エントリにして渡す
edit Each edits[].oldText is matched against the original file, not after earlier edits are applied. Do not emit overlapping or nested edits. Merge nearby changes into one edit. 各 oldText は「元のファイル」に対して一致判定される(前エントリ適用後ではない)。重複・入れ子のエディットは禁止し、近くの編集は 1 つにまとめる
edit Keep edits[].oldText as small as possible while still being unique in the file. Do not pad with large unchanged regions. oldText はファイル内で一意を維持する範囲で最小に。大きな不変領域をパディングしない
write Use write only for new files or complete rewrites. write は新規ファイルか全面書き直しの時のみ使う

この他に、組み立て関数側が 2 種類のガイドラインを追加します。

// bash が有効で、grep / find / ls が無効な場合のみ
if (hasBash && !hasGrep && !hasFind && !hasLs) {
  addGuideline("Use bash for file operations like ls, rg, find");
}

// 常に追加
addGuideline("Be concise in your responses");
addGuideline("Show file paths clearly when working with files");

edit の 4 本のルールを改めて見ると、ここが「ツールごとのガイドライン」の正しい粒度だと思います。

- 複数箇所の変更 → 1 回呼び出しで済ませる(往復回数の節約)
- oldText は「元のファイル」に対して一致(逐次適用との誤解を防ぐ)
- 重複・入れ子エディットを禁止(曖昧な出力を防ぐ)
- oldText は最小だが一意(巨大コンテキストをプロンプトに載せない)

これらは LLM への一般的な言い訳ではなく、そのツールの API 契約をモデルが誤用しないためのルールです。ツールとペアで書くから、ズレにくい。

6. 4 層目: 付加セクション(ファイルから読む)

テンプレートの後には、4 つの付加セクションが順に追加されます。

+ appendSystemPrompt    ← APPEND_SYSTEM.md
+ <project_context>     ← AGENTS.override.md / AGENTS.md / CLAUDE.md
+ <available_skills>    ← 発見された SKILL.md 群のインデックス
+ Current working directory

これらはすべて「ファイルに書いておけば、プロンプトコードを触らずに入力できる」形です。

6.1 追記テキスト: APPEND_SYSTEM.md

テンプレートの直後に追加されるテキストです。プロジェクト側(.pi/APPEND_SYSTEM.md)とグローバル側(agent ディレクトリの APPEND_SYSTEM.md)の両方から発見されます。

使い方:
  .pi/APPEND_SYSTEM.md   → プロジェクト固有の追記(信頼されたプロジェクトのみ)
  ~/.pi/agent/APPEND_SYSTEM.md → グローバルな追記

効かせること:
  - 会社のルール・環境説明の注入
  - テンプレート本体を壊さず上流に追記する

パッケージを fork せずに挙動を変えられる、軽めの拡張ポイントです。

6.2 テンプレート差し替え: SYSTEM.md

customPrompt には、.pi/SYSTEM.md(プロジェクト)または ~/.pi/agent/SYSTEM.md(グローバル)の内容が設定されます。

存在するなら:
  - 既定テンプレートを「丸ごと置き換え」る
  - ただし 6.3 〜 6.5 の付加セクションは引き続き追加される

「プロンプトの全部を自前化したい」ケース用の逃げ口です。ただしスロット埋め込み(ツール一覧・ガイドラインの自動組み立て)は失われるので、必要な場合は自分側で tools・guidelines を組み込む設計になります。

6.3 プロジェクト指示: AGENTS.md / CLAUDE.md

リソースローダが探すファイル名は次の候補です。

AGENTS.override.md / AGENTS.md / AGENTS.MD / CLAUDE.md / CLAUDE.MD

内容は <project_context> ブロックとして注入されます。

<project_context>

Project-specific instructions and guidelines:

<project_instructions path="AGENTS.md">
(ファイル内容)
</project_instructions>

</project_context>

ファイルごとに path 付きタグでラップしているのがポイントで、どの指示がどのファイル由来かをモデルに明示できます。複数ファイルを積んでも混線しにくいです。

6.4 スキル・インデックス: 進行的な開示(progressive disclosure)

スキル(SKILL.md)は、名前・説明・パスのインデックスだけがプロンプトに入ります。

The following skills provide specialized instructions for specific tasks.
Use the read tool to load a skill's file when the task matches its description.
When a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.

<available_skills>
  <skill>
    <name>pi-subagents</name>
    <description>Delegate work to builtin or custom subagents ...</description>
    <location>/root/.pi/agent/.../SKILL.md</location>
  </skill>
</available_skills>

日本語にすると、「以下のスキルが特定のタスク用の専用手順を提供する。タスクが説明に合えば read ツールでファイルを読みなさい。相対パスはスキルディレクトリ基準で解決すること」という案内で、中身は <available_skills> に名前・説明・場所だけです。

全文は、モデルが該当タスクに当たった時点で read して読みに行きます。この「進行的な開示」には 3 つの利点があります。

- プロンプトが小さく保てる(インストールしたスキル数が大きくても)
- 全文は必要な時だけコンテキストに載る(不要なトークン消費が減る)
- スキルの追加が「ファイルの配置」だけで完結する(プロンプト変更ゼロ)

スキルを増やしたいときは SKILL.md を 1 つ置くだけ、というのが運用上とても楽です。

6.5 作業ディレクトリ

最後に 1 行だけ、Current working directory: ${cwd} が付きます。地味ですが、相対パスの解決や bash の前提に直結するので、ここが抜けているとツール呼び出しの精度が落ちます。

7. 再構成した実際のプロンプト(例)

ここまでを全部つなげると、標準 4 ツール(read / bash / edit / write)のセッションで生成されるプロンプトは、だいたい次のようになります。

You are an expert coding assistant operating inside pi, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.

Available tools:
- read: Read file contents
- bash: Execute bash commands (ls, grep, find, etc.)
- edit: Make precise file edits with exact text replacement, including multiple disjoint edits in one call
- write: Create or overwrite files

In addition to the tools above, you may have access to other custom tools depending on the project.

Guidelines:
- Use bash for file operations like ls, rg, find
- Use read to examine files instead of cat or sed.
- You can inspect PI_* environment variables for current model and session details.
- Use edit for precise changes (edits[].oldText must match exactly)
- When changing multiple separate locations in one file, use one edit call with multiple entries in edits[] instead of multiple edit calls
- Each edits[].oldText is matched against the original file, not after earlier edits are applied. Do not emit overlapping or nested edits. Merge nearby changes into one edit.
- Keep edits[].oldText as small as possible while still being unique in the file. Do not pad with large unchanged regions.
- Use write only for new files or complete rewrites.
- Be concise in your responses
- Show file paths clearly when working with files

Pi documentation (read only when the user asks about pi itself, its SDK, extensions, themes, skills, or TUI):
- Main documentation: <パッケージ>/README.md
- Additional docs: <パッケージ>/docs
- Examples: <パッケージ>/examples (extensions, custom tools, SDK)
- When reading pi docs or examples, resolve docs/... under Additional docs and examples/... under Examples, not the current working directory
- When asked about: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), pi packages (docs/packages.md), environment variables (docs/environment-variables.md)
- When working on pi topics, read the docs and examples, and follow .md cross-references before implementing
- Always read pi .md files completely and follow links to related docs (e.g., tui.md for TUI API details)

(+ APPEND_SYSTEM.md の内容)
(+ <project_context>(AGENTS.md 等がある場合))
(+ <available_skills>(スキルがある場合))

Current working directory: /path/to/project

全部で思ったより短いです。
pi のプロンプトの「賢さ」は長さではなく、この組み立て機構にあります。

8. 自分のエージェントに取り込める設計

pi の実装から、自分のエージェントプロンプトを書くときにそのまま取り込めるパターンをまとめます。

8.1 テンプレートは小さく保つ

固定テキストには persona・スロット・ポインタしか置かない。ツール単位・条件付きになりうるルールはテンプレートに入れない。

固定: 誰であるか / どのスロットがあるか / docs の場所
動的: ツール一覧 / ツールルール / プロジェクトコンテキスト / スキル

8.2 ツールに自己紹介を持たせる

ツール紹介と利用ルールを別ファイルのプロンプトに書かない。ツール定義側に promptSnippet(1 行紹介)と promptGuidelines(利用ルール)を載せる。

利点:
- 単一の真実の情報源になる(ツール定義がそのままプロンプト)
- ツールの増減でプロンプトが自動更新される
- ルールが API 契約の隣にあるので、実装変更時に古いままになりにくい

注意:
- snippet のないツールはプロンプトに出ない(ここを ON/OFF スイッチにしてよい)

8.3 プロンプトは条件分岐させる

有効になっていないツールについて喋らない。pi は「bash だけ有効で grep/find/ls が無効」のときだけファイル探索の bash ルールを入れています。

アンチパターン:
  10 ツール分の使い方をプロンプトに書いておき、
  実際には 2 つしか有効にしていない

8.4 ナレッジはインデックスだけ載せる

ノウハウ・手順書は全文をプロンプトに載せない。name + description + path のインデックスだけにして、モデルがマッチしたタスクで全文を読みにいく形にする。

プロンプト内:  <available_skills>(名前 / 説明 / 場所)
読み込み:      タスクがマッチした時だけ read で全文

pi のスキル機構はこのパターンをファイル配置だけで実装した、かなり軽量な設計です。

8.5 プロジェクト規約はファイル化して path 付きで注入

「このリポジトリではこういう手順でデプロイする」「このタブーがある」は、AGENTS.md 系のファイルに書いて、path 付きタグでプロンプトに注入する。

- 複数ファイルを積んでも出所が分かる
- プロンプトコードを触らずに規約を変更できる
- 人が読んで編集できる形(Markdown)をそのまま使える

8.6 チェックリスト

自分のエージェントのプロンプトを書くときのチェックリストです。

- [ ] 固定テンプレートは数十行以内に収まっているか
- [ ] 各ツールの紹介とルールはツール定義側に載っているか
- [ ] プロンプトは有効なツール構成に合わせて条件分岐しているか
- [ ] 大きなナレッジはインデックスのみで、全文は必要時読み込みか
- [ ] プロジェクト規約はファイル化して path 付きで注入されているか
- [ ] ツールの増減でプロンプトを手で直す必要はないか
- [ ] 作業ディレクトリ等の環境情報が含まれているか

まとめ

pi のシステムプロンプトは、結局は小さなテンプレートでした。
本物の設計は、組み立て機構のほうです。

内容 出所
テンプレート persona + スロット + docs ポインタ buildSystemPrompt(固定)
ツール一覧 ツール 1 行紹介 各ツールの promptSnippet
ガイドライン ツールの利用ルール 各ツールの promptGuidelines + 条件分岐
追記 環境・ルール追加 APPEND_SYSTEM.md
コンテキスト プロジェクト指示 AGENTS.override.md / AGENTS.md / CLAUDE.md
スキル ナレッジ・インデックス(名前 / 説明 / パス) formatSkillsForPrompt
環境 作業ディレクトリ cwd

個人的に、ここで一番大事な教訓はこれだと思います。

プロンプトは、手書きで固定される大きなテキストではなく、ツール・コンテキスト・ナレッジから組み立てられる構造であるべきです。

こうすると、プロンプトは小さく保てます。
そして、時間とともに腐りにくくなります。

是非お試しください!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?