Skip to content

Automation Setup Guide

This guide demonstrates how to create and manage workflows that enable automatic action item assignment through AI-powered phrase matching.

Overview

Automations allow your partner application to directly receive action items from Contio meetings based on phrase matching. When an action item matches your automation phrases, Contio will:

  1. Create an automation assignment linking the action item to your partner app
  2. Send a automation.assignment.created webhook to your configured webhook URL
  3. Send action_item.updated webhooks when the action item is modified

Automation Concepts

What is an Automation?

A partner automation defines:

  • Name: Display name for the automation
  • Description: What the automation handles
  • Actions: Array of action configurations (currently supports phrase_match type)
    • Type: "phrase_match" for phrase-based matching
    • Config: Contains phrases array with matching phrases
  • Status: active or inactive

AI Matching Process

  1. Action items are extracted from meeting transcripts by the AI agent
  2. For meetings with participants connected to partner apps, active automations are loaded
  3. Automation trigger phrases are passed to the AI agent as EntityMappings
  4. The AI agent matches action items against automation phrases
  5. Matched items are assigned to partner automation with confidence scores
  6. Webhook notifications are sent to partner applications

Creating Automations

Initialize Admin Client

import { ContioPartnerSDK } from '@contio/partner-sdk';

const sdk = new ContioPartnerSDK({
  apiKey: process.env.CONTIO_ADMIN_API_KEY!,
  apiUrl: process.env.CONTIO_API_URL || 'https://api.contio.ai'
});

const adminClient = sdk.forAdmin();

Create a Contact Automation

async function createContactAutomation() {
  const automation = await adminClient.createAutomation({
    name: 'Create CRM Contact',
    description: 'Create new contacts in CRM from meeting participants',
    trigger_type: 'action_item_match',
    actions: [
      {
        type: 'phrase_match',
        config: {
          phrases: [
            'create contact',
            'add contact',
            'new contact',
            'save contact information',
            'add to CRM'
          ]
        }
      }
    ]
  });

  console.log('Contact automation created:', automation.id);
  return automation;
}

Create a Deal Automation

async function createDealAutomation() {
  const automation = await adminClient.createAutomation({
    name: 'Create Sales Deal',
    description: 'Create new deals in CRM from meeting discussions',
    trigger_type: 'action_item_match',
    actions: [
      {
        type: 'phrase_match',
        config: {
          phrases: [
            'create deal',
            'new opportunity',
            'potential sale',
            'follow up on proposal',
            'send quote',
            'prepare contract'
          ]
        }
      }
    ]
  });

  console.log('Deal automation created:', automation.id);
  return automation;
}

Create a Task Automation

async function createTaskAutomation() {
  const automation = await adminClient.createAutomation({
    name: 'Assign Follow-up Task',
    description: 'Create follow-up tasks in project management tool',
    trigger_type: 'action_item_match',
    actions: [
      {
        type: 'phrase_match',
        config: {
          phrases: [
            'follow up',
            'schedule meeting',
            'send email',
            'prepare document',
            'review proposal',
            'create task'
          ]
        }
      }
    ]
  });

  console.log('Task automation created:', automation.id);
  return automation;
}

Configure Webhook URL

Before receiving webhooks, configure your partner app's webhook URL:

async function configureWebhook() {
  const partnerApp = await adminClient.updatePartnerApp({
    webhook_url: 'https://your-app.com/webhooks/contio',
  });

  console.log('Webhook URL configured:', partnerApp.webhook_url);
}

Handle Automation Webhooks

import { verifyWebhookSignature } from '@contio/partner-sdk';
import express from 'express';

app.post('/webhooks/contio', express.raw({ type: 'application/json' }), async (req, res) => {
  const signature = req.headers['x-contio-signature'] as string;
  const payload = req.body.toString();

  // Verify signature using your partner app's webhook_secret
  if (!verifyWebhookSignature(payload, signature, process.env.CONTIO_WEBHOOK_SECRET!)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  const event = JSON.parse(payload);

  try {
    switch (event.event_type) {
      case 'automation.assignment.created':
        await handleAutomationAssignmentCreated(event);
        break;

      case 'action_item.updated':
        await handleActionItemUpdated(event);
        break;

      default:
        console.log('Unknown event type:', event.event_type);
    }

    res.status(200).json({ success: true });
  } catch (error) {
    console.error('Webhook processing error:', error);
    res.status(500).json({ error: 'Processing failed' });
  }
});

Handle Automation Assignment Created

async function handleAutomationAssignmentCreated(event: any) {
  const { automation_assignment } = event.data;

  console.log('New automation assignment:', automation_assignment.id);
  console.log('Automation:', automation_assignment.automation_name);
  console.log('Action Item:', automation_assignment.action_item.description);
  console.log('Confidence:', automation_assignment.confidence_score);

  // Process based on automation
  const automationName = automation_assignment.automation_name;
  const actionItem = automation_assignment.action_item;

  if (automationName.includes('Contact')) {
    await createCRMContact(actionItem);
  } else if (automationName.includes('Deal')) {
    await createCRMDeal(actionItem);
  } else if (automationName.includes('Task')) {
    await createProjectTask(actionItem);
  }
}

Handle Action Item Updates

async function handleActionItemUpdated(event: any) {
  const { action_item } = event.data;

  console.log('Action item updated:', action_item.action_item_id);
  console.log('Is completed:', action_item.is_completed);

  // Sync updates to your system
  await syncActionItemUpdate(action_item);
}

Managing Automations

List Automations

async function listAutomations() {
  const automations = await adminClient.listAutomations({
    page: 1,
    limit: 100,
    status: 'active'
  });

  console.log('Active automation:');
  automations.data.forEach(automation => {
    console.log(`- ${automation.name}: ${automation.description}`);
    console.log(`  Status: ${automation.status}`);

    // Display phrases
    const phraseAction = automation.actions.find(a => a.type === 'phrase_match');
    if (phraseAction?.config.phrases) {
      console.log(`  Phrases: ${phraseAction.config.phrases.join(', ')}`);
    }
  });

  return automations;
}

Update Automations Phrases

async function updateAutomationmw(automationId: string) {
  const updated = await adminClient.updateAutomation(automationId, {
    actions: [
      {
        type: 'phrase_match',
        config: {
          phrases: [
            'updated phrase',
            'new keyword',
            'additional trigger'
          ]
        }
      }
    ]
  });

  console.log('Automation updated:', updated);
  return updated;
}

Deactivate Automation

async function deactivateAutomation(automationId: string) {
  const updated = await adminClient.updateAutomation(automationId, {
    status: 'inactive'
  });

  console.log('Automation deactivated:', automationId);
  return updated;
}

Best Practices

Phrase Design

  • Use specific, action-oriented phrases
  • Include variations and synonyms (e.g., "create contact", "add contact", "new contact")
  • Avoid overly broad phrases that may cause false matches
  • Test phrases with sample action items before deployment
  • Consider industry-specific terminology
  • Keep phrases concise and focused

Webhook Security

  • Always verify webhook signatures using the SDK's verifyWebhookSignature function
  • Use HTTPS endpoints only
  • Implement rate limiting on your webhook endpoint
  • Log all webhook events for auditing and debugging
  • Store webhook secrets securely (environment variables, secret managers)

Error Handling

  • Implement retry logic with exponential backoff for transient failures
  • Return 200 OK quickly to acknowledge receipt, then process asynchronously
  • Use dead letter queues for failed processing
  • Monitor webhook delivery success rates

Performance Optimization

  • Process webhooks asynchronously (queue-based processing)
  • Batch operations when possible
  • Cache frequently accessed data
  • Monitor processing times and optimize bottlenecks

Troubleshooting

Automation Not Matching Action Items

  • Review phrase list - ensure phrases are specific and action-oriented
  • Verify automation status is active
  • Check that users in the meeting are connected to your partner app
  • Test phrases against sample action item descriptions
  • Review confidence scores in webhook payloads

Webhook Delivery Failures

  • Verify webhook URL is publicly accessible (HTTPS required)
  • Check signature verification logic
  • Review firewall/security settings
  • Ensure webhook endpoint returns 200 OK within timeout

Missing Webhook Events

  • Confirm webhook_url is configured on your partner app
  • Verify webhook_secret is correctly stored
  • Check that action items have has_partner_assignment = true

Next Steps