Agent Skills: Fireflies Calls Skill

Use when user says "find calls about [topic]", "get transcript for [meeting]", or "show calls with [person]". Automatically searches and analyzes Fireflies.ai call recordings. Extracts transcripts, summaries, action items, and meeting insights.

UncategorizedID: tekliner/improvado-agentic-frameworks-and-skills/fireflies-calls

Install this agent skill to your local

pnpm dlx add-skill https://github.com/tekliner/improvado-agentic-frameworks-and-skills/tree/HEAD/skills/fireflies-calls

Skill Files

Browse the full folder contents for fireflies-calls.

Download Skill

Loading file tree…

skills/fireflies-calls/SKILL.md

Skill Metadata

Name
fireflies-calls
Description
Use when user says "find calls about [topic]", "get transcript for [meeting]", or "show calls with [person]". Automatically searches and analyzes Fireflies.ai call recordings. Extracts transcripts, summaries, action items, and meeting insights.

Fireflies Calls Skill

Search and analyze call recordings from Fireflies.ai with full transcript and AI-generated summaries.

When to Use This Skill

Use this skill when:

  • Find calls by keyword, title, or participant
  • Get call transcripts and summaries
  • Extract action items from meetings
  • Analyze conversations from specific dates
  • Review meeting notes and decisions

Quick Start Checklist

When user wants to find or analyze calls:

[ ] 1. Identify search criteria: keyword, participant, or date range
[ ] 2. Use FirefliesClient.search_meetings() with appropriate filters
[ ] 3. Review search results (duration now automatically accurate!)
[ ] 4. Get full details with get_meeting() if transcript needed
[ ] 5. Extract action items with get_action_items() if requested
[ ] 6. Format output with participant list and key insights

5-Second Decision Tree:

  • User mentions specific topic/keyword? → search_meetings(keyword="...")
  • User mentions person's name? → find_calls_with_person(person_name="...") (PREFERRED — checks transcript speakers, not just participants)
  • User asks about date/today? → search_meetings(date_from="...")

CRITICAL: Fireflies participants field is often EMPTY for Google Meet calls. Never rely solely on participant_email or participants list. Always use find_calls_with_person() when searching by person — it checks actual speaker names in transcripts.

Practical Workflow

BEFORE searching for calls:

  1. Determine search type (keyword vs participant vs date)
  2. Build search query:
    • Topic → client.search_meetings(keyword="ECM", date_from="2025-11-01")
    • Person → client.search_meetings(participant_email="contact@example.com")
    • Recent → client.search_meetings(date_from=today, limit=50)
  3. Get details if user needs transcript or action items
  4. Format output with duration, participants, summary

Example rapid application:

User: "Find my calls about token launch this week"

Agent thinks:
- Keyword search needed ("token launch")
- Recent timeframe (this week)
- Use: client.search_meetings(keyword="token launch", date_from="2025-11-04")
- Duration automatically accurate (no API bug workaround needed)

Authentication

API Key: Automatically loaded from .env file:

FIREFLIES_API_KEY="your-api-key-here"

API URL: https://api.fireflies.ai/graphql

IMPORTANT: API key must be set in .env file. Never hardcode it in scripts.

Core Operations

1. Search Calls (Auto Real Duration!)

✅ FIXED: Client now automatically calculates accurate duration from transcripts by default! Fireflies API bug (wrong duration ~30-80 sec) is automatically corrected.

Quick search by keyword:

from data_sources.fireflies.fireflies_client import FirefliesClient
from datetime import datetime, timedelta

client = FirefliesClient()

# Search by keyword - duration is automatically accurate!
meetings = client.search_meetings(
    keyword="ECM",
    date_from=(datetime.now() - timedelta(days=7)).strftime("%Y-%m-%d"),
    limit=20
    # calculate_real_duration=True by default ✅
)

print(f"Found {len(meetings)} calls:\n")

for i, meeting in enumerate(meetings, 1):
    title = meeting.get('title', 'Untitled')
    date_ms = meeting.get('date', 0)
    if date_ms:
        date_obj = datetime.fromtimestamp(date_ms / 1000)
        date_str = date_obj.strftime('%Y-%m-%d %H:%M')
    else:
        date_str = 'Unknown'

    # Duration now accurate (in seconds)
    duration_sec = meeting.get('duration', 0)
    duration_min = duration_sec / 60

    participants = meeting.get('participants', [])
    meeting_id = meeting.get('id')

    print(f"{i}. {title}")
    print(f"   Date: {date_str}")
    print(f"   Duration: {duration_min:.1f} min")
    print(f"   Participants: {', '.join(participants[:3])}")
    print(f"   ID: {meeting_id}")
    print()

Search by participant email:

# Find all calls with specific person
meetings = client.search_meetings(
    participant_email="contact@example.com",
    date_from="2025-11-01",
    limit=50
)

Combined search:

# Keyword + participant + date range
meetings = client.search_meetings(
    keyword="token launch",
    participant_email="rakhan@example.com",
    date_from="2025-11-01",
    date_to="2025-11-04",
    limit=20
)

1b. Find Calls by Person (Speaker Detection)

PREFERRED method when searching by person name. Checks transcript speakers, not just participants.

from data_sources.fireflies.fireflies_client import FirefliesClient
from datetime import datetime

client = FirefliesClient()
today = datetime.now().strftime('%Y-%m-%d')

# Find all calls where Nick Snopov spoke today
meetings = client.find_calls_with_person(
    person_name="Nick Snopov",  # case-insensitive, partial match OK
    date_from=today
)

for m in meetings:
    title = m.get('title', 'Untitled')
    speakers = m.get('speakers', [])
    duration_min = m.get('duration', 0) / 60
    match_src = m.get('match_source', '?')
    print(f"{title} | {duration_min:.1f} min | matched via: {match_src}")
    print(f"  Speakers: {speakers}")

Why this exists: Fireflies API leaves participants empty for ~60% of Google Meet calls. The search_meetings(participant_email=...) will miss these calls entirely. find_calls_with_person() scans actual speaker_name fields in transcripts — never misses.

2. Get Full Call Details with Transcript

Complete meeting analysis:

# Get meeting ID from search results
meeting_id = "01K8RH3QTPMF92ZR63K0TK516D"

# Get full details including transcript
meeting = client.get_meeting(meeting_id, include_transcript=True)

# Display formatted output
print("=" * 100)
print(f"📅 {meeting.get('title')}")
print(f"ID: {meeting_id}")

# Date
date_ms = meeting.get('date', 0)
if date_ms:
    date_obj = datetime.fromtimestamp(date_ms / 1000)
    print(f"Date: {date_obj.strftime('%A, %B %d, %Y at %H:%M')}")

# Duration
duration = meeting.get('duration', 0)
if duration:
    print(f"Duration: {duration / 60:.1f} minutes")

# Participants
participants = meeting.get('participants', [])
if participants:
    print(f"\n👥 Participants ({len(participants)}):")
    for p in participants:
        print(f"   - {p}")

# Summary
summary = meeting.get('summary', {})
if summary:
    print("\n📝 SUMMARY:")
    print("-" * 100)

    if summary.get('overview'):
        print(f"\nOverview:\n{summary['overview']}")

    if summary.get('keywords'):
        print(f"\nKeywords: {', '.join(summary['keywords'])}")

    if summary.get('action_items'):
        print(f"\n✅ Action Items:\n{summary['action_items']}")

# Transcript
sentences = meeting.get('sentences', [])
if sentences:
    print(f"\n💬 TRANSCRIPT ({len(sentences)} sentences):")
    print("-" * 100 + "\n")

    current_speaker = None
    for sentence in sentences[:20]:  # First 20 sentences
        speaker = sentence.get('speaker_name', 'Unknown')
        text = sentence.get('text', '')

        if speaker != current_speaker:
            print(f"\n{speaker}:")
            current_speaker = speaker

        print(f"  {text}")

3. Extract Action Items

Get only action items:

meeting_id = "01K8RH3QTPMF92ZR63K0TK516D"

actions = client.get_action_items(meeting_id)

if actions:
    print("✅ Action Items:")
    for i, action in enumerate(actions, 1):
        print(f"{i}. {action}")
else:
    print("No action items found")

Common Search Patterns

Pattern 1: Get Today's Calls

from datetime import datetime

# TODAY's calls - duration automatically accurate!
today = datetime.now().strftime('%Y-%m-%d')

meetings = client.search_meetings(
    date_from=today,
    limit=50
    # Real duration calculated automatically ✅
)

print(f"📅 Today's calls: {len(meetings)}\n")

total_duration = 0
for i, meeting in enumerate(meetings, 1):
    date_ms = meeting.get('date', 0)
    time_str = datetime.fromtimestamp(date_ms / 1000).strftime('%H:%M')

    duration_sec = meeting.get('duration', 0)
    duration_min = duration_sec / 60
    total_duration += duration_sec

    title = meeting.get('title', 'Untitled')
    participants = meeting.get('participants', [])

    print(f"{i}. [{time_str}] {title}")
    print(f"   Duration: {duration_min:.1f} min")
    print(f"   Participants: {len(participants)} people")
    print()

print(f"\n📊 Total: {total_duration/60:.1f} minutes ({total_duration/3600:.1f} hours)")

Pattern 2: Find Calls About Specific Topic

# Search by keywords
keywords = ["token launch", "ECM", "bio.xyz", "funding"]

for keyword in keywords:
    meetings = client.search_meetings(keyword=keyword, limit=10)
    print(f"\n🔍 '{keyword}': {len(meetings)} calls")

    for meeting in meetings[:3]:  # Top 3
        print(f"   - {meeting.get('title')} ({meeting.get('id')})")

Pattern 3: Participant Call History

# All calls with specific person
email = "contact@example.com"

meetings = client.search_meetings(
    participant_email=email,
    date_from="2025-01-01",
    limit=50
)

print(f"📊 Call history for {email}:")
print(f"Total calls: {len(meetings)}\n")

for meeting in meetings:
    date_ms = meeting.get('date', 0)
    if date_ms:
        date_str = datetime.fromtimestamp(date_ms / 1000).strftime('%Y-%m-%d')
    else:
        date_str = 'Unknown'

    print(f"   {date_str} - {meeting.get('title')}")

Pattern 4: Summary Only (No Transcript)

# Faster if you don't need full transcript
meeting = client.get_meeting(meeting_id, include_transcript=False)

summary = meeting.get('summary', {})
print("Quick Summary:")
print(f"Overview: {summary.get('overview', 'N/A')}")
print(f"Keywords: {', '.join(summary.get('keywords', []))}")

API Methods Reference

find_calls_with_person()

PREFERRED for person search. Checks transcript speakers, not just participants.

Parameters:

  • person_name (str): Name to search (case-insensitive, partial match). E.g. "Nick Snopov", "Nikita"
  • date_from (str): Start date (YYYY-MM-DD)
  • date_to (str): End date (YYYY-MM-DD)
  • limit (int): Max meetings to scan (default: 50)

Returns: List of meetings where the person was a speaker, with extra fields:

  • speakers - List of actual speaker names from transcript
  • match_source - "participants" or "transcript_speakers"

Why it exists: Fireflies leaves participants empty for ~60% of Google Meet calls. search_meetings(participant_email=...) will miss them. This method scans speaker_name in transcripts — never misses.

search_meetings()

Parameters:

  • keyword (str): Search in transcript content
  • title (str): Search in meeting title
  • participant_email (str): Filter by participant
  • organizer_email (str): Filter by organizer
  • host_email (str): Filter by host
  • date_from (str): Start date (YYYY-MM-DD or ISO)
  • date_to (str): End date (YYYY-MM-DD or ISO)
  • limit (int): Max results (default: 50, max: 50)
  • skip (int): Pagination offset (default: 0)
  • calculate_real_duration (bool): Calculate accurate duration from transcript (default: True ✅)
    • Set to False only for faster queries when duration not critical

⚠️ API BUG FIXED: Fireflies API returns wrong duration (~30-80 sec). Client now auto-corrects this by default!

Returns: List of meetings with:

  • id - Meeting ID
  • title - Meeting title
  • date - Unix timestamp (milliseconds)
  • duration - Duration in seconds (automatically accurate from transcript)
  • real_duration - Real duration from transcript (same as duration when auto-calculated)
  • participants - List of emails
  • organizer_email - Organizer email
  • audio_url - Audio recording URL
  • video_url - Video recording URL
  • summary - AI-generated summary object

get_meeting()

Parameters:

  • meeting_id (str): Fireflies meeting ID
  • include_transcript (bool): Include full transcript (default: True)

Returns: Complete meeting data including:

  • All fields from search_meetings()
  • sentences - Full transcript (if include_transcript=True)
    • text - Sentence text
    • speaker_name - Speaker name
    • start_time - Start time in seconds
    • end_time - End time in seconds

get_action_items()

Parameters:

  • meeting_id (str): Fireflies meeting ID

Returns: List of action items as strings

get_user_info()

Parameters: None

Returns: User information:

  • email - User email
  • name - User name
  • minutes_consumed - Minutes of calls processed

Example: Complete Call Analysis Workflow

from data_sources.fireflies.fireflies_client import FirefliesClient
from datetime import datetime, timedelta

client = FirefliesClient()

# Step 1: Search for calls
print("🔍 Searching for calls about 'ECM'...")
date_from = (datetime.now() - timedelta(days=7)).strftime("%Y-%m-%d")

meetings = client.search_meetings(
    keyword="ECM",
    date_from=date_from,
    limit=20
)

if not meetings:
    print("No calls found")
    exit()

print(f"Found {len(meetings)} calls\n")

# Step 2: Select relevant call
for i, meeting in enumerate(meetings, 1):
    title = meeting.get('title', 'Untitled')
    print(f"{i}. {title} (ID: {meeting.get('id')})")

# Step 3: Get full details for first call
selected_meeting_id = meetings[0].get('id')
print(f"\n📥 Analyzing: {meetings[0].get('title')}\n")

meeting = client.get_meeting(selected_meeting_id, include_transcript=True)

# Step 4: Extract key information
summary = meeting.get('summary', {})
sentences = meeting.get('sentences', [])

print("=" * 100)
print(f"📅 {meeting.get('title')}")
print(f"Date: {datetime.fromtimestamp(meeting.get('date', 0) / 1000).strftime('%Y-%m-%d %H:%M')}")
print(f"Duration: {meeting.get('duration', 0) / 60:.1f} minutes")
print(f"Participants: {', '.join(meeting.get('participants', []))}")

print("\n📝 SUMMARY:")
print(summary.get('overview', 'N/A'))

print("\n✅ ACTION ITEMS:")
print(summary.get('action_items', 'N/A'))

print(f"\n💬 TRANSCRIPT ({len(sentences)} sentences):")
current_speaker = None
for sentence in sentences[:15]:
    speaker = sentence.get('speaker_name')
    if speaker != current_speaker:
        print(f"\n{speaker}:")
        current_speaker = speaker
    print(f"  {sentence.get('text')}")

print("\n" + "=" * 100)

Command Line Usage

The FirefliesClient also provides CLI:

# Search calls
python data_sources/fireflies/fireflies_client.py search --keyword "ECM" --from 2025-11-01 --limit 10

# Get meeting details
python data_sources/fireflies/fireflies_client.py get 01K8RH3QTPMF92ZR63K0TK516D

# Get action items only
python data_sources/fireflies/fireflies_client.py actions 01K8RH3QTPMF92ZR63K0TK516D

# Get user info
python data_sources/fireflies/fireflies_client.py user

Related Files

  • Client Implementation: data_sources/fireflies/fireflies_client.py
  • Example Usage: algorithms/A8_G&A_div/Daniel Personal/finetune_on_calls_emails_docs/01_fetch_last_call.py
  • CLAUDE.md Reference: Section 1.1¶6 - Fireflies operations

Version History

  • v1.0 (2025-01-15): Initial skill creation
    • Search calls by keyword, participant, date
    • Get full transcripts and summaries
    • Extract action items
    • CLI and Python API