@pillar-ai/server
v0.2.4
Published
Pillar backend SDK — register server-side tools and handle tool calls
Readme
@pillar-ai/server
Backend SDK for Pillar — register server-side tools and handle tool calls from Pillar Cloud.
Install
npm install @pillar-ai/serverOptional peer dependencies for Zod schema support:
npm install zod zod-to-json-schemaQuick Start
import { Pillar, defineTool } from '@pillar-ai/server';
import { z } from 'zod';
const pillar = new Pillar({
secret: process.env.PILLAR_SECRET!,
endpointUrl: 'https://api.myapp.com/pillar',
});
const lookupCustomer = defineTool({
name: 'lookup_customer',
description: 'Look up a customer by email address',
input: z.object({
email: z.string().email().describe('Customer email address'),
}),
execute: async ({ email }, ctx) => {
const customer = await db.findByEmail(email);
return { name: customer.name, plan: customer.plan };
},
});
await pillar.registerTools([lookupCustomer]);Framework Integration
Express
import express from 'express';
const app = express();
app.use(express.json());
app.post('/pillar', pillar.expressHandler());
app.listen(3000);Hono
import { Hono } from 'hono';
const app = new Hono();
app.post('/pillar', pillar.honoHandler());Next.js (App Router)
// app/api/pillar/route.ts
export const POST = pillar.nextHandler();Fastify
import Fastify from 'fastify';
const fastify = Fastify();
fastify.post('/pillar', pillar.fastifyHandler());
fastify.listen({ port: 3000 });Standalone
pillar.serve({ port: 8787 });Plain JSON Schema (No Zod)
const lookupCustomer = defineTool({
name: 'lookup_customer',
description: 'Look up a customer by email',
inputSchema: {
type: 'object',
properties: {
email: { type: 'string', description: 'Customer email' },
},
required: ['email'],
},
execute: async ({ email }: { email: string }, ctx) => {
return { name: 'Jane' };
},
});API Reference
Pillar
new Pillar({
secret: string, // Required. Your Pillar secret (used for auth and signature verification).
endpointUrl?: string, // URL where Pillar Cloud sends tool calls.
autoRegister?: boolean, // Auto-register tools on first call (default: true).
baseUrl?: string, // Pillar API base URL (default: https://api.trypillar.com).
logger?: Logger, // Custom logger.
})defineTool
defineTool({
name: string, // Unique tool name.
description: string, // Human-readable description.
input?: ZodSchema, // Zod schema (optional).
inputSchema?: JsonSchema, // Plain JSON Schema (optional).
outputSchema?: JsonSchema, // Output schema (optional).
guidance?: string, // Agent instructions.
timeoutMs?: number, // Timeout in ms (default: 30000).
channelCompatibility?: string[], // Channels (default: all).
execute: (input, ctx) => any, // Handler function.
})ToolContext
interface ToolContext {
caller: CallerInfo;
conversationId: string;
callId: string;
productId?: string;
isIdentified: boolean;
confirmed: boolean; // true when re-executing after user confirmation
}
interface CallerInfo {
channel: 'web' | 'slack' | 'discord' | 'email' | 'api';
channelUserId?: string;
externalUserId?: string;
email?: string;
displayName?: string;
}Confirmation responses
When a tool needs user confirmation before performing an action, return a ConfirmationResponse from execute. Pillar renders a channel-appropriate confirmation UI (Block Kit buttons in Slack, structured JSON in the copilot) and re-calls execute with ctx.confirmed = true after the user confirms.
import { defineTool, type ConfirmationResponse } from '@pillar-ai/server';
const createPlan = defineTool({
name: 'create_plan',
description: 'Create a new plan',
input: z.object({ name: z.string(), price: z.number() }),
execute: async (input, ctx): Promise<ConfirmationResponse | { created: boolean }> => {
if (!ctx.confirmed) {
return {
confirmation_required: true,
title: 'Create plan',
message: `Create "${input.name}" at $${input.price}/mo?`,
details: {
'Plan name': input.name,
'Price': `$${input.price}/mo`,
},
confirm_payload: input,
};
}
await db.createPlan(input);
return { created: true };
},
});ConfirmationResponse
| Field | Required | Description |
|---|---|---|
| confirmation_required | yes | Must be true. |
| title | no | Short headline. Defaults to the tool name. |
| message | no | One-line description shown before the buttons. |
| details | no | Key-value pairs rendered as a summary card. |
| confirm_payload | no | Opaque data passed back to execute on confirm. Defaults to the original arguments. |
