203 lines
Revenue Workflows

Solution Page

Post-Call Analysis

Turn a meeting into structured notes, next steps, participant context, and CRM follow-up without manual cleanup.

Sales
RevOps
Founders
Google Calendar
Zoom
Salesforce

Overview

For Sales, RevOps, Founders

Integrations: Google Calendar, Zoom, Salesforce

Meeting recap

Next steps

Participant context

CRM-ready follow-up

Standardizes post-call execution across reps.

Reduces manual cleanup after every meeting.

Makes downstream CRM and enablement workflows easier to automate.

What It Solves

Manual post-call follow-up is inconsistent, slow, and hard to operationalize across a revenue team.

Workflow

1

Collect meeting metadata and conversation context from connected systems.

2

Extract structured notes, follow-ups, and participant intelligence from the call.

3

Return a reusable output package for CRM updates, recap docs, and next-step execution.

Implementation

Review the underlying plan definition, inspect the template when available, and see how the workflow is encoded for repeatable execution.

Plan Code

Markdown Report

post-call-analysis.yaml

203 lines

parameters:
  - name: eventId
    schema:
      type: string
      description: "Calendar Event ID to fetch details for"
  - name: zoomId
    schema:
      type: string
      description: "Zoom Meeting ID associated with the calendar event"
  - name: zoomToken
    schema:
      type: string
      description: "Zoom API Access Token with permissions to read meeting recordings and transcripts"


transformers:
  - name: event_participants_extractor
    onFunctionOutput: calendar_events_get
    jmesPath: "{creator_email: creator.email, start_datetime: start.dateTime, timezone: start.timeZone, participants: attendees[*].{email: email, status: responseStatus, optional: optional}, external_emails: attendees[?!ends_with(email, '@barndoor.ai')].email}"

  - name: finalize_search_results
    onFunctionOutput: search-contacts
    jmesPath: "contact_search_results"

components:
  schemas:
    event_details:
      type: object
      properties:
        creator_email:
          type: string
          description: "Email address of the event creator"
        start_datetime:
          type: string
          description: "Start date and time of the event in ISO format"
        timezone:
          type: string
          description: "Timezone of the event"
        invitees:
          type: array
          items:
            type: object
            properties:
              email:
                type: string
                description: "Email address of the participant"
              status:
                type: string
                description: "Response status of the participant"
              optional:
                type: boolean
                description: "Whether the participant is optional"

preCalls:
      - name: calendar_events_get
        args:
          calendarId: primary
          timeZone: "America/Eastern"
          alwaysIncludeEmail: true
          eventId: "{{ .params.eventId }}"
        in: vars
        var: calendar_event_details

      - name: zoom_aggregator
        in: vars
        var: zoom_recordings
        args:
          meetingId: "{{ .params.zoomId }}"
          accessToken: "{{ .params.zoomToken }}"
        code: |- 
          const fetchMeetingById = runFunction("http_fetch", {
            method: "GET",
            url: `https://api.zoom.us/v2/meetings/${args.meetingId}/recordings`,
            headers: {
              "Content-Type": "application/json",
              "Authorization": `Bearer ${args.accessToken}`,
            }
          });

          const fetchTranscript = runFunction("http_fetch", {
            method: "GET",
            url: `https://api.zoom.us/v2/meetings/${fetchMeetingById.uuid}/transcript`,
            headers: {
              "Content-Type": "application/json",
              "Authorization": `Bearer ${args.accessToken}`,
            }
          });

          const transcriptData = runFunction("http_fetch", {
            method: "GET",
            url: fetchTranscript.download_url,
            headers: {
              "Content-Type": "application/json",
              "Authorization": `Bearer ${args.accessToken}`,
            }
          });

          transcriptData;


sessions:
  calendar-details:
      prompt: |-
        Gvien the data from {{ .vars.calendar_event_details }} map the calendar event details from vars.calendar_event_details to the event_details schema.

  zoom-details:
      attempts: 3
      prompt: |-
        Given the Zoom meeting recording transcript for meeting ID {{ .vars.zoom_recordings }} map the following details to the meeting summary schema:
          1. A summary of the meeting including key points discussed.
          2. next steps derived from the meeting based on next steps schema.
          5. A list of all participants in the meeting.
  
  missing-contacts:
    preCalls:
      - name: queryContact
        args:
          emails: $(vars.calendar_event_details.external_emails)
        code: |-
          let query = "Email IN (" + args.emails.map(email => `'${email}'`).join(", ") + ")";

          const results = runFunction("queryContact", { fields: ["FIELDS(STANDARD)"], where: query });
          const records = results.records || [];
          const found = new Set(records.map(r => r.Email));

          const missing = (args.emails || []).filter(e => !found.has(e));

          const created = missing.map(email => {
            const local = email.split("@")[0];
            const lastName = local.slice(1) || "New";
            const res = runFunction("createContact", { Email: email, LastName: lastName });
            return { email, lastName, id: res.id || res.Id || null };
          });

          // LAST expression is the output:
          ({ missing, created, found: Array.from(found) });

    prompt: Given the contact query results above, map the missing contact to the crm_report
  
  # send-report:
  #   context: true
  #   depemdsOn:
  #     - calendar-details
  #     - zoom-details
  #     - missing-contacts
  #   prePrompt: |-
  #     Given what we know, write an elegant email with a subject of post call analysis describing the content of post-call analysis report. Send this using gmail
schema:
    type: object
    properties:
      calendar_details:
        type: object
        x-session: calendar-details
        $ref: '#/components/schemas/event_details'
      meeting_summary:
        type: object
        x-session: zoom-details
        properties:
          summary:
            type: string
            description: Summary of the meeting including key points discussed.
          next_steps:
            type: array
            description: Actionable next steps derived from the meeting.
            items:
              type: object
              properties:
                step:
                  type: string
                  description: Description of the next step.
                owner:
                  type: string
                  description: Person responsible for the next step.
                ownerType:
                  type: string
                  description: Type of owner (e.g., Barndoor member or external participant).    
 
          call_participants:
            type: array
            items:
              type: object
              properties:
                name:
                  type: string
                  description: Name of the participant.
      crm_report:
        type: array
        x-session: missing-contacts
        items:
          type: object
          properties:
            email:
              type: string
              description: Email address of the contact.
            was_created:
              type: boolean
              description: Whether the contact was created during this run.
            contact_id:
              type: string
              description: Salesforce contact ID.
            salesforce_url:
              type: string
              description: Link to the Salesforce contact page.