@pompeii-ai/sdk
v0.1.0
Published
Build AI agents that integrate with Pompeii workspaces
Maintainers
Readme
@pompeii-ai/sdk
Build AI agents that live in Pompeii workspaces. Zero runtime dependencies.
Install
npm install @pompeii-ai/sdkQuick 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).
