SDK
pi は SDK の利用を支援できます。ユースケースに合わせた統合の構築を依頼してください。
SDK は pi の agent 機能へのプログラム的アクセスを提供します。他のアプリケーションへの pi の組み込み、カスタム UI の構築、自動化ワークフローへの統合に使用します。
使用例:
- カスタム UI(Web、デスクトップ、モバイル)の構築
- 既存アプリケーションへの agent 機能の統合
- agent 推論を伴う自動化パイプラインの作成
- サブ agent を起動するカスタムツールの構築
- agent 動作のプログラム的テスト
最小構成から完全制御まで、examples/sdk/ の動作例を参照してください。
クイックスタート
Section titled “クイックスタート”import { AuthStorage, createAgentSession, ModelRegistry, SessionManager } from "@earendil-works/pi-coding-agent";
// Set up credential storage and model registryconst authStorage = AuthStorage.create();const modelRegistry = ModelRegistry.create(authStorage);
const { session } = await createAgentSession({ sessionManager: SessionManager.inMemory(), authStorage, modelRegistry,});
session.subscribe((event) => { if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") { process.stdout.write(event.assistantMessageEvent.delta); }});
await session.prompt("What files are in the current directory?");インストール
Section titled “インストール”npm install @earendil-works/pi-coding-agentSDK はメインパッケージに含まれています。別途インストールは不要です。
createAgentSession()
Section titled “createAgentSession()”単一の AgentSession を作成するメインのファクトリ関数です。
createAgentSession() は ResourceLoader を使って拡張機能、スキル、プロンプトテンプレート、テーマ、コンテキストファイルを供給します。指定しない場合は、標準のディスカバリを行う DefaultResourceLoader を使用します。
import { createAgentSession, SessionManager } from "@earendil-works/pi-coding-agent";
// Minimal: defaults with DefaultResourceLoaderconst { session } = await createAgentSession();
// Custom: override specific optionsconst { session } = await createAgentSession({ model: myModel, tools: ["read", "bash"], sessionManager: SessionManager.inMemory(),});AgentSession
Section titled “AgentSession”セッションは agent のライフサイクル、メッセージ履歴、モデル状態、コンパクション、イベントストリーミングを管理します。
interface AgentSession { // Send a prompt and wait for completion prompt(text: string, options?: PromptOptions): Promise<void>;
// Queue messages during streaming steer(text: string): Promise<void>; followUp(text: string): Promise<void>;
// Subscribe to events (returns unsubscribe function) subscribe(listener: (event: AgentSessionEvent) => void): () => void;
// Session info sessionFile: string | undefined; sessionId: string;
// Model control setModel(model: Model): Promise<void>; setThinkingLevel(level: ThinkingLevel): void; cycleModel(): Promise<ModelCycleResult | undefined>; cycleThinkingLevel(): ThinkingLevel | undefined;
// State access agent: Agent; model: Model | undefined; thinkingLevel: ThinkingLevel; messages: AgentMessage[]; isStreaming: boolean;
// In-place tree navigation within the current session file navigateTree(targetId: string, options?: { summarize?: boolean; customInstructions?: string; replaceInstructions?: boolean; label?: string }): Promise<{ editorText?: string; cancelled: boolean }>;
// Compaction compact(customInstructions?: string): Promise<CompactionResult>; abortCompaction(): void;
// Abort current operation abort(): Promise<void>;
// Cleanup dispose(): void;}new-session、resume、fork、import などのセッション置換 API は AgentSession ではなく AgentSessionRuntime にあります。
createAgentSessionRuntime() と AgentSessionRuntime
Section titled “createAgentSessionRuntime() と AgentSessionRuntime”アクティブなセッションを置き換え、cwd に紐づくランタイム状態を再構築する必要がある場合は runtime API を使用します。 これは組み込みの対話型、print、RPC モードと同じレイヤーです。
createAgentSessionRuntime() は runtime ファクトリと初期 cwd/セッションターゲットを受け取ります。ファクトリはプロセス全体の固定入力をクロージャし、有効な cwd 用に cwd 紐づきサービスを再作成し、それらのサービスに対してセッションオプションを解決し、完全な runtime 結果を返します。
import { type CreateAgentSessionRuntimeFactory, createAgentSessionFromServices, createAgentSessionRuntime, createAgentSessionServices, getAgentDir, SessionManager,} from "@earendil-works/pi-coding-agent";
const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => { const services = await createAgentSessionServices({ cwd }); return { ...(await createAgentSessionFromServices({ services, sessionManager, sessionStartEvent, })), services, diagnostics: services.diagnostics, };};
const runtime = await createAgentSessionRuntime(createRuntime, { cwd: process.cwd(), agentDir: getAgentDir(), sessionManager: SessionManager.create(process.cwd()),});AgentSessionRuntime は次の操作にわたるアクティブ runtime の置換を担当します:
newSession()switchSession()fork()fork(entryId, { position: "at" })によるクローンフローimportFromJsonl()
重要な動作:
- これらの操作後、
runtime.sessionは変わります - イベント購読は特定の
AgentSessionに紐づくため、置換後は再購読が必要です - 拡張機能を使う場合は、新しいセッションに対して
runtime.session.bindExtensions(...)を再度呼び出してください - 作成時に
runtime.diagnosticsに診断情報が返されます - runtime の作成または置換に失敗した場合、メソッドは例外をスローし、呼び出し側が処理方法を決定します
let session = runtime.session;let unsubscribe = session.subscribe(() => {});
await runtime.newSession();
unsubscribe();session = runtime.session;unsubscribe = session.subscribe(() => {});プロンプトとメッセージキュー
Section titled “プロンプトとメッセージキュー”PromptOptions はプロンプト展開、ストリーミング中のキュー動作、プロンプト事前チェック通知を制御します:
interface PromptOptions { expandPromptTemplates?: boolean; images?: ImageContent[]; streamingBehavior?: "steer" | "followUp"; source?: InputSource; preflightResult?: (success: boolean) => void;}preflightResult は prompt() 呼び出しごとに 1 回呼ばれます:
- プロンプトが受理、キュー投入、または即時処理された場合は
true - 受理前にプロンプト事前チェックが拒否した場合は
false
これは prompt() が resolve する前に発火します。prompt() は、リトライを含む受理済み実行全体が完了した後にのみ resolve します。受理後の失敗は preflightResult(false) ではなく、通常のイベントとメッセージストリームで報告されます。
prompt() メソッドはプロンプトテンプレート、拡張コマンド、メッセージ送信を処理します:
// Basic prompt (when not streaming)await session.prompt("What files are here?");
// With imagesawait session.prompt("What's in this image?", { images: [{ type: "image", source: { type: "base64", mediaType: "image/png", data: "..." } }]});
// During streaming: must specify how to queue the messageawait session.prompt("Stop and do this instead", { streamingBehavior: "steer" });await session.prompt("After you're done, also check X", { streamingBehavior: "followUp" });動作:
- 拡張コマンド(例:
/mycommand):ストリーミング中でも即座に実行されます。pi.sendMessage()経由で独自の LLM 対話を管理します。 - ファイルベースのプロンプトテンプレート(
.mdファイル):送信またはキュー投入前に内容へ展開されます。 - ストリーミング中に
streamingBehavior未指定:エラーをスローします。steer()またはfollowUp()を直接使うか、オプションを指定してください。 preflightResult(true):プロンプトが受理、キュー投入、または即時処理されたことを意味します。preflightResult(false):受理前に事前チェックが拒否されたことを意味します。
ストリーミング中の明示的キュー:
// Queue a steering message for delivery after the current assistant turn finishes its tool callsawait session.steer("New instruction");
// Wait for agent to finish (delivered only when agent stops)await session.followUp("After you're done, also do this");steer() と followUp() はどちらもファイルベースのプロンプトテンプレートを展開しますが、拡張コマンドではエラーになります(拡張コマンドはキューできません)。
Agent と AgentState
Section titled “Agent と AgentState”Agent クラス(@earendil-works/pi-agent-core 由来)はコア LLM 対話を処理します。session.agent 経由でアクセスします。
// Access current stateconst state = session.agent.state;
// state.messages: AgentMessage[] - conversation history// state.model: Model - current model// state.thinkingLevel: ThinkingLevel - current thinking level// state.systemPrompt: string - system prompt// state.tools: AgentTool[] - available tools// state.streamingMessage?: AgentMessage - current partial assistant message// state.errorMessage?: string - latest assistant error
// Replace messages (useful for branching or restoration)session.agent.state.messages = messages; // copies the top-level array
// Replace toolssession.agent.state.tools = tools; // copies the top-level array
// Wait for agent to finish processingawait session.agent.waitForIdle();ストリーミング出力とライフサイクル通知を受け取るにはイベントを購読します。
session.subscribe((event) => { switch (event.type) { // Streaming text from assistant case "message_update": if (event.assistantMessageEvent.type === "text_delta") { process.stdout.write(event.assistantMessageEvent.delta); } if (event.assistantMessageEvent.type === "thinking_delta") { // Thinking output (if thinking enabled) } break;
// Tool execution case "tool_execution_start": console.log(`Tool: ${event.toolName}`); break; case "tool_execution_update": // Streaming tool output break; case "tool_execution_end": console.log(`Result: ${event.isError ? "error" : "success"}`); break;
// Message lifecycle case "message_start": // New message starting break; case "message_end": // Message complete break;
// Agent lifecycle case "agent_start": // Agent started processing prompt break; case "agent_end": // Agent finished (event.messages contains new messages) break;
// Turn lifecycle (one LLM response + tool calls) case "turn_start": break; case "turn_end": // event.message: assistant response // event.toolResults: tool results from this turn break;
// Session events (queue, compaction, retry) case "queue_update": console.log(event.steering, event.followUp); break; case "compaction_start": case "compaction_end": case "auto_retry_start": case "auto_retry_end": break; }});オプションリファレンス
Section titled “オプションリファレンス”ディレクトリ
Section titled “ディレクトリ”const { session } = await createAgentSession({ // Working directory for DefaultResourceLoader discovery cwd: process.cwd(), // default
// Global config directory agentDir: "~/.pi/agent", // default (expands ~)});cwd は DefaultResourceLoader により次に使用されます:
- プロジェクト拡張(
.pi/extensions/) - プロジェクトスキル:
.pi/skills/cwdおよび祖先ディレクトリの.agents/skills/(git リポジトリルートまで、リポジトリ外ではファイルシステムルートまで)
- プロジェクトプロンプト(
.pi/prompts/) - コンテキストファイル(cwd から上方向に辿る
AGENTS.md) - セッションディレクトリ名
agentDir は DefaultResourceLoader により次に使用されます:
- グローバル拡張(
extensions/) - グローバルスキル:
agentDir配下のskills/(例:~/.pi/agent/skills/)~/.agents/skills/
- グローバルプロンプト(
prompts/) - グローバルコンテキストファイル(
AGENTS.md) - 設定(
settings.json) - カスタムモデル(
models.json) - 認証情報(
auth.json) - セッション(
sessions/)
カスタム ResourceLoader を渡すと、cwd と agentDir はリソースディスカバリを制御しなくなります。セッション名とツールパス解決には引き続き影響します。
import { getModel } from "@earendil-works/pi-ai";import { AuthStorage, ModelRegistry } from "@earendil-works/pi-coding-agent";
const authStorage = AuthStorage.create();const modelRegistry = ModelRegistry.create(authStorage);
// Find specific built-in model (doesn't check if API key exists)const opus = getModel("anthropic", "claude-opus-4-5");if (!opus) throw new Error("Model not found");
// Find any model by provider/id, including custom models from models.json// (doesn't check if API key exists)const customModel = modelRegistry.find("my-provider", "my-model");
// Get only models that have valid API keys configuredconst available = await modelRegistry.getAvailable();
const { session } = await createAgentSession({ model: opus, thinkingLevel: "medium", // off, minimal, low, medium, high, xhigh
// Models for cycling (Ctrl+P in interactive mode) scopedModels: [ { model: opus, thinkingLevel: "high" }, { model: haiku, thinkingLevel: "off" }, ],
authStorage, modelRegistry,});モデルが指定されない場合:
- セッションからの復元を試行(継続時)
- 設定のデフォルトを使用
- 利用可能な最初のモデルにフォールバック
API キーと OAuth
Section titled “API キーと OAuth”API キー解決の優先順位(AuthStorage が処理):
- ランタイム上書き(
setRuntimeApiKey経由、永続化されない) auth.jsonに保存された認証情報(API キーまたは OAuth トークン)- 環境変数(
ANTHROPIC_API_KEY、OPENAI_API_KEYなど) - フォールバックリゾルバ(
models.jsonのカスタム provider キー用)
import { AuthStorage, ModelRegistry } from "@earendil-works/pi-coding-agent";
// Default: uses ~/.pi/agent/auth.json and ~/.pi/agent/models.jsonconst authStorage = AuthStorage.create();const modelRegistry = ModelRegistry.create(authStorage);
const { session } = await createAgentSession({ sessionManager: SessionManager.inMemory(), authStorage, modelRegistry,});
// Runtime API key override (not persisted to disk)authStorage.setRuntimeApiKey("anthropic", "sk-my-temp-key");
// Custom auth storage locationconst customAuth = AuthStorage.create("/my/app/auth.json");const customRegistry = ModelRegistry.create(customAuth, "/my/app/models.json");
const { session } = await createAgentSession({ sessionManager: SessionManager.inMemory(), authStorage: customAuth, modelRegistry: customRegistry,});
// No custom models.json (built-in models only)const simpleRegistry = ModelRegistry.inMemory(authStorage);システムプロンプト
Section titled “システムプロンプト”ResourceLoader でシステムプロンプトを上書きします:
import { createAgentSession, DefaultResourceLoader } from "@earendil-works/pi-coding-agent";
const loader = new DefaultResourceLoader({ systemPromptOverride: () => "You are a helpful assistant.",});await loader.reload();
const { session } = await createAgentSession({ resourceLoader: loader });有効にする組み込みツールを指定します:
- 組み込みツール名:
read、bash、edit、write、grep、find、ls - デフォルト組み込み:
read、bash、edit、write noTools: "all"はすべてのツールを無効化noTools: "builtin"はデフォルト組み込みを無効化し、拡張とカスタムツールは有効のままexcludeToolsはtools許可リスト適用後に、特定の組み込み、拡張、カスタムツール名を無効化
edit ツールは Pi の TUI 表示用に details.diff を、SDK 利用者向けに標準 unified patch として details.patch を返します。
import { createAgentSession } from "@earendil-works/pi-coding-agent";
// Read-only modeconst { session } = await createAgentSession({ tools: ["read", "grep", "find", "ls"],});
// Pick specific toolsconst { session } = await createAgentSession({ tools: ["read", "bash", "grep"],});
// Disable one tool while keeping the rest availableconst { session } = await createAgentSession({ excludeTools: ["ask_question"],});カスタム cwd のツール
Section titled “カスタム cwd のツール”カスタム cwd を渡すと、createAgentSession() はその cwd 向けに選択された組み込みツールを構築します。
import { createAgentSession, SessionManager } from "@earendil-works/pi-coding-agent";
const cwd = "/path/to/project";
// Use default tools for custom cwdconst { session } = await createAgentSession({ cwd, sessionManager: SessionManager.inMemory(cwd),});
// Or pick specific tools for custom cwdconst { session } = await createAgentSession({ cwd, tools: ["read", "bash", "grep"], sessionManager: SessionManager.inMemory(cwd),});カスタムツール
Section titled “カスタムツール”import { Type } from "typebox";import { createAgentSession, defineTool } from "@earendil-works/pi-coding-agent";
// Inline custom toolconst myTool = defineTool({ name: "my_tool", label: "My Tool", description: "Does something useful", parameters: Type.Object({ input: Type.String({ description: "Input value" }), }), execute: async (_toolCallId, params) => ({ content: [{ type: "text", text: `Result: ${params.input}` }], details: {}, }),});
// Pass custom tools directlyconst { session } = await createAgentSession({ customTools: [myTool],});独立定義や customTools: [myTool] のような配列には defineTool() を使用します。インライン pi.registerTool({ ... }) は既にパラメータ型を正しく推論します。
customTools 経由のカスタムツールは、拡張登録ツールと結合されます。ResourceLoader で読み込まれた拡張も pi.registerTool() でツールを登録できます。
tools を渡す場合は、有効にしたい各カスタムまたは拡張ツール名を含めてください。例:tools: ["read", "bash", "my_tool"]。
拡張機能は ResourceLoader によって読み込まれます。DefaultResourceLoader は ~/.pi/agent/extensions/、.pi/extensions/、settings.json の拡張ソースから拡張を発見します。
import { createAgentSession, DefaultResourceLoader } from "@earendil-works/pi-coding-agent";
const loader = new DefaultResourceLoader({ additionalExtensionPaths: ["/path/to/my-extension.ts"], extensionFactories: [ (pi) => { pi.on("agent_start", () => { console.log("[Inline Extension] Agent starting"); }); }, ],});await loader.reload();
const { session } = await createAgentSession({ resourceLoader: loader });拡張機能はツール登録、イベント購読、コマンド追加などが可能です。完全な API は extensions.md を参照してください。
イベントバス: 拡張機能は pi.events 経由で通信できます。外部から emit/listen する必要がある場合は、共有 eventBus を DefaultResourceLoader に渡します:
import { createEventBus, DefaultResourceLoader } from "@earendil-works/pi-coding-agent";
const eventBus = createEventBus();const loader = new DefaultResourceLoader({ eventBus,});await loader.reload();
eventBus.on("my-extension:status", (data) => console.log(data));import { createAgentSession, DefaultResourceLoader, type Skill,} from "@earendil-works/pi-coding-agent";
const customSkill: Skill = { name: "my-skill", description: "Custom instructions", filePath: "/path/to/SKILL.md", baseDir: "/path/to", source: "custom",};
const loader = new DefaultResourceLoader({ skillsOverride: (current) => ({ skills: [...current.skills, customSkill], diagnostics: current.diagnostics, }),});await loader.reload();
const { session } = await createAgentSession({ resourceLoader: loader });コンテキストファイル
Section titled “コンテキストファイル”import { createAgentSession, DefaultResourceLoader } from "@earendil-works/pi-coding-agent";
const loader = new DefaultResourceLoader({ agentsFilesOverride: (current) => ({ agentsFiles: [ ...current.agentsFiles, { path: "/virtual/AGENTS.md", content: "# Guidelines\n\n- Be concise" }, ], }),});await loader.reload();
const { session } = await createAgentSession({ resourceLoader: loader });スラッシュコマンド
Section titled “スラッシュコマンド”import { createAgentSession, DefaultResourceLoader, type PromptTemplate,} from "@earendil-works/pi-coding-agent";
const customCommand: PromptTemplate = { name: "deploy", description: "Deploy the application", source: "(custom)", content: "# Deploy\n\n1. Build\n2. Test\n3. Deploy",};
const loader = new DefaultResourceLoader({ promptsOverride: (current) => ({ prompts: [...current.prompts, customCommand], diagnostics: current.diagnostics, }),});await loader.reload();
const { session } = await createAgentSession({ resourceLoader: loader });セッション管理
Section titled “セッション管理”セッションは id/parentId リンクを持つツリー構造を使用し、インプレース分岐を可能にします。
import { type CreateAgentSessionRuntimeFactory, createAgentSession, createAgentSessionFromServices, createAgentSessionRuntime, createAgentSessionServices, getAgentDir, SessionManager,} from "@earendil-works/pi-coding-agent";
// In-memory (no persistence)const { session } = await createAgentSession({ sessionManager: SessionManager.inMemory(),});
// New persistent sessionconst { session: persisted } = await createAgentSession({ sessionManager: SessionManager.create(process.cwd()),});
// Continue most recentconst { session: continued, modelFallbackMessage } = await createAgentSession({ sessionManager: SessionManager.continueRecent(process.cwd()),});if (modelFallbackMessage) { console.log("Note:", modelFallbackMessage);}
// Open specific fileconst { session: opened } = await createAgentSession({ sessionManager: SessionManager.open("/path/to/session.jsonl"),});
// List sessionsconst currentProjectSessions = await SessionManager.list(process.cwd());const allSessions = await SessionManager.listAll(process.cwd());
// Session replacement API for /new, /resume, /fork, /clone, and import flows.const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => { const services = await createAgentSessionServices({ cwd }); return { ...(await createAgentSessionFromServices({ services, sessionManager, sessionStartEvent, })), services, diagnostics: services.diagnostics, };};
const runtime = await createAgentSessionRuntime(createRuntime, { cwd: process.cwd(), agentDir: getAgentDir(), sessionManager: SessionManager.create(process.cwd()),});
// Replace the active session with a fresh oneawait runtime.newSession();
// Replace the active session with another saved sessionawait runtime.switchSession("/path/to/session.jsonl");
// Replace the active session with a fork from a specific user entryawait runtime.fork("entry-id");
// Clone the active path through a specific entryawait runtime.fork("entry-id", { position: "at" });SessionManager ツリー API:
const sm = SessionManager.open("/path/to/session.jsonl");
// Session listingconst currentProjectSessions = await SessionManager.list(process.cwd());const allSessions = await SessionManager.listAll(process.cwd());
// Tree traversalconst entries = sm.getEntries(); // All entries (excludes header)const tree = sm.getTree(); // Full tree structureconst path = sm.getPath(); // Path from root to current leafconst leaf = sm.getLeafEntry(); // Current leaf entryconst entry = sm.getEntry(id); // Get entry by IDconst children = sm.getChildren(id); // Direct children of entry
// Labelsconst label = sm.getLabel(id); // Get label for entrysm.appendLabelChange(id, "checkpoint"); // Set label
// Branchingsm.branch(entryId); // Move leaf to earlier entrysm.branchWithSummary(id, "Summary..."); // Branch with context summarysm.createBranchedSession(leafId); // Extract path to new fileimport { createAgentSession, SettingsManager, SessionManager } from "@earendil-works/pi-coding-agent";
// Default: loads from files (global + project merged)const { session } = await createAgentSession({ settingsManager: SettingsManager.create(),});
// With overridesconst settingsManager = SettingsManager.create();settingsManager.applyOverrides({ compaction: { enabled: false }, retry: { enabled: true, maxRetries: 5 },});const { session } = await createAgentSession({ settingsManager });
// In-memory (no file I/O, for testing)const { session } = await createAgentSession({ settingsManager: SettingsManager.inMemory({ compaction: { enabled: false } }), sessionManager: SessionManager.inMemory(),});
// Custom directoriesconst { session } = await createAgentSession({ settingsManager: SettingsManager.create("/custom/cwd", "/custom/agent"),});静的ファクトリ:
SettingsManager.create(cwd?, agentDir?)- ファイルから読み込みSettingsManager.inMemory(settings?)- ファイル I/O なし
プロジェクト固有の設定:
設定は 2 箇所から読み込まれマージされます:
- グローバル:
~/.pi/agent/settings.json - プロジェクト:
<cwd>/.pi/settings.json
プロジェクトがグローバルを上書きします。ネストされたオブジェクトはキーをマージします。setter はデフォルトでグローバル設定を変更します。
永続化とエラー処理のセマンティクス:
- 設定の getter/setter はインメモリ状態に対して同期的です。
- setter は永続化書き込みを非同期にキュー投入します。
- 永続化境界が必要な場合(例:プロセス終了前、テストでファイル内容を検証する前)は
await settingsManager.flush()を呼び出してください。 SettingsManagerは設定 I/O エラーを出力しません。settingsManager.drainErrors()を使い、アプリ層で報告してください。
ResourceLoader
Section titled “ResourceLoader”DefaultResourceLoader を使って拡張機能、スキル、プロンプト、テーマ、コンテキストファイルを発見します。
import { DefaultResourceLoader, getAgentDir,} from "@earendil-works/pi-coding-agent";
const loader = new DefaultResourceLoader({ cwd, agentDir: getAgentDir(),});await loader.reload();
const extensions = loader.getExtensions();const skills = loader.getSkills();const prompts = loader.getPrompts();const themes = loader.getThemes();const contextFiles = loader.getAgentsFiles().agentsFiles;createAgentSession() は次を返します:
interface CreateAgentSessionResult { // The session session: AgentSession;
// Extensions result (for runner setup) extensionsResult: LoadExtensionsResult;
// Warning if session model couldn't be restored modelFallbackMessage?: string;}
interface LoadExtensionsResult { extensions: Extension[]; errors: Array<{ path: string; error: string }>; runtime: ExtensionRuntime;}import { getModel } from "@earendil-works/pi-ai";import { Type } from "typebox";import { AuthStorage, createAgentSession, DefaultResourceLoader, defineTool, ModelRegistry, SessionManager, SettingsManager,} from "@earendil-works/pi-coding-agent";
// Set up auth storage (custom location)const authStorage = AuthStorage.create("/custom/agent/auth.json");
// Runtime API key override (not persisted)if (process.env.MY_KEY) { authStorage.setRuntimeApiKey("anthropic", process.env.MY_KEY);}
// Model registry (no custom models.json)const modelRegistry = ModelRegistry.create(authStorage);
// Inline toolconst statusTool = defineTool({ name: "status", label: "Status", description: "Get system status", parameters: Type.Object({}), execute: async () => ({ content: [{ type: "text", text: `Uptime: ${process.uptime()}s` }], details: {}, }),});
const model = getModel("anthropic", "claude-opus-4-5");if (!model) throw new Error("Model not found");
// In-memory settings with overridesconst settingsManager = SettingsManager.inMemory({ compaction: { enabled: false }, retry: { enabled: true, maxRetries: 2 },});
const loader = new DefaultResourceLoader({ cwd: process.cwd(), agentDir: "/custom/agent", settingsManager, systemPromptOverride: () => "You are a minimal assistant. Be concise.",});await loader.reload();
const { session } = await createAgentSession({ cwd: process.cwd(), agentDir: "/custom/agent",
model, thinkingLevel: "off", authStorage, modelRegistry,
tools: ["read", "bash", "status"], customTools: [statusTool], resourceLoader: loader,
sessionManager: SessionManager.inMemory(), settingsManager,});
session.subscribe((event) => { if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") { process.stdout.write(event.assistantMessageEvent.delta); }});
await session.prompt("Get status and list files.");SDK は createAgentSession() 上にカスタムインターフェースを構築するための実行モードユーティリティをエクスポートします:
InteractiveMode
Section titled “InteractiveMode”エディタ、チャット履歴、すべての組み込みコマンドを備えた完全な TUI 対話モード:
import { type CreateAgentSessionRuntimeFactory, createAgentSessionFromServices, createAgentSessionRuntime, createAgentSessionServices, getAgentDir, InteractiveMode, SessionManager,} from "@earendil-works/pi-coding-agent";
const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => { const services = await createAgentSessionServices({ cwd }); return { ...(await createAgentSessionFromServices({ services, sessionManager, sessionStartEvent })), services, diagnostics: services.diagnostics, };};const runtime = await createAgentSessionRuntime(createRuntime, { cwd: process.cwd(), agentDir: getAgentDir(), sessionManager: SessionManager.create(process.cwd()),});
const mode = new InteractiveMode(runtime, { migratedProviders: [], modelFallbackMessage: undefined, initialMessage: "Hello", initialImages: [], initialMessages: [],});
await mode.run();runPrintMode
Section titled “runPrintMode”シングルショットモード:プロンプト送信、結果出力、終了:
import { type CreateAgentSessionRuntimeFactory, createAgentSessionFromServices, createAgentSessionRuntime, createAgentSessionServices, getAgentDir, runPrintMode, SessionManager,} from "@earendil-works/pi-coding-agent";
const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => { const services = await createAgentSessionServices({ cwd }); return { ...(await createAgentSessionFromServices({ services, sessionManager, sessionStartEvent })), services, diagnostics: services.diagnostics, };};const runtime = await createAgentSessionRuntime(createRuntime, { cwd: process.cwd(), agentDir: getAgentDir(), sessionManager: SessionManager.create(process.cwd()),});
await runPrintMode(runtime, { mode: "text", initialMessage: "Hello", initialImages: [], messages: ["Follow up"],});runRpcMode
Section titled “runRpcMode”サブプロセス統合用の JSON-RPC モード:
import { type CreateAgentSessionRuntimeFactory, createAgentSessionFromServices, createAgentSessionRuntime, createAgentSessionServices, getAgentDir, runRpcMode, SessionManager,} from "@earendil-works/pi-coding-agent";
const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => { const services = await createAgentSessionServices({ cwd }); return { ...(await createAgentSessionFromServices({ services, sessionManager, sessionStartEvent })), services, diagnostics: services.diagnostics, };};const runtime = await createAgentSessionRuntime(createRuntime, { cwd: process.cwd(), agentDir: getAgentDir(), sessionManager: SessionManager.create(process.cwd()),});
await runRpcMode(runtime);JSON プロトコルは RPC ドキュメント を参照してください。
RPC モードの代替
Section titled “RPC モードの代替”SDK で構築せずサブプロセスベースの統合を行う場合は、CLI を直接使用します:
pi --mode rpc --no-sessionJSON プロトコルは RPC ドキュメント を参照してください。
SDK を優先する場合:
- 型安全性が必要
- 同一 Node.js プロセス内で動作
- agent 状態への直接アクセスが必要
- ツール/拡張機能をプログラム的にカスタマイズしたい
RPC モードを優先する場合:
- 他言語から統合
- プロセス分離が必要
- 言語非依存のクライアントを構築
エクスポート
Section titled “エクスポート”メインエントリポイントは次をエクスポートします:
// FactorycreateAgentSessioncreateAgentSessionRuntimeAgentSessionRuntime
// Auth and ModelsAuthStorageModelRegistry
// Resource loadingDefaultResourceLoadertype ResourceLoadercreateEventBus
// Constants and helpersCONFIG_DIR_NAMEdefineToolgetAgentDirgetPackageDirgetReadmePathgetDocsPathgetExamplesPath
// Session managementSessionManagerSettingsManager
// Tool factoriescreateCodingToolscreateReadOnlyToolscreateReadTool, createBashTool, createEditTool, createWriteToolcreateGrepTool, createFindTool, createLsTool
// Typestype CreateAgentSessionOptionstype CreateAgentSessionResulttype ExtensionFactorytype ExtensionAPItype ToolDefinitiontype Skilltype PromptTemplatetype Tool拡張型の完全な API は extensions.md を参照してください。