
An AI-powered agent that automatically summarizes sales calls using Vercel's Sandbox architecture. The agent analyzes call transcripts and generates structured summaries with objections, action items, and insights.
Template Note: This template uses Gong as a starting example for call transcript integration. You can adapt it to work with other call recording platforms (Zoom, Google Meet, etc.) by modifying the webhook handler and transcript fetching logic.
You can deploy to Vercel and try it immediately with demo data with one click:
Demo mode is enabled by default - no Gong credentials required to test!
git clone https://github.com/vercel-labs/call-summary-agentcd call-summary-agentnpm install
vercel linkvercel env pull
Or manually create .env.local:
AI_GATEWAY_API_KEY=your_ai_gateway_api_key
npm run dev
# Check status (should show demoMode: true)curl http://localhost:3000/api/gong-webhook# Trigger the agent with demo datacurl -X POST http://localhost:3000/api/gong-webhook \-H "Content-Type: application/json" \-d '{}'
To use real Gong API data instead of demo data:
Add these to your Vercel project settings or .env.local:
| Variable | Required | Description |
|---|---|---|
AI_GATEWAY_API_KEY | Yes | Vercel AI Gateway API key |
USE_REAL_DATA | Yes | Set to true to disable demo mode |
GONG_ACCESS_KEY | Yes | Your Gong API access key |
GONG_SECRET_KEY | Yes | Your Gong API secret key |
AI_GATEWAY_API_KEY=your_ai_gateway_api_keyUSE_REAL_DATA=trueGONG_ACCESS_KEY=your_gong_access_keyGONG_SECRET_KEY=your_gong_secret_key
https://your-app.vercel.app/api/gong-webhook| Variable | Required | Default | Description |
|---|---|---|---|
AI_GATEWAY_API_KEY | Yes | - | Vercel AI Gateway API key |
USE_REAL_DATA | No | false | Set to true for production Gong API |
GONG_ACCESS_KEY | When USE_REAL_DATA=true | - | Gong API access key |
GONG_SECRET_KEY | When USE_REAL_DATA=true | - | Gong API secret key |
COMPANY_NAME | No | "Your Company" | Company name in prompts |
AI_MODEL | No | anthropic/claude-sonnet-4 | AI model to use |
SLACK_BOT_TOKEN | No | - | Slack bot token for notifications |
SLACK_CHANNEL_ID | No | - | Slack channel ID for summaries |
SF_CLIENT_ID | No | - | Salesforce Connected App client ID |
SF_USERNAME | No | - | Salesforce username |
SF_LOGIN_URL | No | https://login.salesforce.com | Salesforce login URL |
SF_PRIVATE_KEY_PEM | No | - | Salesforce private key (PEM format) |
Demo mode uses realistic mock data including a sample 20-minute product demo call. The demo files are organized in the /demo-files folder:
demo-files/├── webhook-data.json # Mock Gong webhook payload├── transcript.json # 20-minute call transcript└── context/├── gong-calls/previous/ # Historical calls│ ├── demo-call-000-discovery-call.md│ └── demo-call-intro-initial-call.md├── salesforce/ # CRM context│ ├── account.md│ ├── opportunity.md│ └── contacts.md├── research/ # Background info│ ├── company-research.md│ └── competitive-intel.md└── playbooks/└── sales-playbook.md
These files are loaded into the sandbox for the agent to explore.
By default, the agent uses claude-sonnet-4-20250514. You can change this via:
AI_MODEL=anthropic/claude-sonnet-4# orAI_MODEL=openai/gpt-4o
Override the default system prompt:
AGENT_SYSTEM_PROMPT="You are a sales call analyst..."
Enable Slack notifications by setting:
SLACK_BOT_TOKEN=xoxb-your-bot-tokenSLACK_CHANNEL_ID=C0123456789
The agent posts:
To add multiple channels: Modify lib/slack.ts to route based on call properties.
Enable CRM context by setting Salesforce credentials. The agent will enrich summaries with account data.
See CRM Customization for details on customizing fields or adding other CRMs.
Each step uses the "use step" directive for:
The agent uses bash-tool for exploring call transcripts via shell commands:
# List call filesls gong-calls/# Search for pricing discussionsgrep -r "pricing" gong-calls/# View call metadatacat gong-calls/metadata.json# Find objectionsgrep -i "concern\|issue\|problem" gong-calls/*.md
All bash commands are logged for observability:
[bash-tool] INFO: Bash command starting { command: 'grep -r "pricing" gong-calls/' }[bash-tool] INFO: Bash command completed { command: '...', exitCode: 0, stdoutLength: 605 }
The agent generates structured output:
{summary: string, // Comprehensive call summarytasks: [{taskDescription: string,taskOwner: string,ownerCompany: 'internal' | 'customer' | 'partner'}],objections: [{description: string,quote: string,speaker: string,speakerCompany: string,handled: boolean,handledAnswer: string,handledScore: number, // 0-100handledBy: string}],slackSummary: string, // TL;DR for SlackslackDetails: string // Detailed thread reply}
Add playbook detection by configuring config.playbooks in lib/config.ts.
The agent supports optional CRM integration to enrich call context. By default, Salesforce is supported, but you can customize fields or add other CRMs.
Adding a Different CRM (HubSpot, Pipedrive, etc.)lib/hubspot.ts):export function isHubSpotEnabled(): boolean {return !!process.env.HUBSPOT_API_KEY;}export async function getAccountData(companyId: string): Promise<{accountData: Record<string, unknown> | null;}> {// Implement your CRM's API calls}
lib/config.ts:hubspot: {enabled: !!process.env.HUBSPOT_API_KEY,apiKey: process.env.HUBSPOT_API_KEY || '',},
lib/sandbox-context.ts:import { getAccountData, isHubSpotEnabled } from './hubspot';// In generateFilesForSandbox():if (isHubSpotEnabled() && options.hubspotCompanyId) {const { accountData } = await getAccountData(options.hubspotCompanyId);// Write to sandbox...}
workflows/gong-summary/index.ts:Disabling CRM Integration// Gong may include CRM context from integrationsconst hubspotCompanyId = data.callData.context?.find((c) => c.system === 'HubSpot')?.objects?.find((o) => o.objectType === 'Company')?.objectId;
Simply don't set the SF_* environment variables. The integration checks isSalesforceEnabled() before making any API calls.
# Install dependenciesnpm install# Run development servernpm run dev# Build for productionnpm run build
sales-call-summary-agent/├── app/│ ├── api/gong-webhook/ # Webhook endpoint│ ├── layout.tsx│ └── page.tsx # Status page├── demo-files/ # Demo mode files│ ├── webhook-data.json│ ├── transcript.json│ └── context/ # Additional context files├── lib/│ ├── agent.ts # ToolLoopAgent configuration│ ├── config.ts # Centralized configuration│ ├── gong-client.ts # Gong API helpers│ ├── mock-data.ts # Demo mode loader│ ├── salesforce.ts # Optional Salesforce integration│ ├── slack.ts # Optional Slack integration│ ├── sandbox-context.ts # File generation for sandbox│ ├── tools.ts # Agent tools (bash-tool)│ ├── types.ts # TypeScript types│ └── logger.ts # Logging utility└── workflows/└── gong-summary/├── index.ts # Main workflow└── steps.ts # Workflow steps
Receives Gong webhook payloads and triggers the summary workflow.
Request Body: Gong webhook payload or empty {} in demo mode.
Response:
{"message": "Workflow triggered","callId": "1234567890"}
Health check endpoint.
Response:
{"status": "ok","service": "sales-call-summary-agent","demoMode": true,"configValid": true,"configErrors": []}
The function returns output in the format agentOutputSchema (detailed in agent.ts). You can save this output in Slack.
Contributions are welcome! Please open an issue or submit a pull request.