pi-mono/packages/coding-agent/examples/sdk
Armin Ronacher 8562bcf66a feat(coding-agent): codemode and MCP
This adds codemode and MCP support to pi. Codemode (packages/codemode) runs
model-written JavaScript in a QuickJS wasm VM inside a worker. From there the
script calls pi's tools as async functions, uses a per-session store, and can
read the model catalog and run classifiers. The codemode tool in coding-agent
is compatible with Codex's exec tool, and codemode.mode works like Codex's
tool modes (on or only). Large results are written to a JSON temp file. MCP
(packages/mcp) is a standalone client for stdio and streamable HTTP servers,
with OAuth.

The core only gets general mechanisms; codemode, tool_search and MCP are
built-in extensions that use them. Other extensions can replace these
built-ins. Tools declare an exposure: direct, model-only, codemode, deferred
or hidden. prepareLoadout() lets an orchestrating tool change which tool
declarations the model sees. ctx.executeTool() runs nested calls through
validation and the tool_call/tool_result hooks. Those calls emit events with
parentToolCallId and are recorded as bounded nestedCalls on the parent
result, which compaction and HTML export use. Tools can also return
structuredContent with an outputSchema, and can report errors with isError
instead of throwing. MCP servers come from mcp.json (global, or per project
after the project is trusted) or from pi.registerMcpServer(). They are
managed with /mcp and pi mcp list|login|logout, and their runtimes load on
first use.

Closes #10040
2026-09-29 09:12:50 +02:00
..
01-minimal.ts fix(coding-agent): dispose SDK example sessions 2026-05-11 13:26:08 +08:00
02-custom-model.ts fix(coding-agent): replace deprecated getModel in SDK example (#7306) 2026-07-30 22:01:49 +02:00
03-custom-prompt.ts fix(coding-agent): dispose SDK example sessions 2026-05-11 13:26:08 +08:00
04-skills.ts fix(coding-agent): dispose SDK example sessions 2026-05-11 13:26:08 +08:00
05-tools.ts fix(coding-agent): dispose SDK example sessions 2026-05-11 13:26:08 +08:00
06-extensions.ts fix(extension-examples): use agent_settled instead of end (#8242) 2026-08-17 13:10:23 +02:00
07-context-files.ts fix(coding-agent): dispose SDK example sessions 2026-05-11 13:26:08 +08:00
08-prompt-templates.ts fix(coding-agent): dispose SDK example sessions 2026-05-11 13:26:08 +08:00
09-api-keys-and-oauth.ts fix(coding-agent): make model refresh cancellation caller-owned 2026-08-04 00:03:52 +02:00
10-settings.ts fix(coding-agent): dispose SDK example sessions 2026-05-11 13:26:08 +08:00
11-sessions.ts fix(coding-agent): dispose SDK example sessions 2026-05-11 13:26:08 +08:00
12-full-control.ts fix(coding-agent): make model refresh cancellation caller-owned 2026-08-04 00:03:52 +02:00
13-session-runtime.ts chore: migrate pi packages to earendil works scope 2026-05-07 15:59:42 +02:00
14-codemode-mcp.ts feat(coding-agent): codemode and MCP 2026-09-29 09:12:50 +02:00
README.md feat(coding-agent): codemode and MCP 2026-09-29 09:12:50 +02:00

SDK Examples

Programmatic usage of pi-coding-agent via createAgentSession() and createAgentSessionRuntime().

The runtime example shows how to build a recreate function that closes over process-global fixed inputs and recreates cwd-bound services and sessions as the active session cwd changes.

Examples

File Description
01-minimal.ts Simplest usage with all defaults
02-custom-model.ts Select model and thinking level
03-custom-prompt.ts Replace or modify system prompt
04-skills.ts Discover, filter, or replace skills
05-tools.ts Built-in tool allowlists
06-extensions.ts Logging, blocking, result modification
07-context-files.ts AGENTS.md context files
08-prompt-templates.ts File-based prompt templates
09-api-keys-and-oauth.ts API key resolution, OAuth config
10-settings.ts Override compaction, retry, terminal settings
11-sessions.ts In-memory, persistent, continue, list sessions
12-full-control.ts Replace everything, no discovery
13-session-runtime.ts Manage runtime-backed session replacement
14-codemode-mcp.ts Add the codemode, tool_search, and MCP extensions

Running

cd packages/coding-agent
node examples/sdk/01-minimal.ts

Quick Reference

import { getModel } from "@earendil-works/pi-ai";
import {
  createAgentSession,
  DefaultResourceLoader,
  ModelRuntime,
  SessionManager,
  SettingsManager,
} from "@earendil-works/pi-coding-agent";

const modelRuntime = await ModelRuntime.create();

// Minimal
const { session } = await createAgentSession({ modelRuntime });

// Custom model
const model = getModel("anthropic", "claude-opus-4-5");
const { session } = await createAgentSession({ model, thinkingLevel: "high", modelRuntime });

// Modify prompt
const loader = new DefaultResourceLoader({
  systemPromptOverride: (base) => `${base}\n\nBe concise.`,
});
await loader.reload();
const { session } = await createAgentSession({ resourceLoader: loader, modelRuntime });

// Read-only
const { session } = await createAgentSession({ tools: ["read", "grep", "find", "ls"], modelRuntime });

// In-memory
const { session } = await createAgentSession({
  sessionManager: SessionManager.inMemory(),
  modelRuntime,
});

// Full control
const customRuntime = await ModelRuntime.create({
  authPath: "/my/app/auth.json",
  modelsPath: "/my/app/models.json",
});
await customRuntime.setRuntimeApiKey("anthropic", process.env.MY_KEY!);

const resourceLoader = new DefaultResourceLoader({
  systemPromptOverride: () => "You are helpful.",
  extensionFactories: [myExtension],
  skillsOverride: () => ({ skills: [], diagnostics: [] }),
  agentsFilesOverride: () => ({ agentsFiles: [] }),
  promptsOverride: () => ({ prompts: [], diagnostics: [] }),
});
await resourceLoader.reload();

const { session } = await createAgentSession({
  model,
  modelRuntime: customRuntime,
  resourceLoader,
  tools: ["read", "bash", "my_tool"],
  customTools: [myTool],
  sessionManager: SessionManager.inMemory(),
  settingsManager: SettingsManager.inMemory(),
});

// Run prompts
session.subscribe((event) => {
  if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
    process.stdout.write(event.assistantMessageEvent.delta);
  }
});
await session.prompt("Hello");

Options

Option Default Description
modelRuntime Runtime using agentDir/auth.json and models.json Canonical model and authentication runtime
cwd process.cwd() Working directory
agentDir ~/.pi/agent Config directory
model From settings/first available Model to use
thinkingLevel From settings/"off" off, low, medium, high
tools ["read", "bash", "edit", "write"] built-ins Allowlist tool names across built-in, extension, and custom tools
customTools [] Additional tool definitions
resourceLoader DefaultResourceLoader Resource loader for extensions, skills, prompts, themes, and context files
sessionManager SessionManager.create(cwd) Persistence
settingsManager SettingsManager.create(cwd, agentDir) Settings overrides

Events

session.subscribe((event) => {
  switch (event.type) {
    case "message_update":
      if (event.assistantMessageEvent.type === "text_delta") {
        process.stdout.write(event.assistantMessageEvent.delta);
      }
      break;
    case "tool_execution_start":
      console.log(`Tool: ${event.toolName}`);
      break;
    case "tool_execution_end":
      console.log(`Result: ${event.result}`);
      break;
    case "agent_settled":
      console.log("Done");
      break;
  }
});