Skip to content

AI-Enabled Meeting Prep

This guide shows how to combine the Meeting Context API (v1.4.6) and the Chat Session API (v1.4.7) to build AI-powered meeting preparation workflows. Partners can upload background materials, let the AI build a fully customized meeting — complete with named templates, structured agendas, talking points, and participants — then inspect and refine the result.

Overview

The AI-Enabled Meeting Prep workflow has three phases:

  1. Upload Context — Provide the AI with background materials (research, briefs, prior notes)
  2. Build with the AI — The agent analyzes documents and constructs the agenda, talking points, and participant list directly on the meeting
  3. Review & Refine — Inspect the AI-built meeting via the API and make targeted adjustments using the entity APIs or further chat
┌──────────────────┐     ┌──────────────────┐     ┌──────────────────┐
│  Upload Context  │────▶│  Build with AI   │────▶│  Review & Refine │
│  Documents       │     │  Agent builds    │     │  Inspect via API │
│                  │     │  agenda, adds    │     │  Adjust entities │
│                  │     │  participants    │     │  or chat further │
└──────────────────┘     └──────────────────┘     └──────────────────┘
   POST /meetings/       POST /sessions            GET /meetings/{id}/
   {id}/context          PUT /sessions/{id}          agenda-items
                                                   GET /meetings/{id}/
                                                     participants

Prerequisites

  • Partner app with OAuth scopes: meetings:write, context:write, chat:write
  • A user who has authorized your app via OAuth

Phase 1: Upload Context Documents

The Meeting Context API accepts text-based documents that are automatically sanitized and converted to clean Markdown for the AI agent.

Supported Formats

Format Extensions Notes
Plain Text .txt Direct pass-through
Markdown .md HTML embeds sanitized
CSV / TSV .csv, .tsv Rendered as Markdown tables (up to 1,000 rows)
JSON .json Structured → nested Markdown headings
YAML .yaml, .yml Structured → nested Markdown headings
XML .xml Tree → nested Markdown headings
HTML .html, .htm Tags stripped, content preserved

Sanitization Pipeline

Every uploaded document passes through a multi-stage sanitization pipeline before the AI agent sees it:

  1. Format Validation — UTF-8 encoding verified, binary content rejected
  2. Format Conversion — Source format converted to canonical Markdown with YAML front matter
  3. PII Redaction — Credit card numbers, SSNs, and email addresses automatically redacted
  4. Secret Detection — API keys, tokens, and passwords are detected and redacted
  5. Formula Injection Escaping — Spreadsheet formula patterns (=, +, -, @ prefixes) escaped

Upload Limits

Constraint Value
Maximum file size 4.5 MB
Maximum documents per meeting per partner 20
Content encoding UTF-8 only

Example: Upload a Research Brief

const contextDoc = await sdk.user.uploadMeetingContext(meetingId, {
  file: researchBriefBuffer,
  title: 'Q2 Market Research Summary',
  context_type: 'research',
  source_format: 'md'
});

// contextDoc.id → use this to prime the chat session
console.log(`Uploaded context: ${contextDoc.id}`);

Phase 2: Converse with the AI Agent

With context documents uploaded, create a chat session scoped to the same meeting. The agent has access to all context documents attached to that meeting. Context from prior meetings and other workspace features such as custom templates are also available to the agent.

Start a Meeting-Scoped Session

const session = await sdk.user.createChatSession({
  meeting_id: meetingId,
  message: `Use the "Quarterly Planning" template to build out a
    90-minute meeting with the executive team. My talking points should
    include insights and key findings from last week's staff meeting.`,
  metadata: {
    workflow: 'meeting-prep',
    template_type: 'quarterly-planning'
  }
});

Note: All context documents previously uploaded to this meeting are automatically included in the agent's context window. Simply provide the meeting_id and the agent will reference all attached documents.

Refine with Follow-Up Messages

The agent builds the agenda, adds participants, applies a named template, and structures talking points directly on the meeting. Use follow-up messages to guide the agent's work:

// Ask the agent to adjust the time allocation and focus for a specific agenda item
await sdk.user.sendMessage(session.id, {
  message: `For the "Market Expansion" agenda item, adjust
    the time allocation to 30 minutes for the research brief discussion
    to ensure alignment with our current priorities.`
});
// → Your webhook endpoint receives session.turn.completed when the agent finishes

// Ask the agent to add the right participants
await sdk.user.sendMessage(session.id, {
  message: `Add the marketing and product leads as participants.
    The budget discussion should also include Jim Gladney from Finance.`
});
// → Another session.turn.completed webhook fires when this turn is done

The agent operates directly on the meeting entity — creating and editing agenda items, adding participants, and updating descriptions.

Asynchronous by design. Both createChatSession and sendMessage return immediately — they do not block until the agent finishes. Your integration should listen for webhook callbacks to know when each turn is complete:

Event When it fires What to do
session.turn.completed Agent finished processing a turn Safe to send follow-up messages or inspect updated meeting entities
session.turn.failed Agent encountered an error Inspect error_code / error_message and decide whether to retry
session.expired Session timed out due to inactivity Start a new session if more interaction is needed

See the Webhook Events reference and the AsyncAPI specification for full payload schemas.

Phase 3: Review & Refine

After the agent has built the meeting, use the entity APIs to inspect what was created and make targeted adjustments.

Inspect the AI-Built Agenda

// Review agenda items the agent created
const agendaItems = await sdk.user.listAgendaItems(meetingId);

for (const item of agendaItems.items) {
  console.log(`[${item.item_type}] ${item.title} (${item.time_allocation_minutes}min)`);
  console.log(`  ${item.description}\n`);
}

// Review participants the agent added
const participants = await sdk.user.listParticipants(meetingId);

for (const p of participants.items) {
  console.log(`${p.name}${p.role}`);
}

Refine via Entity APIs

Make surgical edits to individual items without re-running the full AI flow:

// Update an agenda item's time allocation
await sdk.user.updateAgendaItem(meetingId, agendaItemId, {
  time_allocation_minutes: 25  // Give more time to this discussion
});

// Remove a participant the agent added incorrectly
await sdk.user.removeParticipant(meetingId, participantId);

// Add a missing agenda item manually
await sdk.user.createAgendaItem(meetingId, {
  item_type: 'INFORMATION',
  title: 'Logistics & Room Setup',
  description: 'Conference Room B, video bridge link in calendar invite.',
  time_allocation_minutes: 5
});

Refine via Further Chat

For larger changes, continue the chat session — the agent still has full context:

await sdk.user.sendMessage(session.id, {
  message: `Move the budget discussion to the first agenda slot and
    increase its time to 20 minutes. Also add a 5-minute wrap-up
    item at the end for action item review.`
});
// → Wait for session.turn.completed webhook before inspecting updated entities

Agenda Item Types

The agent uses these item types when building the agenda:

Type Purpose Best For
DISCUSSION Open-ended conversation topics Strategy reviews, brainstorming
DECISION Items requiring a concrete decision Budget approvals, go/no-go
ACTION_ITEM Tasks to assign and track Follow-ups, deliverables
INFORMATION Read-out or status updates Metrics reviews, announcements

Complete Meeting Prep Example

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

async function prepareQuarterlyPlanning(userToken: string) {
  const sdk = ContioPartnerSDK.forUser({
    clientId: process.env.OAUTH_CLIENT_ID!,
    clientSecret: process.env.OAUTH_CLIENT_SECRET!,
    accessToken: userToken
  });

  // 1. Create a draft meeting to attach context to
  const meeting = await sdk.user.createMeeting({
    title: 'Q2 Quarterly Planning',
    start_time: '2026-04-01T14:00:00Z',
    end_time: '2026-04-01T15:00:00Z',
    template_id: QUARTERLY_TEMPLATE_ID,
    detail_level: 'STANDARD'
  });

  // 2. Upload context documents
  const research = await sdk.user.uploadMeetingContext(meeting.id, {
    file: fs.readFileSync('./q2-research.md'),
    title: 'Q2 Market Research',
    source_format: 'md'
  });

  const retro = await sdk.user.uploadMeetingContext(meeting.id, {
    file: fs.readFileSync('./q1-retro.csv'),
    title: 'Q1 Retrospective Scores',
    source_format: 'csv'
  });

  // 3. Start a chat session — agent auto-loads all context for this meeting
  const session = await sdk.user.createChatSession({
    meeting_id: meeting.id,
    message: `Build a structured 60-minute quarterly planning agenda
      based on the pre-loaded context. Include specific talking points,
      time allocations, and add the relevant participants.`,
    metadata: { workflow: 'meeting-prep', template: 'quarterly-planning' }
  });

  // 4. The agent processes asynchronously — your webhook endpoint
  //    receives `session.turn.completed` when the first turn finishes.

  // 5. On receiving the webhook, send a follow-up to refine:
  await sdk.user.sendMessage(session.id, {
    message: `Add talking points about competitive positioning
      for the Market Expansion item, using data from the research brief.
      Also add our finance director as a participant for the budget item.`
  });
  // → Another session.turn.completed webhook fires when this turn completes.

  // 6. Once the webhook confirms completion, review and adjust
  const agenda = await sdk.user.listAgendaItems(meeting.id);
  const participants = await sdk.user.listParticipants(meeting.id);

  console.log(`Meeting ${meeting.id} prepared:`);
  console.log(`  ${agenda.items.length} agenda items`);
  console.log(`  ${participants.items.length} participants`);

  // 7. Optional: make surgical edits via entity APIs
  // await sdk.user.updateAgendaItem(meeting.id, itemId, { time_allocation_minutes: 25 });
}

Tips and Best Practices

  • Upload multiple document types. CSV data and narrative Markdown complement each other — the AI can cross-reference quantitative data with qualitative insights.
  • Be specific in your prompts. Instead of "suggest an agenda," ask for "a 60-minute agenda with 4 items, time allocations, and talking points backed by the uploaded data."
  • Use metadata for tracking. The metadata field on sessions lets you tag workflows (e.g., workflow: 'meeting-prep') so you can audit which sessions produced which meetings.
  • Leverage templates. Bind meetings to known templates by name or via template_id so the AI's suggestions align with your organization's standard meeting structures.
  • Use webhooks, not polling. Agent turns are asynchronous. Register a webhook endpoint and listen for session.turn.completed events rather than polling. This keeps your integration event-driven and responsive. See the Webhook Events reference for all chat session event schemas.
  • Review before sharing. Always inspect the AI-built agenda and participant list via the entity APIs before distributing the meeting invite. The agent does the heavy lifting, but a human review pass ensures quality.
  • SDK Examples — Full SDK reference with authentication patterns
  • API Guide — REST endpoint reference and pagination
  • Webhook Events — Subscribe to meeting and action item events