コンテンツにスキップ

SDK

pi は SDK の利用を支援できます。ユースケースに合わせた統合の構築を依頼してください。

SDK は pi の agent 機能へのプログラム的アクセスを提供します。他のアプリケーションへの pi の組み込み、カスタム UI の構築、自動化ワークフローへの統合に使用します。

使用例:

  • カスタム UI(Web、デスクトップ、モバイル)の構築
  • 既存アプリケーションへの agent 機能の統合
  • agent 推論を伴う自動化パイプラインの作成
  • サブ agent を起動するカスタムツールの構築
  • agent 動作のプログラム的テスト

最小構成から完全制御まで、examples/sdk/ の動作例を参照してください。

import { AuthStorage, createAgentSession, ModelRegistry, SessionManager } from "@earendil-works/pi-coding-agent";
// Set up credential storage and model registry
const 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?");
Terminal window
npm install @earendil-works/pi-coding-agent

SDK はメインパッケージに含まれています。別途インストールは不要です。

単一の AgentSession を作成するメインのファクトリ関数です。

createAgentSession()ResourceLoader を使って拡張機能、スキル、プロンプトテンプレート、テーマ、コンテキストファイルを供給します。指定しない場合は、標準のディスカバリを行う DefaultResourceLoader を使用します。

import { createAgentSession, SessionManager } from "@earendil-works/pi-coding-agent";
// Minimal: defaults with DefaultResourceLoader
const { session } = await createAgentSession();
// Custom: override specific options
const { session } = await createAgentSession({
model: myModel,
tools: ["read", "bash"],
sessionManager: SessionManager.inMemory(),
});

セッションは 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;
}

preflightResultprompt() 呼び出しごとに 1 回呼ばれます:

  • プロンプトが受理、キュー投入、または即時処理された場合は true
  • 受理前にプロンプト事前チェックが拒否した場合は false

これは prompt() が resolve する前に発火します。prompt() は、リトライを含む受理済み実行全体が完了した後にのみ resolve します。受理後の失敗は preflightResult(false) ではなく、通常のイベントとメッセージストリームで報告されます。

prompt() メソッドはプロンプトテンプレート、拡張コマンド、メッセージ送信を処理します:

// Basic prompt (when not streaming)
await session.prompt("What files are here?");
// With images
await 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 message
await 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 calls
await 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 クラス(@earendil-works/pi-agent-core 由来)はコア LLM 対話を処理します。session.agent 経由でアクセスします。

// Access current state
const 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 tools
session.agent.state.tools = tools; // copies the top-level array
// Wait for agent to finish processing
await 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;
}
});
const { session } = await createAgentSession({
// Working directory for DefaultResourceLoader discovery
cwd: process.cwd(), // default
// Global config directory
agentDir: "~/.pi/agent", // default (expands ~)
});

cwdDefaultResourceLoader により次に使用されます:

  • プロジェクト拡張(.pi/extensions/
  • プロジェクトスキル:
    • .pi/skills/
    • cwd および祖先ディレクトリの .agents/skills/(git リポジトリルートまで、リポジトリ外ではファイルシステムルートまで)
  • プロジェクトプロンプト(.pi/prompts/
  • コンテキストファイル(cwd から上方向に辿る AGENTS.md
  • セッションディレクトリ名

agentDirDefaultResourceLoader により次に使用されます:

  • グローバル拡張(extensions/
  • グローバルスキル:
    • agentDir 配下の skills/(例:~/.pi/agent/skills/
    • ~/.agents/skills/
  • グローバルプロンプト(prompts/
  • グローバルコンテキストファイル(AGENTS.md
  • 設定(settings.json
  • カスタムモデル(models.json
  • 認証情報(auth.json
  • セッション(sessions/

カスタム ResourceLoader を渡すと、cwdagentDir はリソースディスカバリを制御しなくなります。セッション名とツールパス解決には引き続き影響します。

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 configured
const 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,
});

モデルが指定されない場合:

  1. セッションからの復元を試行(継続時)
  2. 設定のデフォルトを使用
  3. 利用可能な最初のモデルにフォールバック

examples/sdk/02-custom-model.ts を参照

API キー解決の優先順位(AuthStorage が処理):

  1. ランタイム上書き(setRuntimeApiKey 経由、永続化されない)
  2. auth.json に保存された認証情報(API キーまたは OAuth トークン)
  3. 環境変数(ANTHROPIC_API_KEYOPENAI_API_KEY など)
  4. フォールバックリゾルバ(models.json のカスタム provider キー用)
import { AuthStorage, ModelRegistry } from "@earendil-works/pi-coding-agent";
// Default: uses ~/.pi/agent/auth.json and ~/.pi/agent/models.json
const 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 location
const 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);

examples/sdk/09-api-keys-and-oauth.ts を参照

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 });

examples/sdk/03-custom-prompt.ts を参照

有効にする組み込みツールを指定します:

  • 組み込みツール名:readbasheditwritegrepfindls
  • デフォルト組み込み:readbasheditwrite
  • noTools: "all" はすべてのツールを無効化
  • noTools: "builtin" はデフォルト組み込みを無効化し、拡張とカスタムツールは有効のまま
  • excludeToolstools 許可リスト適用後に、特定の組み込み、拡張、カスタムツール名を無効化

edit ツールは Pi の TUI 表示用に details.diff を、SDK 利用者向けに標準 unified patch として details.patch を返します。

import { createAgentSession } from "@earendil-works/pi-coding-agent";
// Read-only mode
const { session } = await createAgentSession({
tools: ["read", "grep", "find", "ls"],
});
// Pick specific tools
const { session } = await createAgentSession({
tools: ["read", "bash", "grep"],
});
// Disable one tool while keeping the rest available
const { session } = await createAgentSession({
excludeTools: ["ask_question"],
});

カスタム cwd を渡すと、createAgentSession() はその cwd 向けに選択された組み込みツールを構築します。

import { createAgentSession, SessionManager } from "@earendil-works/pi-coding-agent";
const cwd = "/path/to/project";
// Use default tools for custom cwd
const { session } = await createAgentSession({
cwd,
sessionManager: SessionManager.inMemory(cwd),
});
// Or pick specific tools for custom cwd
const { session } = await createAgentSession({
cwd,
tools: ["read", "bash", "grep"],
sessionManager: SessionManager.inMemory(cwd),
});

examples/sdk/05-tools.ts を参照

import { Type } from "typebox";
import { createAgentSession, defineTool } from "@earendil-works/pi-coding-agent";
// Inline custom tool
const 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 directly
const { session } = await createAgentSession({
customTools: [myTool],
});

独立定義や customTools: [myTool] のような配列には defineTool() を使用します。インライン pi.registerTool({ ... }) は既にパラメータ型を正しく推論します。

customTools 経由のカスタムツールは、拡張登録ツールと結合されます。ResourceLoader で読み込まれた拡張も pi.registerTool() でツールを登録できます。

tools を渡す場合は、有効にしたい各カスタムまたは拡張ツール名を含めてください。例:tools: ["read", "bash", "my_tool"]

examples/sdk/05-tools.ts を参照

拡張機能は 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 する必要がある場合は、共有 eventBusDefaultResourceLoader に渡します:

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));

examples/sdk/06-extensions.tsdocs/extensions.md を参照

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 });

examples/sdk/04-skills.ts を参照

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 });

examples/sdk/07-context-files.ts を参照

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 });

examples/sdk/08-prompt-templates.ts を参照

セッションは 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 session
const { session: persisted } = await createAgentSession({
sessionManager: SessionManager.create(process.cwd()),
});
// Continue most recent
const { session: continued, modelFallbackMessage } = await createAgentSession({
sessionManager: SessionManager.continueRecent(process.cwd()),
});
if (modelFallbackMessage) {
console.log("Note:", modelFallbackMessage);
}
// Open specific file
const { session: opened } = await createAgentSession({
sessionManager: SessionManager.open("/path/to/session.jsonl"),
});
// List sessions
const 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 one
await runtime.newSession();
// Replace the active session with another saved session
await runtime.switchSession("/path/to/session.jsonl");
// Replace the active session with a fork from a specific user entry
await runtime.fork("entry-id");
// Clone the active path through a specific entry
await runtime.fork("entry-id", { position: "at" });

SessionManager ツリー API:

const sm = SessionManager.open("/path/to/session.jsonl");
// Session listing
const currentProjectSessions = await SessionManager.list(process.cwd());
const allSessions = await SessionManager.listAll(process.cwd());
// Tree traversal
const entries = sm.getEntries(); // All entries (excludes header)
const tree = sm.getTree(); // Full tree structure
const path = sm.getPath(); // Path from root to current leaf
const leaf = sm.getLeafEntry(); // Current leaf entry
const entry = sm.getEntry(id); // Get entry by ID
const children = sm.getChildren(id); // Direct children of entry
// Labels
const label = sm.getLabel(id); // Get label for entry
sm.appendLabelChange(id, "checkpoint"); // Set label
// Branching
sm.branch(entryId); // Move leaf to earlier entry
sm.branchWithSummary(id, "Summary..."); // Branch with context summary
sm.createBranchedSession(leafId); // Extract path to new file

examples/sdk/11-sessions.tsセッション形式 を参照

import { createAgentSession, SettingsManager, SessionManager } from "@earendil-works/pi-coding-agent";
// Default: loads from files (global + project merged)
const { session } = await createAgentSession({
settingsManager: SettingsManager.create(),
});
// With overrides
const 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 directories
const { session } = await createAgentSession({
settingsManager: SettingsManager.create("/custom/cwd", "/custom/agent"),
});

静的ファクトリ:

  • SettingsManager.create(cwd?, agentDir?) - ファイルから読み込み
  • SettingsManager.inMemory(settings?) - ファイル I/O なし

プロジェクト固有の設定:

設定は 2 箇所から読み込まれマージされます:

  1. グローバル:~/.pi/agent/settings.json
  2. プロジェクト:<cwd>/.pi/settings.json

プロジェクトがグローバルを上書きします。ネストされたオブジェクトはキーをマージします。setter はデフォルトでグローバル設定を変更します。

永続化とエラー処理のセマンティクス:

  • 設定の getter/setter はインメモリ状態に対して同期的です。
  • setter は永続化書き込みを非同期にキュー投入します。
  • 永続化境界が必要な場合(例:プロセス終了前、テストでファイル内容を検証する前)は await settingsManager.flush() を呼び出してください。
  • SettingsManager は設定 I/O エラーを出力しません。settingsManager.drainErrors() を使い、アプリ層で報告してください。

examples/sdk/10-settings.ts を参照

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 tool
const 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 overrides
const 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() 上にカスタムインターフェースを構築するための実行モードユーティリティをエクスポートします:

エディタ、チャット履歴、すべての組み込みコマンドを備えた完全な 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();

シングルショットモード:プロンプト送信、結果出力、終了:

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"],
});

サブプロセス統合用の 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 ドキュメント を参照してください。

SDK で構築せずサブプロセスベースの統合を行う場合は、CLI を直接使用します:

Terminal window
pi --mode rpc --no-session

JSON プロトコルは RPC ドキュメント を参照してください。

SDK を優先する場合:

  • 型安全性が必要
  • 同一 Node.js プロセス内で動作
  • agent 状態への直接アクセスが必要
  • ツール/拡張機能をプログラム的にカスタマイズしたい

RPC モードを優先する場合:

  • 他言語から統合
  • プロセス分離が必要
  • 言語非依存のクライアントを構築

メインエントリポイントは次をエクスポートします:

// Factory
createAgentSession
createAgentSessionRuntime
AgentSessionRuntime
// Auth and Models
AuthStorage
ModelRegistry
// Resource loading
DefaultResourceLoader
type ResourceLoader
createEventBus
// Constants and helpers
CONFIG_DIR_NAME
defineTool
getAgentDir
getPackageDir
getReadmePath
getDocsPath
getExamplesPath
// Session management
SessionManager
SettingsManager
// Tool factories
createCodingTools
createReadOnlyTools
createReadTool, createBashTool, createEditTool, createWriteTool
createGrepTool, createFindTool, createLsTool
// Types
type CreateAgentSessionOptions
type CreateAgentSessionResult
type ExtensionFactory
type ExtensionAPI
type ToolDefinition
type Skill
type PromptTemplate
type Tool

拡張型の完全な API は extensions.md を参照してください。