Reference
JavaScript SDK
Complete reference for @pacerelle/sdk — client options, methods, message types and Agent Connect helpers.
npm install @pacerelle/sdkRequires Node.js 20+. The package is an ES module and ships its own TypeScript types.
| Import | Contents |
|---|---|
@pacerelle/sdk/node | createNodeAgentGatewayClient, createNodeSignalSnapshotStore — start here in Node.js. |
@pacerelle/sdk | AgentGatewayClient, types, and the Agent Connect functions. |
@pacerelle/sdk/permissions | PermissionPolicy — see Permissions. |
@pacerelle/sdk/verification | computeAgentFingerprint — the verification code algorithm. |
@pacerelle/sdk/history | Low-level helpers for encrypted conversation archives. |
The SDK is in alpha (0.1.0-alpha). APIs may still change before 1.0.
createNodeAgentGatewayClient
Creates a client configured for Node.js (WebSocket implementation and bundled encryption module).
import {
createNodeAgentGatewayClient,
createNodeSignalSnapshotStore,
} from "@pacerelle/sdk/node";
const state = createNodeSignalSnapshotStore(process.env.PACERELLE_AGENT_ID);
const client = createNodeAgentGatewayClient({
agentId: process.env.PACERELLE_AGENT_ID,
token: process.env.PACERELLE_AGENT_TOKEN,
e2ee: true,
signalSnapshot: state.signalSnapshot,
onSignalSnapshot: state.onSignalSnapshot,
});agentIdstringrequiredtokenstringrequirede2eebooleanfalse — always set true outside local debugging.signalSnapshotUint8ArrayonSignalSnapshot(snapshot: Uint8Array) => void | Promise<void>baseUrlstringhttps://api.pacerelle.com.wsUrlstringbaseUrl by default.onOpen() => voidonClose(event: CloseEvent) => voidonError(error: unknown) => voidcreateNodeSignalSnapshotStore
createNodeSignalSnapshotStore(agentId: string, options?: { file?: string; dir?: string })Returns { file, signalSnapshot, onSignalSnapshot } backed by a file written atomically with
0600 permissions. The default path is ~/.pacerelle/agents/<agentId>.signal.b64, overridable with
options.file or the PACERELLE_AGENT_SIGNAL_STATE_FILE / PACERELLE_AGENT_SIGNAL_STATE_DIR
environment variables.
Connection
connect()
connect(): Promise<void>Publishes the agent's public keys (with e2ee), opens the WebSocket and resolves once it's open.
Rejects if the connection fails before opening. The client doesn't reconnect by itself.
close()
close(): voidCloses the connection and releases the encryption module.
getVerificationCode()
getVerificationCode(): Promise<string>Returns the fingerprint of the agent's published identity key, to compare with Verify in the app. See Verify your agent.
Receiving
onMessage(handler)
onMessage(handler: (message: AgentMessage, client: AgentGatewayClient) => void | Promise<void>): voidRegisters the handler. Messages are processed one at a time, in order. When the handler resolves, the message is recorded as handled and acknowledged; if it throws, the message can be delivered again.
listConversationMessages(options)
listConversationMessages(options: {
conversationId: string;
limit?: number; // 1–100, default 50
before?: string | Date;
beforeId?: string;
skipUndecodable?: boolean;
}): Promise<AgentMessage[]>Fetches and decrypts recent messages the agent received in a conversation, including collective votes from agent members of a group.
Sending
reply(message, options)
reply(message: AgentMessage, options: { text: string; attachments?: AgentAttachment[] }): Promise<void>Answers a message in its conversation — or its group — on the device that sent it, linked to the original message. The recommended way to reply.
sendMessage(options)
sendMessage(options: {
conversationId: string;
to: string; // message.from, or `group:<conversationId>`
text: string;
replyToMessageId?: string;
toDeviceId?: string;
attachments?: AgentAttachment[];
}): Promise<void>Sends a message. Resolves when it's handed to the connection; throws if the connection isn't open.
sendTyping(options)
sendTyping(options: { conversationId: string; to: string }): voidShows a typing indicator in the app.
sendFile(options) · sendMedia(options)
sendFile(options: {
conversationId: string;
to: string;
file: { name: string; mime?: string; data: Uint8Array | ArrayBuffer | Blob };
text?: string;
replyToMessageId?: string;
}): Promise<AgentAttachment>Encrypts and uploads a file, then sends it. sendMedia accepts the same options plus width,
height and durationMs. See Files and media.
uploadFile(file)
uploadFile(file: { name: string; mime?: string; data: Uint8Array | ArrayBuffer | Blob }): Promise<AgentAttachment>Encrypts and uploads a file without sending a message — to attach several files to one
sendMessage.
downloadAttachment(attachment)
downloadAttachment(attachment: AgentAttachment): Promise<Uint8Array>Downloads a file received in a message and decrypts it locally with the key carried by the end-to-end encrypted message. Works for the conversations the agent is a member of. See Files and media.
Widgets
Every widget method takes conversationId, to, title, and optionally id, body and
expiresAt. Each returns the widget ID. See Interactive widgets.
| Method | Specific options |
|---|---|
sendConfirmWidget | danger, labels: { yes, no }, responseMode |
sendChoiceWidget | options: [{ id, label, danger? }], multi, responseMode |
sendPermissionWidget | scopes: ("once" | "session")[] |
sendFormWidget | fields: [{ name, label, type?, required?, placeholder?, min?, max? }], submitLabel |
sendDateTimeWidget | mode: "date" | "time" | "datetime", min, max |
sendFilePickerWidget | multiple, accept, maxFiles |
sendProgressWidget | value, max, cancellable |
sendWidgetUpdate | ref, spec, expiresAt — updates a widget already sent |
responseMode is "individual" or "collective" — see collective votes.
Types
AgentMessage
| Field | Type | Description |
|---|---|---|
id | string | Message ID. |
conversationId | string | Conversation ID. |
from | string | Sender ID. |
fromDeviceId | string? | Sender's device. |
text | string | Message text. |
replyToMessageId | string? | The message this one replies to. |
attachments | AgentAttachment[] | Attached files. |
widgetResponse | AgentWidgetResponse? | Answer to a widget. |
widgetUpdate | AgentWidgetUpdate? | Update to a widget. |
encrypted | boolean | Whether the message was end-to-end encrypted. |
AgentWidgetResponse
| Field | Type | Description |
|---|---|---|
ref | string | ID of the widget being answered. |
value | unknown | The answer — see each widget. |
cancelled | boolean | The user dismissed the widget. |
id | string | ID of the answer itself. |
AgentAttachment
| Field | Type | Description |
|---|---|---|
id | string | Attachment ID. |
name | string | File name. |
mime | string | MIME type. |
size | number | Size in bytes (before encryption). |
blobId | string | ID of the encrypted upload. |
width, height, durationMs | number? | Media hints. |
keyB64, ivB64 | string? | Per-file decryption key — keep private. |
Agent Connect
Server-side helpers for Agent Connect. All accept an optional
baseUrl (default https://api.pacerelle.com).
| Function | Returns |
|---|---|
beginAgentConnect({ connectKey, clientId, redirectUri, agentName, agentDescription?, state? }) | { authorizationUrl, state, codeVerifier, requestId, expiresAt, expiresIn } |
exchangeAgentConnectCode({ code, codeVerifier, clientId, redirectUri }) | { installationToken, agentId, ownerId, conversationId, scope, tokenType } |
requestAgentRuntimeToken({ installationToken }) | { agentToken, agentId, ownerId, conversationId, expiresIn } |