Skip to content

Quickstart - Humans + AI Agents

This guide walks you through setting up a complete beeps system with human responders and AI agents working in parallel. New to beeps? Read Core Concepts first to understand how the pieces fit together.

By the end of this guide, you’ll have:

  • A relay that receives alerts
  • A schedule with team members rotating on-call
  • Contact methods (email and SMS) for notifications
  • An AI agent integration for automated triage
  • Parallel routing: alerts go to both humans and AI simultaneously
  • A beeps account
  • An API key from your organization settings (looks like bk_xxxxxxxx)

Step 1: Install the SDK and Initialize the Client

Section titled “Step 1: Install the SDK and Initialize the Client”
Terminal window
npm install @beepsdev/sdk

Set your API key:

Terminal window
export BEEPS_API_KEY="bk_your_api_key_here"

Create a new file beeps.config.ts:

import { BeepsClient } from "@beepsdev/sdk";
const client = new BeepsClient({
apiKey: process.env.BEEPS_API_KEY,
});

Create a relay, which is the pipeline that receives alerts and routes them through rules.

const relay = await client.relay.create({
name: "production relay",
description: "routes critical production incidents",
externalKey: "production::relay",
});
console.log(`Created relay: ${relay.id}`);

You can also use an existing relay:

const relays = await client.relay.list();
const relay = relays[0];

Related: Managing Relays

Create a schedule to define who is on-call and when rotations happen.

const schedule = await client.schedule.create({
name: "Primary On-Call",
relayId: relay.id,
type: "weekly",
startDay: "monday",
startTime: "09:00", // UTC
externalKey: "primary::schedule",
});
console.log(`Created schedule: ${schedule.id}`);

Or use an existing schedule:

const schedules = await client.schedule.list();
const schedule = schedules[0];

Related: Managing Schedules

Add users to the on-call rotation:

await client.schedule.addMember(schedule.id, {
userId: "usr_alice",
});
await client.schedule.addMember(schedule.id, {
userId: "usr_bob",
});
console.log("Added team members to schedule");

Members rotate in the order they’re added.

Related: Schedule Members

Add contact methods to define how users receive notifications.

const onCall = await client.schedule.getOnCall(schedule.id);
console.log(`Current on-call: ${onCall.email}`);
await client.contactMethod.create({
userId: onCall.userId,
transport: "email",
value: "engineer@example.com",
});
await client.contactMethod.create({
userId: onCall.userId,
transport: "sms",
value: "+14155551234", // E.164 format
});
console.log("Added contact methods");

Related: Managing Contact Methods

Add an integration to store credentials for your AI agent. You’ll need an API key from your agent provider — get one from Devin API settings or Cursor dashboard.

const integration = await client.integration.create({
name: "Devin Agent",
provider: "devin",
apiKey: process.env.DEVIN_API_KEY,
metadata: {
environment: "production",
},
});
console.log(`Created integration: ${integration.id}`);

Related: Managing Integrations

Create rules that route alerts to responders. These rules run in parallel so AI agents and humans both get notified simultaneously.

await client.relay.rules.create(relay.id, {
name: "AI Agent Auto-Triage",
externalKey: "agents::devin",
ruleType: "agent",
group: "agents",
order: 1,
config: {
agentType: "devin",
integrationId: integration.id,
pollInterval: 30000,
maxPollAttempts: 120,
},
enabled: true,
});
console.log("Created AI agent rule");
await client.relay.rules.create(relay.id, {
name: "Notify On-Call Engineer",
externalKey: "humans::primary::schedule-notify",
ruleType: "schedule_notify",
group: "humans",
order: 1,
config: {
scheduleId: schedule.id,
},
enabled: true,
});
console.log("Created human notification rule");

Rules in different groups ("agents" vs "humans") run in parallel. Both the AI agent and human receive the alert simultaneously.

Related: Relay Rules

List all rules to confirm configuration:

const rules = await client.relay.rules.list(relay.id);
console.log("\nRelay Rules:");
rules.forEach((rule) => {
console.log(` [${rule.group}] ${rule.name}`);
console.log(` Type: ${rule.ruleType}`);
console.log(` Enabled: ${rule.enabled}`);
});

Here’s the complete beeps.config.ts combining all steps:

import { BeepsClient } from "@beepsdev/sdk";
async function configure() {
const client = new BeepsClient({
apiKey: process.env.BEEPS_API_KEY,
});
// 1. Create relay
const relay = await client.relay.create({
name: "production relay",
description: "routes critical production incidents",
externalKey: "production::relay",
});
console.log(`Relay: ${relay.name}`);
// 2. Create schedule
const schedule = await client.schedule.create({
name: "Primary On-Call",
relayId: relay.id,
type: "weekly",
startDay: "monday",
startTime: "09:00",
externalKey: "primary::schedule",
});
console.log(`Schedule: ${schedule.name}`);
// 3. Add team members
await client.schedule.addMember(schedule.id, { userId: "usr_alice" });
await client.schedule.addMember(schedule.id, { userId: "usr_bob" });
// 4. Add contact methods
const onCall = await client.schedule.getOnCall(schedule.id);
await client.contactMethod.create({
userId: onCall.userId,
transport: "email",
value: "engineer@example.com",
});
await client.contactMethod.create({
userId: onCall.userId,
transport: "sms",
value: "+14155551234",
});
// 5. Create AI integration
const integration = await client.integration.create({
name: "Devin Production Agent",
provider: "devin",
apiKey: process.env.DEVIN_API_KEY,
externalKey: "agents::devin::integration",
});
// 6. Create relay rules (parallel: agents + humans)
await client.relay.rules.create(relay.id, {
name: "AI Agent Auto-Triage",
externalKey: "agents::devin",
ruleType: "agent",
group: "agents",
order: 1,
config: {
agentType: "devin",
integrationId: integration.id,
},
enabled: true,
});
await client.relay.rules.create(relay.id, {
name: "Notify On-Call Engineer",
externalKey: "humans::schedule-notify",
ruleType: "schedule_notify",
group: "humans",
order: 1,
config: {
scheduleId: schedule.id,
},
enabled: true,
});
// 7. Verify
const rules = await client.relay.rules.list(relay.id);
console.log(`\nSetup complete! ${rules.length} rules configured`);
}
configure().catch(console.error);

Run it:

Terminal window
export BEEPS_API_KEY="bk_your_key_here"
export DEVIN_API_KEY="apk_your_devin_key_here"
npx tsx beeps.config.ts

Send a test alert to your relay’s webhook URL (found in your relay’s details):

Terminal window
curl -X POST https://hooks.beeps.dev/YOUR_WEBHOOK_ID \
-H "Content-Type: application/json" \
-d '{
"title": "Test Alert",
"message": "Testing the on-call system",
"severity": "high"
}'

You should see:

  • The AI agent (Devin) receives the alert and starts triaging
  • The on-call engineer receives an email/SMS notification
  • Both happen simultaneously!

Since beeps.config.ts uses externalKey everywhere, it’s idempotent and safe to re-run. Treat it like database migrations — check it into your repo and run it in CI on merge.

name: Deploy beeps config
on:
push:
branches: [main]
paths: [beeps.config.ts]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm install @beepsdev/sdk
- run: npx tsx beeps.config.ts
env:
BEEPS_API_KEY: ${{ secrets.BEEPS_API_KEY }}
DEVIN_API_KEY: ${{ secrets.DEVIN_API_KEY }}

Changes to your on-call config go through PR review like any other code change.

Alert Received
|
Relay: "production relay"
|
|-- [agents] AI Agent Auto-Triage --> Devin starts working
|
|-- [humans] Notify On-Call Engineer --> Email/SMS sent

Both rules run in parallel because they’re in different groups ("agents" and "humans").

To run AI first, then escalate to humans, use the same group:

await client.relay.rules.create(relay.id, {
name: "Try AI first",
ruleType: "agent",
group: "default",
order: 1,
config: { agentType: "devin", integrationId: integration.id },
});
await client.relay.rules.create(relay.id, {
name: "Escalate to humans",
ruleType: "schedule_notify",
group: "default",
order: 2,
config: { scheduleId: schedule.id },
});
await client.relay.rules.create(relay.id, {
name: "Escalate to backup",
ruleType: "schedule_notify",
group: "humans",
order: 2,
config: { scheduleId: backupSchedule.id },
});

If you encounter issues, see the Troubleshooting Guide for solutions: