Use when building features that join, record, or transcribe Zoom/Meet/Teams/Webex calls — meeting bots, call notetakers, sales-call summarizers, interview transcribers. Covers ctx.ai.meetings.start/get/stop/list, webhook setup, and credit metering.
npx skills add https://github.com/butterbase-ai/butterbase-skills --skill meetings
Guide for building features that spawn meeting bots via ctx.ai.meetings. Covers the four SDK methods, webhook handling, idempotency, and cost-aware design.
Reach for this skill when your feature involves any of:
bot.done, then run an LLM over the transcript to populate a CRM record.If you need only audio/video file upload without a live meeting join, use manage_storage instead.
| Method | What it does | One-line example |
|--------|-------------|-----------------|
| bb.ai.meetings.start(opts) | Spawns a bot and returns immediately with status: "joining" | const { data: bot } = await bb.ai.meetings.start({ meetingUrl, transcript: true }) |
| bb.ai.meetings.get(id) | Fetches current status + artifact URLs | const { data } = await bb.ai.meetings.get(bot.id) |
| bb.ai.meetings.stop(id) | Removes the bot from the call early | await bb.ai.meetings.stop(bot.id) |
| bb.ai.meetings.list(opts) | Lists bots with optional status, limit, cursor filters | await bb.ai.meetings.list({ status: 'done', limit: 50 }) |
All methods return { data, error } — always check error before using data.
manage_ai with action: "configure_meetings_webhook", passing forward_url pointing at a deployed Butterbase function or your own endpoint.bb.ai.meetings.start(...). Status begins as joining.joining → waiting_room → in_call → recording. The bot.in_call_recording event fires.ended, then done once artifacts are processed.bot.done — your handler receives the event. The bot's recordingUrl and transcriptUrl are now populated.bb.ai.meetings.get(id).Deploy this as a Butterbase function with trigger: { type: "http", config: { method: "POST", auth: "none" } }.
export async function handler(req: Request, ctx: any): Promise<Response> {
const event = req.headers.get('x-bb-event');
const body = await req.text();
const payload = JSON.parse(body);
const botId: string = payload.data?.bot_id ?? payload.data?.id;
// Idempotency: skip if we already processed this bot + event combo.
const claimed = await ctx.idempotency.claim(`meeting:${botId}:${event}`);
if (!claimed) {
return new Response('duplicate', { status: 200 });
}
switch (event) {
case 'bot.done': {
// Artifacts are ready — store a reference or kick off extraction.
await ctx.db.query(
`UPDATE meeting_jobs SET status = 'done', bot_id = $1 WHERE external_ref = $2`,
[botId, payload.data?.metadata?.jobRef ?? botId]
);
break;
}
case 'transcript.done': {
// Transcript artifact URL is now available. Kick off downstream processing.
await ctx.db.query(
`INSERT INTO transcript_queue (bot_id, created_at) VALUES ($1, now())`,
[botId]
);
break;
}
case 'bot.fatal': {
await ctx.db.query(
`UPDATE meeting_jobs SET status = 'fatal' WHERE bot_id = $1`,
[botId]
);
break;
}
default:
// Other events (bot.in_call_recording, recording.done, transcript.failed) — handle as needed.
break;
}
return new Response('ok', { status: 200 });
}
Key points:
ctx.idempotency.claim(key) — the meetings service may retry for up to 24 hours.x-bb-key-id matches the first 16 characters of your current webhook secret to detect stale post-rotation events.200 even for events you don't handle — a non-2xx response triggers a retry.Before dispatching a bot in a user-pays context, call estimateCost and surface the projected charge:
const { data: estimate } = await bb.ai.meetings.estimateCost({
durationMinutes: 60,
transcript: true,
});
// estimate.usd — show this to the user or check against a quota
Rates (v1):
| Dimension | Rate |
|-----------|------|
| Recording (mp4 or audio_only) | $0.50/hr + markup, prorated per second |
| Transcription | $0.15/hr + markup, prorated per second |
Both charges are applied against the app's AI credit balance once the bot reaches done.
For user-pays apps, hold a projected credit reservation at bot-start time and display a live cost counter using the bot's current duration (polled from bb.ai.meetings.get).
The underlying meetings infrastructure may change providers without notice. Do not depend on undocumented fields in the event payload or on provider-specific bot behavior.
ctx.ai.meetings must be called from a serverless function or server-side code, not directly from the browser. Use a Butterbase function as a backend proxy.Analyzes meeting transcripts and recordings to uncover behavioral patterns, communication insights, and actionable feedback. Identifies when you avoid conflict, use filler words, dominate conversations, or miss opportunities to listen. Perfect for professionals seeking to improve their communication and leadership skills.
Toolkit for creating animated GIFs optimized for Slack, with validators for size constraints and composable animation primitives. This skill applies when users request animated GIFs or emoji animations for Slack from descriptions like "make me a GIF for Slack of X doing Y".
Analyzes your recent Claude Code chat history to identify coding patterns, development gaps, and areas for improvement, curates relevant learning resources from HackerNews, and automatically sends a personalized growth report to your Slack DMs.
Knowledge and utilities for creating animated GIFs optimized for Slack. Provides constraints, validation tools, and animation concepts. Use when users request animated GIFs for Slack like "make me a GIF of X doing Y for Slack.
A skill that creates new Claude skills and automatically shares them on Slack using Rube for seamless team collaboration and skill discovery.
Automate Electron desktop apps (VS Code, Slack, Discord, Figma, Notion, Spotify, etc.) using agent-browser via Chrome DevTools Protocol. Use when the user needs to interact with an Electron app, automate a desktop app, connect to a running app, control a native app, or test an Electron application. Triggers include "automate Slack app", "control VS Code", "interact with Discord app", "test this Electron app", "connect to desktop app", or any task requiring automation of a native Electron application.
Prepare meeting materials with Notion context and Codex research; use when gathering context, drafting agendas/pre-reads, and tailoring materials to attendees.
Interactive daily standup/meeting update generator. Use when user says 'daily', 'standup', 'scrum update', 'status update', 'what did I do yesterday', 'prepare for meeting', 'morning update', or 'team sync'. Pulls activity from GitHub, Jira, and Claude Code session history. Conducts 4-question interview (yesterday, today, blockers, discussion topics) and generates formatted Markdown update.
Take butterbase-ai/meetings from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.