Skip to main content
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