fireflies-reference-architecture
SKILL.md
Fireflies.ai Reference Architecture
Overview
Production architecture for meeting intelligence with Fireflies.ai. Covers transcript processing pipelines, CRM integration, action item extraction, and meeting analytics dashboards using the GraphQL API.
Prerequisites
- Fireflies.ai API key with GraphQL access
- GraphQL client (
graphql-requestorurql) - CRM system for action item sync (optional)
- Database for transcript storage
Architecture Diagram
┌──────────────────────────────────────────────────────┐
│ Meeting Sources │
│ Zoom │ Google Meet │ Teams │ Dialpad │ Phone │
└──────────┬───────────────────────────────┬───────────┘
│ │
▼ ▼
┌──────────────────────┐ ┌─────────────────────────┐
│ Fireflies.ai Bot │ │ Upload API │
│ (auto-join meetings)│ │ (manual recordings) │
└──────────┬───────────┘ └──────────┬──────────────┘
│ │
▼ ▼
┌──────────────────────────────────────────────────────┐
│ Fireflies Processing │
│ Transcription │ Speaker ID │ AI Summary │ Actions │
└──────────────────────────┬───────────────────────────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
┌──────────────┐ ┌────────┐ ┌──────────────┐
│ Transcript │ │ Action │ │ Webhook │
│ Storage │ │ Items │ │ Events │
│ (DB/Search) │ │ (CRM) │ │ (Real-time) │
└──────────────┘ └────────┘ └──────────────┘
Instructions
Step 1: GraphQL Client Setup
import { GraphQLClient } from 'graphql-request';
const fireflies = new GraphQLClient('https://api.fireflies.ai/graphql', {
headers: { Authorization: `Bearer ${process.env.FIREFLIES_API_KEY}` },
});
// Fetch recent transcripts
const GET_TRANSCRIPTS = `
query GetTranscripts($limit: Int) {
transcripts(limit: $limit) {
id title date duration
organizer_email participants
summary { overview action_items keywords }
}
}
`;
async function getRecentMeetings(limit = 20) {
const data = await fireflies.request(GET_TRANSCRIPTS, { limit });
return data.transcripts;
}
Step 2: Transcript Processing Pipeline
const GET_FULL_TRANSCRIPT = `
query GetTranscript($id: String!) {
transcript(id: $id) {
id title
sentences {
speaker_name text
start_time end_time
}
summary { overview action_items keywords }
meeting_attendees { displayName email }
}
}
`;
interface ProcessedMeeting {
id: string;
title: string;
attendees: string[];
actionItems: string[];
keyTopics: string[];
speakerBreakdown: Record<string, number>;
}
async function processMeeting(id: string): Promise<ProcessedMeeting> {
const { transcript } = await fireflies.request(GET_FULL_TRANSCRIPT, { id });
const speakerTime: Record<string, number> = {};
for (const s of transcript.sentences) {
const duration = s.end_time - s.start_time;
speakerTime[s.speaker_name] = (speakerTime[s.speaker_name] || 0) + duration;
}
return {
id: transcript.id,
title: transcript.title,
attendees: transcript.meeting_attendees.map((a: any) => a.email),
actionItems: transcript.summary.action_items || [],
keyTopics: transcript.summary.keywords || [],
speakerBreakdown: speakerTime,
};
}
Step 3: Webhook Integration
import express from 'express';
const app = express();
app.post('/webhooks/fireflies', express.json(), async (req, res) => {
const { event_type, meeting_id, transcript_id } = req.body;
if (event_type === 'Transcription completed') {
const meeting = await processMeeting(transcript_id);
// Sync action items to CRM
for (const item of meeting.actionItems) {
await createCRMTask(item, meeting.attendees);
}
}
res.json({ received: true });
});
Step 4: Meeting Analytics Aggregation
async function weeklyMeetingReport() {
const meetings = await getRecentMeetings(50);
const oneWeekAgo = Date.now() - 7 * 86400000; # 86400000 = configured value
const recent = meetings.filter(
(m: any) => new Date(m.date).getTime() > oneWeekAgo
);
return {
totalMeetings: recent.length,
totalHours: recent.reduce((s: number, m: any) => s + m.duration / 3600, 0).toFixed(1), # 3600: timeout: 1 hour
topAttendees: countAttendees(recent).slice(0, 5),
actionItemCount: recent.reduce((s: number, m: any) =>
s + (m.summary?.action_items?.length || 0), 0),
};
}
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Empty transcript | Meeting too short | Check minimum duration before processing |
| Missing speakers | Speaker diarization failed | Fall back to participant list |
| GraphQL rate limit | Too many queries | Batch requests, cache transcripts |
| Webhook not firing | URL not configured | Verify in Fireflies dashboard settings |
Examples
Quick Meeting Search
async function searchMeetings(keyword: string) {
const meetings = await getRecentMeetings(100);
return meetings.filter((m: any) =>
m.title?.toLowerCase().includes(keyword.toLowerCase()) ||
m.summary?.keywords?.some((k: string) => k.toLowerCase().includes(keyword))
);
}
Resources
Output
- Configuration files or code changes applied to the project
- Validation report confirming correct implementation
- Summary of changes made and their rationale
Weekly Installs
14
Repository
jeremylongshore…s-skillsGitHub Stars
1.6K
First Seen
Feb 18, 2026
Security Audits
Installed on
codex14
mcpjam13
claude-code13
junie13
windsurf13
zencoder13