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

orqo-node-sdk

v1.2.0

Published

Orqo Gateway — TypeScript SDK for plug-and-play WhatsApp integration

Readme


✨ Features

| Feature | Description | |---------|-------------| | 🚀 Plug-and-Play | Provision → Connect → Send in 5 lines of code | | 🔒 Type-Safe | Full TypeScript coverage with strict mode — every method, every event | | 📦 Zero Dependencies | Only globalThis.fetch — works in Node.js 18+, Bun, Deno, and Edge | | 🔁 Retry & Resilience | Exponential backoff with configurable retry on 429/5xx | | 🪝 Webhook Handler | HMAC-verified, typed event dispatch for Express/Hono/Fastify/Node | | 🤖 Agent Management | Full CRUD for AI agents with Mastra engine support | | 🔌 API Bridge | Connect any OpenAPI spec and the agent gains tools automatically | | ⏰ Cron Jobs | Schedule recurring actions per instance | | 🤝 Handoff | Bot ↔ Human session transfer with metadata | | 🧠 Mastra Engine | Native or Mastra-powered agents with working memory, sub-agents, and evals | | 📡 Event Emitter | Type-safe OrqoEventEmitter with on/once/off for all webhook events | | ⚡ DX Helpers | askAgent(), collectStream(), quickStart(), toJid() utilities |


📦 Installation

npm install orqo-node-sdk

Requirements: Node.js 18+ (or any runtime with globalThis.fetch)


🚀 Quick Start

1. Provision an Instance

import { OrqoClient } from 'orqo-node-sdk';

const orqo = new OrqoClient({
  host: 'https://gateway.orqo.ai',
  adminToken: process.env.ORQO_ADMIN_TOKEN!,
});

const { instance, result } = await orqo.provision({
  name: 'My Support Bot',
  webhookUrl: 'https://my-app.com/webhooks/orqo',
  webhookSecret: process.env.WEBHOOK_SECRET,
});

console.log(`✅ Instance ${result.instanceId} created`);

2. Connect WhatsApp

// Wait for QR scan with live feedback
await instance.waitForConnection({
  onQr: (qr) => console.log('📱 Scan this QR:', qr),
  timeoutMs: 120_000,
});

console.log('🟢 WhatsApp connected!');

3. Send a Message

await instance.sendMessage({
  to: '[email protected]',
  text: 'Hello from Orqo! 🚀',
});

4. Receive Events

import { createWebhookHandler } from 'orqo-node-sdk';

app.post('/webhooks/orqo', createWebhookHandler({
  secret: process.env.WEBHOOK_SECRET,
  onMessageReceived: async (event) => {
    console.log(`💬 ${event.from}: ${event.text}`);
  },
  onConnectionChanged: (event) => {
    console.log(`📡 ${event.state}`);
  },
}));

5. Advanced: Skills, MCP, and OpenAPI APIs

You can extend agents dynamically by connecting external APIs and installing remote agent skills (via .skill or .zip files).

// 1. Provision with external MCP servers
const { instance } = await orqo.provision({
  name: 'Advanced Bot',
  config: {
    mcpServers: {
      "salesforce-mcp": {
        url: "https://my-salesforce-mcp.server.com/sse",
        env: { "SF_TOKEN": process.env.SF_TOKEN }
      }
    }
  }
});

// 2. Install a pre-packaged Agent Skill (prompts, logic, and MCP tools)
await instance.installSkill({ 
  remoteUrl: 'https://github.com/my-org/support-skill/archive/refs/tags/v1.zip' 
});

// 3. Import any standard REST API as tools using an OpenAPI/Swagger document
await instance.connectApi({
  name: "ecommerce-backend",
  schemaUrl: "https://api.my-store.com/swagger.json",
  headers: { "Authorization": "Bearer token123" }
});

console.log("🔥 Agent successfully supercharged with MCP, Skills, and REST APIs!");

📖 API Reference

OrqoClient — Admin Operations

Requires adminToken. Used for instance lifecycle management.

const orqo = new OrqoClient({ host, adminToken });

| Method | Returns | Description | |--------|---------|-------------| | provision(options) | { instance, result } | Create instance + boot WhatsApp | | listInstances() | InstanceStatus[] | List all instances | | getInstance(id, token) | OrqoInstance | Get handle for existing instance | | createInstance(options) | Record | Create instance (non-provision) | | deleteInstance(id) | void | Delete an instance | | startInstance(id) | void | Start an instance container | | stopInstance(id) | void | Stop an instance container | | createInstanceBackup(id)| { backupUrl, size }| Create an instance DB backup | | listAdminAgents(id) | Agent[] | List agents globally via Admin | | patchAdminAgent(id, agentId)| Agent | Patch agent via Admin | | deleteAdminAgent(id, agentId)| void | Delete agent via Admin | | reseedAdminAgents(id)| void | Reseed/Reset all agents knowledge | | getGlobalStats() | GlobalStats | Retrieve platform global metrics | | getAuditLogs(opts?) | AuditLogEntry[]| Retrieve global audit logs | | getInstanceAuditLogs(id, opts?) | AuditLogEntry[] | Per-instance audit logs | | cleanupAuditLogs(opts?) | { deleted } | Delete old audit entries |


OrqoInstance — Instance Operations

Scoped to a single instance. All methods auto-retry on 429/5xx.

WhatsApp

| Method | Returns | Description | |--------|---------|-------------| | getWhatsAppStatus() | WhatsAppStatus | Connection state + QR code | | connectWhatsApp() | InstanceStatus | Start WhatsApp socket | | disconnectWhatsApp() | void | Disconnect WhatsApp | | reconnectWhatsApp() | InstanceStatus | Force reconnect (stale connections) | | pairByPhone(phone) | { code } | Phone-number pairing code | | waitForConnection(opts?) | WhatsAppStatus | Poll until connected (with QR callback) |

Messaging

| Method | Returns | Description | |--------|---------|-------------| | send(phone, text, opts?) | SendMessageResult | Send a text message (JID auto-formatted) | | sendMessage({ to, text }) | SendMessageResult | Send a text message (RAW JID required) | | getMessages(opts?) | Record[] | Retrieve messages (with sessionKey filter) | | listSessions(opts?) | PaginatedResult<SessionConversation> | Paginated session list with search/channel filter | | getSessions(opts?) | SessionInfo[] | (deprecated) Simple session list |

Agents

| Method | Returns | Description | |--------|---------|-------------| | streamAgent(id, opts) | AsyncGenerator | Stream agent response (Server-Sent Events) | | createAgent(config) | Agent | Create an AI agent | | listAgents() | Agent[] | List all agents | | getAgent(id) | Agent | Get agent by ID | | updateAgent(id, updates) | Agent | Patch agent config | | deleteAgent(id) | void | Remove an agent |

Skills Management

| Method | Returns | Description | |--------|---------|-------------| | listAvailableSkills() | Skill[] | List all bundled skills available to install | | installSkill(name) | InstallResult | Install a bundled skill by name directly | | installSkill({ remoteUrl }) | InstallResult | Download & install a remote .skill or .zip |

Webhooks

| Method | Returns | Description | |--------|---------|-------------| | addWebhook({ url, event, secret? }) | Webhook | Register a webhook | | listWebhooks() | Webhook[] | List registered webhooks | | removeWebhook(id) | void | Unregister a webhook |

Guardrails

| Method | Returns | Description | |--------|---------|-------------| | setGuardrails(config) | GuardrailConfig | Set AI response rules | | getGuardrails() | GuardrailConfig | Get current guardrail config |

Session Handoff

| Method | Returns | Description | |--------|---------|-------------| | handoffToHuman(options) | HandoffResult | Transfer session to human agent | | resumeBot(sessionId) | HandoffResult | Return session to bot control |

Cron Jobs

| Method | Returns | Description | |--------|---------|-------------| | listCronJobs() | Record[] | List scheduled jobs | | createCronJob(config) | Record | Schedule a recurring job | | deleteCronJob(id) | void | Remove a scheduled job | | runCronJob(id) | Record | Trigger a job manually |

API Bridge

| Method | Returns | Description | |--------|---------|-------------| | connectApi(options) | { bridge, tools } | Connect an OpenAPI spec | | listApiBridges() | Array | List connected bridges | | removeApiBridge(id) | { success } | Disconnect a bridge | | refreshApiBridge(id) | { bridge, tools } | Re-fetch spec & update tools |

Monitoring

| Method | Returns | Description | |--------|---------|-------------| | getStatus() | InstanceStatus | Instance health & metadata | | getStats() | Record | Messages, sessions, uptime |


🪝 Webhook Handler

The createWebhookHandler() function provides a framework-agnostic webhook receiver with HMAC signature verification and typed event dispatch.

Express

import express from 'express';
import { createWebhookHandler } from 'orqo-node-sdk';

const app = express();
app.use(express.json());

app.post('/webhooks/orqo', createWebhookHandler({
  secret: process.env.WEBHOOK_SECRET,
  onConnectionChanged: (e) => {
    console.log(`${e.instanceId}: ${e.state}`);
  },
  onMessageReceived: async (e) => {
    console.log(`From ${e.from}: ${e.text}`);
    // Process message...
  },
  onMessageProcessed: (e) => {
    console.log(`AI processed: ${e.messageId}`);
  },
  onHandoff: (e) => {
    console.log(`Handoff: session ${e.sessionId}`);
  },
  onEvent: (e) => {
    // Catch-all for any event type
  },
  onVerificationFailed: (err) => {
    console.error('⚠️ Invalid signature:', err.message);
  },
}));

Hono

import { Hono } from 'hono';
import { createWebhookHandler } from 'orqo-node-sdk';

const app = new Hono();

app.post('/webhooks/orqo', async (c) => {
  const handler = createWebhookHandler({
    secret: c.env.WEBHOOK_SECRET,
    onMessageReceived: async (e) => {
      console.log(`${e.from}: ${e.text}`);
    },
  });
  await handler(
    { body: await c.req.json(), headers: c.req.raw.headers },
    { status: (s) => ({ json: (b) => c.json(b, s) }) },
  );
  return c.body(null, 200);
});

Event Types

| Event | Interface | Trigger | |-------|-----------|---------| | connection:changed | ConnectionChangedEvent | WhatsApp connects/disconnects | | message:received | MessageReceivedEvent | New incoming message | | message:processed | MessageProcessedEvent | AI finishes processing | | session:handoff | HandoffEvent | Session transferred to human | | agent:step_finish | StepFinishEvent | Mastra agent step completes |

Security

  • HMAC-SHA256 signature verification (X-Webhook-Signature header)
  • Dual runtime: Web Crypto API (browser/edge) + Node.js crypto fallback
  • Timing-safe string comparison to prevent timing attacks

🔌 API Bridge

Connect any external REST API via its OpenAPI spec. The AI agent automatically gains typed tools from the spec endpoints.

// Connect your CRM API — agent instantly gets tools like
// "crm_getContact", "crm_createLead", "crm_updateDeal"
await instance.connectApi({
  name: 'salesforce',
  specUrl: 'https://api.salesforce.com/openapi.json',
  auth: { type: 'bearer', token: process.env.SF_TOKEN },
  description: 'CRM for sales pipeline management',
});

// Connect a payments API
await instance.connectApi({
  name: 'stripe',
  specUrl: 'https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json',
  auth: { type: 'bearer', token: process.env.STRIPE_KEY },
});

// List what's connected
const bridges = await instance.listApiBridges();
console.log(bridges.map(b => `${b.name}: ${b.tools.length} tools`));

Auth Types

| Type | Fields | Example | |------|--------|---------| | bearer | token | { type: 'bearer', token: 'sk-...' } | | apiKey | token, headerName | { type: 'apiKey', token: 'key', headerName: 'X-API-Key' } | | basic | username, password | { type: 'basic', username: 'u', password: 'p' } | | custom | headers | { type: 'custom', headers: { 'X-Custom': 'val' } } |

Security

The API Bridge includes built-in SSRF prevention:

  • Blocks private/loopback/metadata IP addresses
  • Validates URL protocols (http/https only)
  • Limits spec size (2MB), operations (100), bridges per instance (10)
  • Blocks redirect-based attacks

🛡️ Resilience

All HTTP methods include automatic retry with exponential backoff:

const orqo = new OrqoClient({
  host: 'https://gateway.orqo.ai',
  adminToken: 'token',
  retry: {
    maxAttempts: 5,        // default: 3
    backoffMs: 500,        // default: 1000
    multiplier: 2,         // default: 2
    retryOn: [429, 503],   // default: [429, 500, 502, 503, 504]
  },
});

The retry config cascades from OrqoClientOrqoInstance, so all instance methods inherit the same resilience settings.

Backoff Timeline (defaults)

Attempt 1 → immediate
Attempt 2 → wait 1000ms
Attempt 3 → wait 2000ms
Attempt 4 → wait 4000ms  (if maxAttempts > 3)

🤝 Complete Workflow Example

import { OrqoClient, createWebhookHandler } from 'orqo-node-sdk';
import express from 'express';

// ── 1. Setup ─────────────────────────────────────────────
const orqo = new OrqoClient({
  host: process.env.ORQO_HOST!,
  adminToken: process.env.ORQO_ADMIN_TOKEN!,
});

// ── 2. Provision ─────────────────────────────────────────
const { instance } = await orqo.provision({
  name: 'Customer Support',
  webhookUrl: 'https://my-app.com/webhooks/orqo',
  webhookSecret: process.env.WEBHOOK_SECRET,
});

// ── 3. Configure Agent ───────────────────────────────────
await instance.createAgent({
  name: 'Support Agent',
  type: 'chat',
  systemPrompt: `You are a helpful customer support agent.
    Be concise and professional. If you cannot resolve
    the issue, hand off to a human agent.`,
  tools: ['knowledge-base', 'ticket-system'],
});

// ── 4. Set Guardrails ────────────────────────────────────
await instance.setGuardrails({
  blockedTopics: ['competitor-pricing', 'internal-processes'],
  maxResponseLength: 500,
  filterPII: true,
});

// ── 5. Connect External APIs ─────────────────────────────
await instance.connectApi({
  name: 'zendesk',
  specUrl: 'https://api.zendesk.com/openapi.json',
  auth: { type: 'bearer', token: process.env.ZENDESK_TOKEN },
});

// ── 6. Connect WhatsApp ──────────────────────────────────
await instance.waitForConnection({
  onQr: (qr) => sendQrToAdmin(qr),
});

// ── 7. Receive Events ────────────────────────────────────
const app = express();
app.use(express.json());

app.post('/webhooks/orqo', createWebhookHandler({
  secret: process.env.WEBHOOK_SECRET,
  onMessageReceived: async (e) => {
    console.log(`💬 ${e.pushName}: ${e.text}`);
  },
  onHandoff: async (e) => {
    await notifyHumanAgent(e.sessionId, e.reason);
  },
}));

// ── 8. Schedule Reminders ────────────────────────────────
await instance.createCronJob({
  schedule: '0 9 * * 1',  // Every Monday at 9am
  action: 'send-weekly-summary',
  payload: { channel: 'admin' },
});

app.listen(3000, () => console.log('🚀 Running on :3000'));

🏗 Architecture

┌──────────────────────────────────────────────────────────────┐
│                      orqo-node-sdk                           │
├──────────────┬─────────────────┬─────────────────────────────┤
│  OrqoClient  │  OrqoInstance   │  createWebhookHandler()     │
│  (Admin)     │  (Per-instance) │  (Event receiver)           │
│              │                 │                             │
│  provision() │  30 methods     │  HMAC verification          │
│  listInst()  │  WhatsApp       │  Typed event dispatch       │
│  deleteInst()│  Agents         │  Express/Hono/Fastify       │
│  getInst()   │  Webhooks       │  Web Crypto + Node.js       │
│              │  Guardrails     │                             │
│              │  Handoff        │                             │
│              │  API Bridge     │                             │
│              │  Cron Jobs      │                             │
│              │  Stats/Messages │                             │
├──────────────┴─────────────────┴─────────────────────────────┤
│                   Retry / Resilience Layer                    │
│          Exponential backoff • Configurable • Cascading      │
├──────────────────────────────────────────────────────────────┤
│                   globalThis.fetch (zero deps)               │
│          Node.js 18+ • Bun • Deno • Cloudflare Workers       │
└──────────────────────────────────────────────────────────────┘
         │                    │
         ▼                    ▼
  ┌──────────────┐   ┌──────────────────┐
  │ Orqo Gateway │   │ Your HTTP Server │
  │  REST API    │   │  Webhook Events  │
  └──────────────┘   └──────────────────┘

🧠 Mastra Engine

Create agents powered by Mastra with working memory, sub-agents, and structured output:

import { Engine } from 'orqo-node-sdk';

const agent = await instance
    .agent('Restaurant Bot')
    .engine(Engine.MASTRA)
    .mastraModel('openai/gpt-4o')
    .prompt('You manage orders for a restaurant.')
    .tools('order_lookup', 'refund_tool')
    .skills('investigador-br')
    .subAgents('billing-specialist')
    .workingMemory({ scope: 'contact' })
    .jsonOutput({ type: 'object', properties: { action: { type: 'string' } } })
    .maxToolRounds(5)
    .identity('Ana', '👩‍💼')
    .create();

📡 Event Emitter

Type-safe event emitter for webhook events with on/once/off:

import { OrqoEventEmitter, createWebhookHandler } from 'orqo-node-sdk';

const emitter = new OrqoEventEmitter();

emitter
    .on('message:received', (e) => console.log(`From ${e.from}: ${e.text}`))
    .on('agent:step_finish', (e) => console.log(`Step: ${e.agentId}`))
    .on('*', (e) => metrics.track(e.event));

// Wire into your webhook handler
app.post('/webhooks', createWebhookHandler({
    secret: process.env.WEBHOOK_SECRET,
    onEvent: (e) => emitter.emit(e),
}));

⚡ DX Helpers

import { askAgent, collectStream, quickStart, toJid, quickSend } from 'orqo-node-sdk';

// One-shot agent question
const reply = await askAgent(instance, 'agent-1', 'What time do you open?', 'session-key');

// Collect full stream into text + tool calls
const { text, toolCalls, usage } = await collectStream(
    instance.streamAgent('agent-1', { text: 'Hello', sessionKey: 'sess-1' })
);

// Full setup in one call: provision → connect → wait for QR
const instance = await quickStart(orqo, 'My Bot', {
    provider: LLMProvider.OPENAI, model: 'gpt-4o-mini', apiKey: 'sk-...',
});

// Format phone to JID
const jid = toJid('+55 11 99988-7766');  // '[email protected]'

📋 Type Exports

All types are exported from the main entry point:

import type {
  // Config
  OrqoClientConfig, OrqoInstanceConfig, RetryConfig,

  // Provisioning
  ProvisionOptions, ProvisionResult,

  // WhatsApp
  WhatsAppStatus, SendMessageOptions, SendMessageResult,

  // Instance
  InstanceStatus, InstanceStats, InstanceLimits,

  // Agents
  AgentConfig, Agent, AgentStreamOptions, AgentStreamEvent,

  // Webhooks
  WebhookConfig, Webhook, WebhookHandlerOptions,

  // Events
  WebhookEvent, ConnectionChangedEvent, MessageReceivedEvent,
  MessageProcessedEvent, HandoffEvent, StepFinishEvent, OrqoWebhookEvent,

  // v1.0 Types
  PaginatedResult, PromptSection, SessionConversation,
  DetailedStats, GlobalStats, AuditLogEntry,
} from 'orqo-node-sdk';

// Constants & classes
import {
  OrqoClient, OrqoInstance, OrqoEventEmitter,
  AgentBuilder, ProvisionBuilder,
  Events, LLMProvider, AgentType, Engine,
  askAgent, collectStream, quickStart, toJid, quickSend,
} from 'orqo-node-sdk';

🔧 Runtime Compatibility

| Runtime | Version | Status | |---------|---------|--------| | Node.js | 18+ | ✅ Full support | | Bun | 1.0+ | ✅ Full support | | Deno | 1.28+ | ✅ Full support | | Cloudflare Workers | — | ✅ Full support | | Vercel Edge | — | ✅ Full support | | Browser | — | ⚠️ CORS-dependent |


🔄 Migration Guide (v0.x → v1.0)

| Change | v0.x | v1.0 | |--------|------|------| | Streaming | AgentStreamOptions.message | AgentStreamOptions.text | | Sessions | getSessions()SessionInfo[] | listSessions()PaginatedResult<SessionConversation> | | Builder | engine() accepted AgentTypeValue | engine() accepts EngineType | | Stream events | No delta type | AgentStreamEvent.type includes 'delta' | | Package version | 0.3.0 | 1.0.0 |

[!NOTE] getSessions() is still available but deprecated. Migrate to listSessions() for full pagination and filtering.


📄 License

MIT — Use it however you want.