How to Embed the Prime Agent SDK in Your Node.js Application

Import createAgentSession from @earendil-works/pi-coding-agent to instantiate a fully configured AgentSession that handles LLM interactions, tool execution, and state persistence without spawning external processes.

The Prime Agent SDK (@earendel-works/pi-coding-agent) provides a TypeScript interface for running the autonomous coding agent directly inside your application. Unlike the CLI interface, embedding the SDK gives you fine-grained control over authentication, model selection, resource loading, and conversation branching while maintaining full type safety and zero subprocess overhead.

Core Architecture of the SDK

The SDK centers on a factory pattern that assembles runtime services and returns a high-level session object you can drive programmatically.

The createAgentSession Factory

Located in packages/coding-agent/src/core/sdk.ts, the createAgentSession function (lines 55-66) orchestrates the initialization sequence:

  1. Resolves the working directory (cwd) and global config directory (agentDir)
  2. Instantiates AuthStorage and ModelRegistry (or accepts injected instances)
  3. Builds a SettingsManager and SessionManager for configuration and persistence
  4. Creates a DefaultResourceLoader to discover extensions, skills, prompts, and themes
  5. Resolves the initial Model from options, session restore, or defaults
  6. Constructs the underlying Agent with streaming and retry logic
  7. Returns an AgentSession with loaded extensions and diagnostics

Key Runtime Components

Component Source File Responsibility
AgentSession packages/coding-agent/src/agent-session.ts High-level API exposing prompt(), steer(), followUp(), and subscribe() methods
AuthStorage packages/coding-agent/src/auth-storage.ts Resolves API keys from environment variables, ~/.prime/agent/auth.json, or runtime overrides
ModelRegistry packages/coding-agent/src/model-registry.ts Exposes available models and validates credentials
DefaultResourceLoader packages/coding-agent/src/resource-loader.ts Discovers extensions, skills, prompts, themes, and context files from ~/.prime/agent and .prime/agent directories
SessionManager packages/coding-agent/src/session-manager.ts Persists conversation trees to session.jsonl, supports branching, forking, and cloning operations
SettingsManager packages/coding-agent/src/settings-manager.ts Manages runtime configuration including thinking level, timeouts, retry limits, and tool allow-lists
ExtensionRunner packages/coding-agent/src/extensions/index.ts Executes user-defined extensions that can register tools, subscribe to events, or inject custom commands

Quick Start: Running Your First Prompt

Install the SDK package, then instantiate the minimal required services to create an in-memory session:

import { AuthStorage, createAgentSession, ModelRegistry, SessionManager } from "@earendil-works/pi-coding-agent";

const authStorage = AuthStorage.create();                       // uses ~/.prime/agent/auth.json
const modelRegistry = ModelRegistry.create(authStorage);        // reads ~/.prime/agent/models.json
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("List the files in the current directory");

This example streams token-level deltas to stdout as the agent generates its response. The AuthStorage.create() call automatically discovers credentials from your environment or the standard Prime Agent configuration directory.

Configuring Models and Custom Tools

For production use, explicitly specify the model and tool set rather than relying on defaults. The findInitialModel logic in packages/coding-agent/src/core/sdk.ts (lines 8-16) checks options, restored sessions, settings, and finally the first available model.

import { getModel } from "@earendil-works/pi-ai";
import {
  AuthStorage,
  createAgentSession,
  DefaultResourceLoader,
  defineTool,
  ModelRegistry,
  SessionManager,
  SettingsManager,
} from "@earendil-works/pi-coding-agent";
import { Type } from "typebox";

// Load a specific Claude model
const model = getModel("anthropic", "claude-opus-4-5");

// Define a simple custom tool
const echoTool = defineTool({
  name: "echo",
  label: "Echo",
  description: "Returns the supplied text",
  parameters: Type.Object({ text: Type.String() }),
  execute: async (_, { text }) => ({
    content: [{ type: "text", text }],
    details: {},
  }),
});

const settings = SettingsManager.inMemory({ thinking: { enabled: false } });
const loader = new DefaultResourceLoader({ settingsManager: settings });
await loader.reload();

const { session } = await createAgentSession({
  model,
  tools: ["ipython"],               // enable only the built‑in ipython tool
  customTools: [echoTool],          // add our custom tool
  resourceLoader: loader,
  sessionManager: SessionManager.inMemory(),
});

Use the tools array to whitelist built-in tools (set noTools: "all" to disable entirely) and customTools to inject your own implementations via the defineTool helper.

Advanced: Custom Resource Loaders and Persistent Sessions

Override resource discovery to inject prompt templates or load extensions from non-standard paths. The DefaultResourceLoader accepts a promptsOverride function and custom agentDir parameters:

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

// Custom loader that injects a global prompt template
const loader = new DefaultResourceLoader({
  cwd: process.cwd(),
  agentDir: "/custom/.prime/agent",
  settingsManager: SettingsManager.create(),
  promptsOverride: (cur) => ({
    prompts: [
      ...cur.prompts,
      {
        name: "hello",
        description: "Greets the user",
        source: "(inline)",
        content: "# Hello\n\nSay hello to the user.",

      },
    ],
    diagnostics: cur.diagnostics,
  }),
});
await loader.reload();

// Persistent session stored under the default `sessions/` directory
const { session } = await createAgentSession({
  resourceLoader: loader,
  sessionManager: SessionManager.create(process.cwd()),
});

// Simple extension that logs every tool execution
session.subscribe(event => {
  if (event.type === "tool_execution_start") {
    console.log(`🛠️  Tool started: ${event.toolName}`);
  }
});

await session.prompt("Run the hello prompt");

Extensions loaded by the ResourceLoader receive the same ExtensionAPI used by the interactive TUI, allowing you to register event listeners that react to tool execution or message updates.

Managing Session Lifecycle with the Runtime API

When you need to replace the active session programmatically (for example, after forking or importing a conversation), use the lower-level runtime constructors. The extensionRunnerRef in packages/coding-agent/src/core/sdk.ts (lines 21-30) demonstrates how the SDK wires extensions into the session lifecycle:

import {
  createAgentSessionRuntime,
  createAgentSessionServices,
  getAgentDir,
  InteractiveMode,
  SessionManager,
} from "@earendil-works/pi-coding-agent";

const services = await createAgentSessionServices({ cwd: process.cwd() });
const runtime = await createAgentSessionRuntime(
  async ({ cwd, sessionManager }) => ({
    ...(await createAgentSessionFromServices({
      services,
      sessionManager,
      sessionStartEvent: undefined,
    })),
    services,
    diagnostics: services.diagnostics,
  }),
  {
    cwd: process.cwd(),
    agentDir: getAgentDir(),
    sessionManager: SessionManager.create(process.cwd()),
  }
);

// Switch to a fresh session
await runtime.newSession();
const session = runtime.session;   // new AgentSession instance

This pattern is useful for long-running applications that must manage multiple conversation branches or implement custom session management UIs.

Summary

  • Import createAgentSession from @earendil-works/pi-coding-agent as the primary entry point for embedding the agent.
  • Provide explicit services (AuthStorage, ModelRegistry, SessionManager) to override default credential discovery and persistence behavior.
  • Use DefaultResourceLoader to customize where the SDK searches for prompts, skills, and extensions.
  • Register custom tools via the customTools array and the defineTool helper with JSON Schema validation.
  • Subscribe to events using session.subscribe() to stream tokens, monitor tool execution, or inject UI updates.
  • Manage persistence with SessionManager.create() for file-based storage or SessionManager.inMemory() for ephemeral sessions.

Frequently Asked Questions

How do I install the Prime Agent SDK?

Install the package via npm or yarn: npm install @earendil-works/pi-coding-agent. The SDK requires Node.js and expects TypeScript 5.0+ for full type support. All dependencies, including the core agent runtime and tool definitions, are bundled with the package.

Can I use custom tools when embedding the SDK?

Yes. Define tools using the defineTool helper from @earendil-works/pi-coding-agent, which accepts a name, description, JSON Schema parameters (using Typebox), and an async execution function. Pass your custom tools to the customTools array in createAgentSession options. Built-in tools like ipython can be enabled via the tools allow-list or disabled entirely with noTools: "all".

How does session persistence work when embedding the SDK?

The SessionManager handles persistence. Use SessionManager.create(cwd) to write conversation trees to a sessions/ directory as JSONL files (session.jsonl), or use SessionManager.inMemory() for stateless operation. When restoring, pass the same sessionManager instance to createAgentSession and the SDK will automatically resume from the persisted state.

What is the difference between the SDK and the CLI mode?

The CLI (prime-agent) is a thin wrapper around the same SDK functions that provides a TUI and JSON-RPC interface. When you embed the SDK directly, you skip the subprocess overhead and gain programmatic access to the AgentSession object, allowing you to customize streaming behavior, implement custom authentication flows, and integrate the agent into existing Node.js applications without shelling out.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →