Can PrimeAgent Be Extended with Custom Modules? A Complete Guide to the Plugin Architecture

Yes, PrimeAgent is designed as a modular, plugin-friendly platform with four official extension points—AI providers, coding-agent skills, TUI components, and configuration hooks—that let developers add functionality without modifying core source code.

PrimeAgent separates its core services (AI provider handling, coding-agent orchestration, and terminal UI rendering) from extension points discovered at startup through glob patterns. This architecture, implemented in the PrimeIntellect-ai/prime-agent repository, enables dynamic loading of custom modules from the plugins/ directory without requiring a full rebuild.


AI Providers: Adding Custom LLM Backends

The AI provider system in packages/ai/src/providers/register-builtins.ts uses a lazy-loading registration pattern. You implement a standard interface and register your provider by name.

Provider Interface Requirements

Your provider must export two streaming functions:

  • stream(model, messages, opts) — full streaming with metadata
  • streamSimple(model, messages, opts) — simplified text-only streaming

Both return AssistantMessageEventStream objects defined in packages/ai/src/types.

Implementation Example

// packages/ai/src/providers/my-custom-provider.ts
import {
  AssistantMessageEventStream,
  StreamOptions,
} from "../types";

export interface MyProviderOptions extends StreamOptions {
  temperature?: number;
}

export async function stream(
  model: string,
  messages: any[],
  opts: MyProviderOptions,
): Promise<AssistantMessageEventStream> {
  // Translate your LLM's response format to AssistantMessageEventStream
  return new ReadableStream({
    start(controller) {
      // Stream events matching the expected shape
    }
  });
}

export async function streamSimple(
  model: string,
  messages: any[],
  opts: MyProviderOptions
): Promise<ReadableStream<string>> {
  // Simplified text-only output
}

Registration

Lazy-load your provider in the registry to avoid initialization overhead:

// packages/ai/src/providers/register-builtins.ts
import { registerBuiltinProvider } from "./registry";

registerBuiltinProvider("my-custom-api", async () =>
  import("./my-custom-provider")
);

When a user specifies api: "my-custom-api" in their configuration, PrimeAgent dynamically imports and instantiates your provider.


Coding-Agent Skills: Adding Custom Commands

Skills extend PrimeAgent's command vocabulary. The package manager in packages/coding-agent/src/package-manager.ts scans plugins/*/skills at startup and auto-discovers modules matching the skill interface.

Skill Structure

Each skill requires:

  • SKILL.md — documentation for the LLM and users
  • skill.ts — TypeScript module exporting a Skill object

Complete Skill Example

// plugins/pdf-to-markdown/skills/pdf-to-markdown/skill.ts
import { Skill } from "coding-agent";

export const skill: Skill = {
  name: "pdf-to-markdown",
  description: "Convert a PDF file to Markdown text",
  async run({ args, context }) {
    const [pdfPath] = args;
    if (!pdfPath) {
      throw new Error("Usage: pdf-to-markdown <path>");
    }
    // Your conversion logic here
    const markdown = await convertPdf(pdfPath);
    return { output: markdown };
  },
};
<!-- plugins/pdf-to-markdown/skills/pdf-to-markdown/SKILL.md -->

# pdf-to-markdown

Converts a PDF document to Markdown.

## Usage

pdf-to-markdown


## Examples

Convert a research paper:

pdf-to-markdown ./paper.pdf

Upon restart, PrimeAgent recognizes /run pdf-to-markdown ./doc.pdf as a valid command in both CLI and TUI modes.


TUI Components: Extending the Terminal Interface

PrimeAgent's terminal UI, built on Blessed, exposes extension points in packages/tui/src/index.ts for custom widgets and key bindings.

Widget Implementation

// packages/tui/src/custom-status.ts
import { Box } from "blessed";

export function createStatusWidget(): Box {
  const widget = new Box({
    top: "100%-1",
    left: 0,
    width: "100%",
    height: 1,
    style: { bg: "gray", fg: "white" },
    tags: true,
    content: "{center}Custom Provider: Ready{/center}",
  });

  // Expose update method for external callers
  (widget as any).setStatus = (text: string) => {
    widget.setContent(`{center}${text}{/center}`);
    widget.screen.render();
  };

  return widget;
}

Integration Point

// packages/tui/src/index.ts
import { createStatusWidget } from "./custom-status";
import { DEFAULT_EDITOR_KEYBINDINGS } from "./keys";

export function init(screen: blessed.Widgets.Screen) {
  const status = createStatusWidget();
  screen.append(status);

  // Add custom key binding
  DEFAULT_EDITOR_KEYBINDINGS["C-x"] = () => {
    status.setStatus("Action triggered!");
  };

  // ... existing initialization
}

The widget integrates immediately because screen.append() registers it with Blessed's rendering loop.


Configuration Hooks: Runtime Behavior Modification

PrimeAgent's configuration system supports extension through environment variables and JSON configuration, resolved in two key files:

File Purpose Extension Method
packages/ai/src/env-api-keys.ts API key resolution Add new provider API key patterns
packages/coding-agent/src/core/model-resolver.ts Default model mapping Register defaults for custom providers

Both files use dynamic property access, so new environment variables or config keys become automatically available throughout the system without type definition changes.


Key Architectural Files for PrimeAgent Extension

Understanding these files clarifies how the plugin system operates:


Summary

PrimeAgent's extension architecture enables custom module integration through four mechanisms:

  • AI providers — Implement stream/streamSimple interfaces and register in register-builtins.ts for lazy-loaded LLM support
  • Skills — Create plugins/<name>/skills/<skill>/ directories with skill.ts and SKILL.md for auto-discovered commands
  • TUI widgets — Export Blessed components from packages/tui/src/ and append to the screen instance
  • Configuration — Extend env-api-keys.ts or model-resolver.ts for runtime behavior customization

All extension points use dynamic import() and glob-based discovery, enabling drop-in functionality without recompiling the core project.


Frequently Asked Questions

Does PrimeAgent require rebuilding to add custom modules?

No. The package manager and provider registry use dynamic import() statements with glob patterns (plugins/*/skills). Place your code in the correct directory structure and restart PrimeAgent—the new functionality loads automatically without a build step.

What interface must a custom AI provider implement?

Your provider must export stream(model, messages, opts) and streamSimple(model, messages, opts) functions returning AssistantMessageEventStream or ReadableStream<string> respectively, as defined in packages/ai/src/types. Register via registerBuiltinProvider() in register-builtins.ts.

Can skills access the full PrimeAgent context?

Yes. The Skill.run method receives a context object containing args (parsed arguments), fs (sandboxed filesystem access), and llm (query interface to the active provider). Check packages/coding-agent/src/types.ts for the complete SkillContext interface.

How do I debug a skill that isn't loading?

Verify three things: (1) your file path matches plugins/*/skills/<name>/skill.ts, (2) the file exports skill as a named export matching the Skill interface, and (3) SKILL.md exists in the same directory. The package manager logs discovery results when DEBUG=prime-agent is set in your environment.

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 →