Agent Workflows

Learn how to build intelligent agents that leverage ClarityCall's conversation intelligence to automate workflows, enrich data, and enhance communication.

Why Build Agents with ClarityCall?

ClarityCall provides unique conversation intelligence that goes beyond basic transcription. Your agents can access:

  • Personality insights - Understand communication styles and preferences
  • Pattern analysis - Identify trends across conversations and relationships
  • Contextual understanding - Access full conversation history and context
  • Real-time processing - React to new insights via webhooks

Agent Use Cases

1. Meeting Prep Agent

Automatically prepare for meetings by pulling relevant context from past conversations. Save 15+ minutes per call.

How It Works

  1. Calendar integration detects upcoming meeting
  2. Agent identifies meeting participants via email/name matching
  3. Pulls recent conversations and insights for each participant
  4. Generates context summary with:
    • Communication preferences
    • Recent topics discussed
    • Outstanding action items
    • Suggested approach
  5. Delivers summary via email, Slack, or calendar note

Example Implementation

typescript
import { ClarityCallAPI } from '@claritycall/sdk';

async function prepareMeetingContext(participants: string[]) {
  const api = new ClarityCallAPI({ apiKey: process.env.CLARITYCALL_API_KEY });
  const context = [];

  for (const email of participants) {
    // Find contact by email
    const contact = await api.contacts.findByEmail(email);
    if (!contact) continue;

    // Get conversation history
    const conversations = await api.recordings.list({
      contact_id: contact.id,
      limit: 5,
      sort: 'meeting_date:desc'
    });

    // Get personality insights
    const insights = await api.insights.get(contact.id);

    context.push({
      name: contact.name,
      email: contact.email,
      communication_style: insights.communication_approach,
      recent_topics: insights.recent_topics,
      action_items: insights.pending_action_items,
      last_conversation: conversations[0]?.meeting_date
    });
  }

  return generateMeetingBrief(context);
}

function generateMeetingBrief(context) {
  return {
    summary: `Meeting prep for ${context.length} participants`,
    participants: context.map(p => ({
      name: p.name,
      approach: p.communication_style,
      key_topics: p.recent_topics.slice(0, 3),
      follow_ups: p.action_items
    }))
  };
}

2. Webhook Integration Agent

Send personality insights and conversation intelligence to external systems via webhooks. Keep your tools synchronized automatically.

How It Works

  1. Subscribe to ClarityCall webhooks for new insights
  2. When insight is ready, fetch full contact data
  3. POST enriched data to your external system webhook
  4. Handle responses and retry on failure

Example Implementation

typescript
// Webhook handler for new insights
app.post('/webhooks/claritycall/insight-ready', async (req, res) => {
  const { recording_id, contact_id } = req.body;

  // Fetch full insight data
  const insights = await claritycall.insights.get(contact_id);
  const contact = await claritycall.contacts.get(contact_id);

  // Send to external webhook
  await fetch(process.env.EXTERNAL_WEBHOOK_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      contact_id: contact.id,
      contact_email: contact.email,
      communication_style: insights.communication_approach,
      favorite_topics: insights.favorite_topics,
      last_meeting_date: insights.last_conversation_date,
      total_conversations: insights.total_conversations,
      personality_summary: insights.personality_summary
    })
  });

  res.json({ success: true });
});

// Batch sync existing contacts
async function syncAllContactsViaWebhook() {
  const contacts = await claritycall.contacts.list({ limit: 100 });

  for (const contact of contacts.items) {
    const insights = await claritycall.insights.get(contact.id);
    await notifyExternalSystem(contact, insights);
  }
}

3. Communication Coach Agent

Provide real-time communication suggestions based on contact preferences and past interaction patterns.

How It Works

  1. User initiates communication (email compose, call prep, etc.)
  2. Agent identifies recipient and pulls communication preferences
  3. Analyzes past successful conversations
  4. Generates approach recommendations
  5. Displays contextual suggestions to user

Example Implementation

typescript
async function getCommunciationGuidance(recipientEmail: string) {
  const contact = await claritycall.contacts.findByEmail(recipientEmail);
  if (!contact) {
    return { suggestion: 'No prior interaction data available' };
  }

  const insights = await claritycall.insights.get(contact.id);

  // Analyze communication style
  const guidance = {
    recipient: contact.name,
    style: insights.communication_approach,

    // Generate specific recommendations
    dos: [
      insights.prefers_data_driven && 'Include specific data and metrics',
      insights.prefers_direct && 'Lead with the main point',
      insights.values_relationships && 'Include personal check-in'
    ].filter(Boolean),

    donts: [
      insights.dislikes_small_talk && 'Avoid lengthy preambles',
      insights.prefers_brevity && 'Keep message concise',
      insights.dislikes_jargon && 'Use plain language'
    ].filter(Boolean),

    tone: insights.preferred_tone, // 'formal', 'casual', 'friendly', etc.
    topics_to_mention: insights.interests,
    topics_to_avoid: insights.sensitive_topics
  };

  return guidance;
}

// Email plugin example
chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
  if (request.action === 'get_email_guidance') {
    const guidance = await getCommunciationGuidance(request.recipientEmail);
    sendResponse({ guidance });
  }
});

4. Follow-up Agent

Automatically draft personalized follow-up emails based on conversation content and identified action items.

How It Works

  1. Recording processing completes (webhook notification)
  2. Agent fetches full transcript and insights
  3. Identifies action items and key decisions
  4. Retrieves contact communication preferences
  5. Generates personalized follow-up draft
  6. Sends draft to user for review/sending

Example Implementation

typescript
async function generateFollowUpEmail(recordingId: string) {
  // Get recording details
  const recording = await claritycall.recordings.get(recordingId);
  const transcript = await claritycall.recordings.getTranscript(recordingId);

  // Get insights
  const insights = await claritycall.insights.getByRecording(recordingId);

  // Extract action items (from insights or transcript analysis)
  const actionItems = insights.action_items;
  const decisions = insights.key_decisions;

  // Get contact preferences for tone
  const contact = await claritycall.contacts.get(recording.primary_contact_id);
  const preferences = await claritycall.insights.get(contact.id);

  // Generate email using LLM with context
  const emailDraft = await generateWithAI({
    template: 'follow_up',
    context: {
      meeting_title: recording.title,
      meeting_date: recording.meeting_date,
      participants: recording.participants,
      action_items: actionItems,
      decisions: decisions,
      key_topics: insights.topics_discussed,
      tone: preferences.preferred_tone,
      style: preferences.communication_approach
    }
  });

  return emailDraft;
}

// Webhook handler
app.post('/webhooks/claritycall/processing-complete', async (req, res) => {
  const { recording_id } = req.body;

  // Generate follow-up
  const email = await generateFollowUpEmail(recording_id);

  // Save as draft in user's email system
  await emailService.createDraft({
    to: email.recipients,
    subject: email.subject,
    body: email.body,
    metadata: { claritycall_recording_id: recording_id }
  });

  res.json({ success: true });
});

API Endpoints for Agent Workflows

Core Endpoints

  • GET /api/v2/contacts - List and search contacts
  • GET /api/v2/contacts/:id - Get contact details
  • GET /api/v2/recordings - List recordings with filters
  • GET /api/v2/recordings/:id - Get recording details
  • GET /api/v2/recordings/:id/transcript - Get full transcript
  • GET /api/v2/insights/contact/:id - Get contact insights
  • POST /api/v2/webhooks - Configure webhook endpoints

Webhook Events

Subscribe to real-time events to trigger agent workflows:

  • recording.processing.started - New recording uploaded
  • recording.processing.completed - Transcript ready
  • insights.generated - New insights available
  • contact.updated - Contact information changed

Best Practices

Performance

  • Cache contact insights to reduce API calls
  • Use webhooks instead of polling for real-time updates
  • Batch API requests when processing multiple contacts
  • Implement exponential backoff for retries

Data Privacy

  • Store minimal data - reference ClarityCall IDs instead of copying sensitive content
  • Respect user permissions when syncing to external systems
  • Implement proper authentication for webhook endpoints
  • Use HTTPS for all API communications

User Experience

  • Provide preview/approval flow for automated actions (emails, webhook notifications)
  • Allow users to customize agent behavior and preferences
  • Show transparency - let users know what data is being used
  • Implement error handling with clear user messaging

Example: Complete Meeting Prep Agent

Here's a complete example of a meeting prep agent that integrates with Google Calendar and sends briefs via Slack:

typescript
import { ClarityCallAPI } from '@claritycall/sdk';
import { google } from 'googleapis';
import { WebClient } from '@slack/web-api';

const claritycall = new ClarityCallAPI({ apiKey: process.env.CLARITYCALL_API_KEY });
const slack = new WebClient(process.env.SLACK_BOT_TOKEN);

// Run every hour to check for upcoming meetings
async function checkUpcomingMeetings() {
  const calendar = google.calendar({ version: 'v3', auth: getGoogleAuth() });

  // Get meetings in next 2 hours
  const now = new Date();
  const twoHoursFromNow = new Date(now.getTime() + 2 * 60 * 60 * 1000);

  const events = await calendar.events.list({
    calendarId: 'primary',
    timeMin: now.toISOString(),
    timeMax: twoHoursFromNow.toISOString(),
    singleEvents: true,
    orderBy: 'startTime'
  });

  for (const event of events.data.items || []) {
    // Skip if already sent prep
    if (await hasSentPrep(event.id)) continue;

    // Generate meeting prep
    const attendees = event.attendees?.map(a => a.email) || [];
    const prep = await generateMeetingPrep(attendees, event.summary);

    // Send to Slack
    await slack.chat.postMessage({
      channel: process.env.SLACK_CHANNEL,
      text: `Meeting prep for: ${event.summary}`,
      blocks: formatMeetingPrepBlocks(prep, event)
    });

    await markPrepSent(event.id);
  }
}

async function generateMeetingPrep(attendeeEmails: string[], meetingTitle: string) {
  const attendeeContext = [];

  for (const email of attendeeEmails) {
    const contact = await claritycall.contacts.findByEmail(email);
    if (!contact) continue;

    // Get latest insights
    const insights = await claritycall.insights.get(contact.id);

    // Get recent conversations
    const recentConvos = await claritycall.recordings.list({
      contact_id: contact.id,
      limit: 3,
      sort: 'meeting_date:desc'
    });

    attendeeContext.push({
      name: contact.name,
      email: contact.email,
      communication_style: insights.communication_approach,
      recent_topics: insights.recent_topics.slice(0, 5),
      pending_actions: insights.pending_action_items,
      last_conversation: recentConvos[0]?.meeting_date,
      conversation_count: insights.total_conversations,
      key_interests: insights.interests
    });
  }

  return {
    meeting_title: meetingTitle,
    attendees: attendeeContext,
    overall_approach: deriveOverallApproach(attendeeContext),
    suggested_agenda: generateSuggestedAgenda(attendeeContext)
  };
}

function formatMeetingPrepBlocks(prep, event) {
  return [
    {
      type: 'header',
      text: { type: 'plain_text', text: `📅 ${prep.meeting_title}` }
    },
    {
      type: 'section',
      text: {
        type: 'mrkdwn',
        text: `*Time:* ${new Date(event.start.dateTime).toLocaleString()}\n*Duration:* ${calculateDuration(event)}`
      }
    },
    {
      type: 'divider'
    },
    ...prep.attendees.map(attendee => ({
      type: 'section',
      text: {
        type: 'mrkdwn',
        text: `*${attendee.name}*\n` +
              `📊 _${attendee.conversation_count} previous conversations_\n` +
              `💡 **Communication Style:** ${attendee.communication_style}\n` +
              `🔖 **Recent Topics:** ${attendee.recent_topics.join(', ')}\n` +
              `✅ **Follow-ups:** ${attendee.pending_actions.join(', ') || 'None'}`
      }
    })),
    {
      type: 'divider'
    },
    {
      type: 'section',
      text: {
        type: 'mrkdwn',
        text: `*Suggested Approach:*\n${prep.overall_approach}`
      }
    }
  ];
}

// Run every hour
setInterval(checkUpcomingMeetings, 60 * 60 * 1000);

Next Steps