7.2 KiB
SDK
@earendil-works/pi-coding-agent embeds Pi in a Node.js or Bun process. It provides direct TypeScript access to the agent, sessions, tools, models, and resources used by the command-line application.
Use the SDK for in-process TypeScript integration. For a language-independent or isolated subprocess, see CLI Integration.
import { createAgentSession } from "@earendil-works/pi-coding-agent";
const { session } = await createAgentSession();
try {
await session.prompt("What files are in the current directory?");
console.log(session.getLastAssistantText());
} finally {
session.dispose();
}
This uses the working directory, discovered resources, stored settings, and configured credentials. prompt() resolves when the run finishes.
The complete minimal example also streams text events. All SDK examples are typechecked with the repository.
Session lifecycle
createAgentSession() creates an AgentSession. The session owns one conversation, its model and tools, queued messages, compaction state, and extension runtime.
Read current state through session.messages, session.model, session.thinkingLevel, session.systemPrompt, and session.getActiveToolNames().
Sessions are persistent by default. Supply a SessionManager to choose another storage policy:
import { SessionManager } from "@earendil-works/pi-coding-agent";
const transientSessions = SessionManager.inMemory();
const persistentSessions = SessionManager.create(process.cwd());
Pass the selected manager as sessionManager when creating the session. The sessions example shows how to create, continue, list, and open sessions.
cwd selects the workspace used for project resource discovery, context files, session grouping, and built-in tool paths. Pass it explicitly when the target differs from process.cwd().
session.dispose() aborts active work, invalidates extension contexts, disconnects from the agent, and removes event listeners. Call it when the session is no longer needed.
AgentSessionRuntime adds newSession(), switchSession(), fork(), and importFromJsonl(). Each operation replaces the active AgentSession and recreates services for the target working directory.
After a runtime replacement, subscriptions belong to the old AgentSession and must be rebound. See the session runtime example.
Prompting
prompt() handles extension commands and expands file-based prompt templates before ordinary user messages enter the agent. For an accepted agent run, it resolves after the run finishes, including automatic retries.
A prompt sent while the session is already streaming must specify whether it should steer the current run or follow it. Calling prompt() without that choice rejects rather than guessing.
A steering message enters after the current assistant turn and its tool calls. A follow-up enters after the current run finishes its pending work. steer() and followUp() expose those behaviors directly.
abort() stops the active operation and waits for the session to become idle. waitForIdle() waits without aborting it.
Subscribing to events
Subscribe before prompting when the host needs streamed output:
const unsubscribe = session.subscribe((event) => {
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
process.stdout.write(event.assistantMessageEvent.delta);
}
});
try {
await session.prompt("Explain this repository");
} finally {
unsubscribe();
}
Session events report message updates, tool execution, queues, compaction, retries, and run lifecycle changes.
message_end contains the authoritative completed message. agent_end marks the end of one low-level agent run, but automatic recovery or queued work can still follow.
Use agent_settled when the host needs to know that Pi will not continue automatically.
Configuring a session
Without overrides, the factory creates a ModelRuntime, file-backed SettingsManager, persistent SessionManager, DefaultResourceLoader, and the configured default tools.
Each boundary can be supplied explicitly:
modelRuntime,model,thinkingLevel, andscopedModelscontrol model access and selection.settingsManagersupplies merged settings or an in-memory configuration.sessionManagersupplies persistent or in-memory conversation history.resourceLoadersupplies extensions, skills, prompt templates, themes, and context files.tools,noTools,excludeTools, andcustomToolscontrol the active tool set.
Use DefaultResourceLoader when you want standard discovery with selected overrides. Supply a custom ResourceLoader when the host owns resource storage and discovery completely.
Inline extension factories can be supplied through DefaultResourceLoader. Give one an InlineExtension name only when it needs a stable name in diagnostics and startup output.
See the focused examples for models, tools, extensions, and full control.
Examples
| Example | Purpose |
|---|---|
| Minimal | Create, prompt, observe, and dispose a session |
| Custom model | Select a model and thinking level |
| System prompt | Replace or append to the system prompt |
| Skills | Discover, filter, and add skills |
| Tools | Select built-in tools and their working directory |
| Extensions | Load file-based and inline extensions |
| Context files | Add or replace project instructions |
| Prompt templates | Add file-style prompt templates |
| Credentials | Configure credential and model storage |
| Settings | Supply file-backed or in-memory settings |
| Sessions | Control session persistence and restoration |
| Full control | Replace default discovery and state services |
| Session runtime | Replace the active session safely |
Resources
- Choose a Model covers model selection and authentication; Provider Setup and Custom Models provide exact configuration.
- Configuration explains normal discovery and settings; Settings lists every setting.
- Sessions and Context explains session behavior; Session Format defines persisted entries.
- Extensions, Skills, and Prompt Templates document resources supplied through a
ResourceLoader. - CLI Integration covers print, JSON, and RPC alternatives to an in-process SDK integration.