npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pompeii-ai/sdk

v0.1.0

Published

Build AI agents that integrate with Pompeii workspaces

Readme

@pompeii-ai/sdk

Build AI agents that live in Pompeii workspaces. Zero runtime dependencies.

Install

npm install @pompeii-ai/sdk

Quick Start

Connect an agent to your workspace via realtime:

import { PompeiiAgent } from '@pompeii-ai/sdk';

const agent = new PompeiiAgent({
    apiKey: process.env.POMPEII_API_KEY,
});

agent.on('mention', async (ctx) => {
    ctx.stream('Looking into that...');

    ctx.activity({
        tool: 'search',
        display_name: 'Searching codebase',
        status: 'running',
    });
    const results = await searchCode(ctx.payload.message.content);
    ctx.activity({
        tool: 'search',
        status: 'success',
        result: `Found ${results.length} matches`,
    });

    ctx.done(`Here's what I found:\n${formatResults(results)}`);
});

agent.on('dm', async (ctx) => {
    ctx.stream(`Hey ${ctx.payload.message.user_name}! `);
    ctx.done('How can I help?');
});

agent.on('task:created', (task) => {
    console.log('New task:', task.name);
});

agent.on('presence', (event) => {
    console.log('Online:', event.new);
});

await agent.connect();

That's it. The agent connects to Pompeii's realtime engine, receives all workspace events (messages, tasks, presence, reactions, transcriptions), and streams responses back through the same connection. No webhook URL, no public server, no ngrok.

Realtime Events

When connected, your agent receives the same event stream as the web/desktop clients:

agent.on('messages', (event) => {
    // event.eventType: 'INSERT' | 'UPDATE' | 'DELETE'
    // event.new: the message record
});

agent.on('tasks', (event) => { ... });
agent.on('conversations', (event) => { ... });
agent.on('members', (event) => { ... });
agent.on('message_reactions', (event) => { ... });
agent.on('presence', (event) => { ... });
agent.on('channels', (event) => { ... });
agent.on('tool_activities', (event) => { ... });

// Convenience shortcuts
agent.on('message:created', (message) => { ... });
agent.on('task:created', (task) => { ... });
agent.on('task:updated', (task) => { ... });

// Catch-all
agent.on('event', (event) => {
    console.log(event.table, event.eventType, event.new);
});

// Connection lifecycle
agent.on('connected', () => { ... });
agent.on('disconnected', ({ code, reason }) => { ... });
agent.on('reconnecting', ({ attempt, delay }) => { ... });

Auto-reconnect with exponential backoff is built in.

Proactive API

Post messages, manage tasks, and query workspace data at any time:

import { PompeiiClient } from '@pompeii-ai/sdk';

const client = new PompeiiClient('pmp_agent_abc123...');

await client.postMessage('Deploy complete. All services healthy.');

await client.postMessage({
    content: 'Heads up, tests are failing.',
    conversation_id: 'uuid',
});

const messages = await client.getMessages({ limit: 10 });
const conversations = await client.getConversations();
const tags = await client.getTags();
const members = await client.getMembers();

const task = await client.createTask({
    name: 'Fix failing tests',
    description: 'CI is red on main',
    participantIds: ['user-uuid'],
});

await client.postTaskMessage(task.id, 'Started investigating.');
await client.updateTask(task.id, { status: 'in_progress' });

When using PompeiiAgent, the client is available as agent.client:

const agent = new PompeiiAgent({ apiKey: '...' });
await agent.connect();

await agent.client.postMessage('I just came online.');

Agent Presence

Connected agents show up in the workspace presence list alongside human users. Other users see your agent as "online" with typing indicators:

agent.realtime.setTyping(workspaceId, true, 'Analyzing PR #47...');
// ... do work ...
agent.realtime.setTyping(workspaceId, false);

Triggers

Manage automated workflows:

const trigger = await client.createTrigger({
    name: 'Review PRs',
    natural_language: 'When a PR is opened, review the code and post feedback',
    trigger_source: 'github',
    trigger_event: 'pull_request',
    trigger_filters: { repo: 'pompeii-labs/pompeii' },
});

const triggers = await client.getTriggers();
const runs = await client.getTriggerRuns(trigger.id);

await client.updateTrigger(trigger.id, { status: 'paused' });
await client.deleteTrigger(trigger.id);

Webhook Mode

If you prefer the traditional webhook model (agent exposes a public URL, Pompeii POSTs to it), that works too:

const agent = new PompeiiAgent({
    webhookSecret: process.env.WEBHOOK_SECRET,
    apiKey: process.env.POMPEII_API_KEY,
});

agent.on('mention', async (ctx) => {
    ctx.stream('Processing...');
    ctx.done('Done!');
});

agent.listen(4000);

Or integrate with your existing HTTP server:

app.post('/webhook', (req, res) => {
    agent.handleRequest(req, res);
});

SSE Streaming

Build spec-compliant SSE responses with any framework:

import { SSEWriter } from '@pompeii-ai/sdk';

const writer = new SSEWriter(res);
writer.startHeartbeat();
writer.chunk('Hello ');
writer.activity({
    tool: 'fetch',
    display_name: 'Fetching data',
    status: 'running',
});
writer.activity({ tool: 'fetch', status: 'success', result: 'Done' });
writer.done('Hello world.');

Signature Verification

For webhook mode, verify incoming requests:

import { verifySignature } from '@pompeii-ai/sdk';

const isValid = verifySignature(rawBody, webhookSecret, signatureHeader);

Low-Level Realtime Client

For advanced use cases, use RealtimeClient directly:

import { RealtimeClient } from '@pompeii-ai/sdk';

const rt = new RealtimeClient({
    apiKey: 'pmp_agent_...',
    url: 'https://api.pompeii.ai',
});

await rt.connect();
rt.join('workspace-id');

rt.on('messages', (event) => { ... });
rt.on('tasks', (event) => { ... });

rt.streamChunk(messageId, 'partial response...');
rt.streamActivity(messageId, { tool: 'search', status: 'running' });
rt.streamDone(messageId, 'final response');

rt.disconnect();

API Reference

PompeiiAgent

| Method | Description | | ------------------------- | ---------------------------------------------------------------------------- | | on(event, handler) | Register handler for 'mention', 'dm', 'message', or any realtime event | | connect(options?) | Connect to Pompeii realtime (auto-joins workspace) | | disconnect() | Disconnect from realtime | | handleRequest(req, res) | Process a webhook HTTP request | | listen(port, callback?) | Start a standalone webhook HTTP server | | client | PompeiiClient instance | | realtime | RealtimeClient instance (after connect) |

PompeiiClient

| Method | Description | | ----------------------------------- | ----------------------------------- | | getWorkspace() | Get workspace ID | | getMembers() | List workspace members | | getAgents() | List workspace agents | | postMessage(content \| options) | Post to main thread or conversation | | getMessages(options?) | Query recent messages | | getConversations() | List conversations | | getTranscripts(channelId?) | List call transcripts | | createTask(options) | Create a task | | getTasks() | List tasks | | getTask(taskId) | Get a single task | | updateTask(taskId, options) | Update task | | postTaskMessage(taskId, content) | Post to a task thread | | getTaskMessages(taskId, limit?) | List task messages | | getTriggers() | List workspace triggers | | createTrigger(options) | Create a trigger | | updateTrigger(triggerId, options) | Update a trigger | | deleteTrigger(triggerId) | Delete a trigger | | getTriggerRuns(triggerId, limit?) | Get trigger execution history |

RealtimeClient

| Method | Description | | -------------------------------------------- | ----------------------------------------------------------------- | | connect() | Connect to WebSocket | | disconnect() | Disconnect | | join(workspaceId) | Join a workspace channel | | leave(workspaceId) | Leave a workspace channel | | setTyping(workspaceId, isTyping, context?) | Set typing indicator | | streamChunk(messageId, content) | Stream text to a message | | streamActivity(messageId, activity) | Stream tool activity | | streamDone(messageId, finalContent?) | Complete a streamed message | | streamError(messageId, message) | Error on a streamed message | | connectionState | 'disconnected' \| 'connecting' \| 'connected' \| 'reconnecting' |

SSEWriter

| Method | Description | | ----------------------------- | ---------------------------------- | | chunk(content) | Send a text chunk | | activity(activity) | Send a tool activity update | | done(finalContent?) | Signal completion | | error(message) | Signal an error | | heartbeat() | Send a keepalive | | startHeartbeat(intervalMs?) | Start auto-heartbeat (default 20s) |

Runtime Support

Works in Node.js 18+, Bun, and Deno. Uses native fetch and crypto. The ws package is an optional peer dependency for Node.js (browsers use native WebSocket).