Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/sam-ayo/recall_sdk/llms.txt

Use this file to discover all available pages before exploring further.

Retrieves detailed logs of the bot’s activity during the meeting lifecycle. Useful for debugging issues and understanding bot behavior.

Method Signature

bot.getBotLogs(params: BaseBotParams): Promise<BotLogs>

Parameters

id
string
required
The unique identifier of the bot

Response

Returns an array of log entries:
logs
array
Array of log entry objects
timestamp
string
ISO 8601 timestamp when the log entry was created
level
string
Log level: “info”, “warning”, “error”, or “debug”
message
string
Log message describing the event
event_type
string
Type of event (e.g., “bot_joining”, “recording_started”, “error_occurred”)
details
object
Additional context and details about the event

Example

import { Recall } from '@recall.ai/sdk';

const client = new Recall({
  apiKey: 'your-api-key',
  region: 'us-west-2'
});

// Get bot logs
const logs = await client.bot.getBotLogs({
  id: 'bot_1234567890'
});

console.log(`Total log entries: ${logs.logs.length}`);

for (const log of logs.logs) {
  console.log(`[${log.timestamp}] ${log.level.toUpperCase()}: ${log.message}`);
}

Example: Filter Errors

async function getErrors(botId: string) {
  const logs = await client.bot.getBotLogs({ id: botId });
  
  const errors = logs.logs.filter(log => log.level === 'error');
  
  if (errors.length === 0) {
    console.log('No errors found');
    return [];
  }
  
  console.log(`Found ${errors.length} error(s):`);
  
  for (const error of errors) {
    console.log(`\n[${error.timestamp}]`);
    console.log(`Event: ${error.event_type}`);
    console.log(`Message: ${error.message}`);
    if (error.details) {
      console.log('Details:', JSON.stringify(error.details, null, 2));
    }
  }
  
  return errors;
}

await getErrors('bot_1234567890');

Example: Track Bot Progress

async function trackBotProgress(botId: string) {
  const logs = await client.bot.getBotLogs({ id: botId });
  
  const milestones = logs.logs.filter(log => 
    ['bot_created', 'bot_joining', 'bot_joined', 'recording_started', 
     'recording_stopped', 'bot_left', 'processing_complete'].includes(log.event_type)
  );
  
  console.log('Bot Lifecycle Timeline:');
  console.log('='.repeat(50));
  
  for (const milestone of milestones) {
    const time = new Date(milestone.timestamp).toLocaleTimeString();
    console.log(`${time} - ${milestone.message}`);
  }
}

await trackBotProgress('bot_1234567890');

Example: Debug Bot Issues

async function debugBot(botId: string) {
  const bot = await client.bot.retrieve({ id: botId });
  const logs = await client.bot.getBotLogs({ id: botId });
  
  console.log('Bot Debug Information');
  console.log('='.repeat(50));
  console.log(`Bot ID: ${bot.id}`);
  console.log(`Status: ${bot.status}`);
  console.log(`Platform: ${bot.meeting_url.platform}`);
  console.log(`\nRecent Logs (last 10):`);
  
  const recentLogs = logs.logs.slice(-10);
  
  for (const log of recentLogs) {
    const time = new Date(log.timestamp).toLocaleTimeString();
    const level = log.level.toUpperCase().padEnd(7);
    console.log(`${time} [${level}] ${log.message}`);
  }
  
  // Check for common issues
  const hasErrors = logs.logs.some(log => log.level === 'error');
  const hasPermissionDenied = logs.logs.some(log => 
    log.message.includes('permission') && log.message.includes('denied')
  );
  
  console.log('\nDiagnostics:');
  if (hasErrors) {
    console.log('⚠️ Errors detected - see error logs above');
  }
  if (hasPermissionDenied) {
    console.log('⚠️ Recording permission was denied');
  }
  if (!hasErrors && !hasPermissionDenied) {
    console.log('✓ No obvious issues detected');
  }
}

await debugBot('bot_1234567890');

Example: Export Logs to File

import { writeFile } from 'fs/promises';

async function exportLogs(botId: string, filename: string) {
  const logs = await client.bot.getBotLogs({ id: botId });
  
  let content = `Bot Logs - ${botId}\n`;
  content += '='.repeat(80) + '\n\n';
  
  for (const log of logs.logs) {
    content += `[${log.timestamp}] ${log.level.toUpperCase()}\n`;
    content += `Event: ${log.event_type}\n`;
    content += `Message: ${log.message}\n`;
    if (log.details) {
      content += `Details: ${JSON.stringify(log.details)}\n`;
    }
    content += '\n';
  }
  
  await writeFile(filename, content);
  console.log(`Logs exported to ${filename}`);
}

await exportLogs('bot_1234567890', 'bot-logs.txt');

Example: Monitor Bot in Real-time

async function monitorBot(botId: string, intervalSeconds: number = 10) {
  let lastLogCount = 0;
  
  const checkLogs = async () => {
    const logs = await client.bot.getBotLogs({ id: botId });
    const bot = await client.bot.retrieve({ id: botId });
    
    if (logs.logs.length > lastLogCount) {
      const newLogs = logs.logs.slice(lastLogCount);
      for (const log of newLogs) {
        const time = new Date(log.timestamp).toLocaleTimeString();
        console.log(`[${time}] ${log.message}`);
      }
      lastLogCount = logs.logs.length;
    }
    
    if (['done', 'fatal', 'media_expired'].includes(bot.status)) {
      console.log(`\nBot reached final status: ${bot.status}`);
      clearInterval(interval);
    }
  };
  
  console.log(`Monitoring bot ${botId}...`);
  const interval = setInterval(checkLogs, intervalSeconds * 1000);
  await checkLogs(); // Initial check
}

await monitorBot('bot_1234567890', 5);

Notes

  • Logs are continuously updated as the bot progresses through its lifecycle
  • Logs are retained for a limited time after the meeting ends
  • Use logs for debugging issues like permission denials, connection problems, or unexpected behavior
  • Error-level logs indicate issues that prevented the bot from functioning normally

Build docs developers (and LLMs) love