mirror of
https://github.com/james-m-jordan/openai-cookbook.git
synced 2025-05-09 19:32:38 +00:00
Gpt action salesforce gong (#1761)
Co-authored-by: pap <pap@openai.com>
This commit is contained in:
parent
e82d689fc6
commit
fc24b1c2b1
@ -0,0 +1,446 @@
|
||||
# GPT Action Library: Salesforce + Gong
|
||||
|
||||
## Introduction
|
||||
|
||||
This page provides an instruction & guide for developers building middleware to connect a GPT Action to a specific application. Before you proceed, make sure to first familiarize yourself with the following information:
|
||||
|
||||
- [Introduction to GPT Actions](https://platform.openai.com/docs/actions)
|
||||
- [Introduction to GPT Actions Library](https://platform.openai.com/docs/actions/actions-library)
|
||||
- [Example of Building a GPT Action from Scratch](https://platform.openai.com/docs/actions/getting-started)
|
||||
|
||||
This particular GPT Action provides an overview of how to build a GPT that retrieves information from Salesforce and Gong. This will include creating multiple custom actions which are documented in existing cookbooks. We will highlight these cookbooks in the next section.
|
||||
|
||||
### Value + Example Business Use Cases
|
||||
|
||||
**Value**: Users can now leverage ChatGPT's capabilities to:
|
||||
|
||||
- Connect to Salesforce
|
||||
- Search for customer accounts
|
||||
- Retrieve Gong transcripts from previous calls
|
||||
|
||||
**Example Use Cases**:
|
||||
|
||||
A sales rep is preparing for an upcoming customer meeting. Using this integration, they can quickly retrieve relevant account details from Salesforce, access recent Gong call transcripts, and receive AI-generated summaries and insights structured around proven sales methodologies like MEDPICC or SPICED. This empowers the rep with a clear, actionable understanding of the customer's current state and next steps — all in minutes
|
||||
|
||||
## Application Information
|
||||
In this example, we are connecting to Salesforce and Gong (via a middleware). We are going to refer to existing cookbooks for basic setup and authentication instructions for Salesforce and creating a middleware.
|
||||
|
||||
### Salesforce GPT Action
|
||||
|
||||
Refer to our cookbook on setting up a GPT Action for Salesforce. The two settings to pay attention to in that cookbook are:
|
||||
|
||||
- [Application Information](https://cookbook.openai.com/examples/chatgpt/gpt_actions_library/gpt_action_salesforce#application-information) - this covers the necessary concepts to be familiar with in Salesforce
|
||||
- [Authentication Instructions](https://cookbook.openai.com/examples/chatgpt/gpt_actions_library/gpt_action_salesforce#authentication-instructions) - this covers creating a Connected App in Salesforce and configuring OAuth (on both Salesforce and ChatGPT)
|
||||
|
||||
### Middleware GPT Action
|
||||
Refer to any one of our cookbooks on creating a middleware:
|
||||
|
||||
- [GPT Actions library (Middleware) - AWS](https://cookbook.openai.com/examples/chatgpt/gpt_actions_library/gpt_middleware_aws_function)
|
||||
- [GPT Actions library (Middleware) - Azure Functions](https://cookbook.openai.com/examples/chatgpt/gpt_actions_library/gpt_middleware_azure_function)
|
||||
- [GPT Actions library (Middleware) - Google Cloud Function](https://cookbook.openai.com/examples/chatgpt/gpt_actions_library/gpt_middleware_google_cloud_function)
|
||||
|
||||
### Application Prerequisites
|
||||
|
||||
In addition to the prerequisites in the cookbooks above, please ensure that you have access to a Gong API key
|
||||
|
||||
## Application Setup
|
||||
|
||||
### Deploying a serverless function
|
||||
|
||||
This serverless function will accept an array of `callIds`, fetch the transcripts from Gong and clean up the response that it sends to ChatGPT. Here is an example of what it looks like on Azure Functions (Javascript)
|
||||
|
||||
```javascript
|
||||
const { app } = require('@azure/functions');
|
||||
const axios = require('axios');
|
||||
|
||||
// Replace with your Gong API token
|
||||
const GONG_API_BASE_URL = "https://api.gong.io/v2";
|
||||
const GONG_API_KEY = process.env.GONG_API_KEY;
|
||||
|
||||
app.http('callTranscripts', {
|
||||
methods: ['POST'],
|
||||
authLevel: 'function',
|
||||
handler: async (request, context) => {
|
||||
try {
|
||||
const body = await request.json();
|
||||
const callIds = body.callIds;
|
||||
|
||||
if (!Array.isArray(callIds) || callIds.length === 0) {
|
||||
return {
|
||||
status: 400,
|
||||
body: "Please provide call IDs in the 'callIds' array."
|
||||
};
|
||||
}
|
||||
|
||||
// Fetch call transcripts
|
||||
const transcriptPayload = { filter: { callIds } };
|
||||
const transcriptResponse = await axios.post(`${GONG_API_BASE_URL}/calls/transcript`, transcriptPayload, {
|
||||
headers: {
|
||||
'Authorization': `Basic ${GONG_API_KEY}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
const transcriptData = transcriptResponse.data;
|
||||
|
||||
// Fetch extensive call details
|
||||
const extensivePayload = {
|
||||
filter: { callIds },
|
||||
contentSelector: {
|
||||
exposedFields: { parties: true }
|
||||
}
|
||||
};
|
||||
|
||||
const extensiveResponse = await axios.post(`${GONG_API_BASE_URL}/calls/extensive`, extensivePayload, {
|
||||
headers: {
|
||||
'Authorization': `Basic ${GONG_API_KEY}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
const extensiveData = extensiveResponse.data;
|
||||
|
||||
// Create a map of call IDs to metadata and speaker details
|
||||
const callMetaMap = {};
|
||||
extensiveData.calls.forEach(call => {
|
||||
callMetaMap[call.metaData.id] = {
|
||||
title: call.metaData.title,
|
||||
started: call.metaData.started,
|
||||
duration: call.metaData.duration,
|
||||
url: call.metaData.url,
|
||||
speakers: {}
|
||||
};
|
||||
|
||||
call.parties.forEach(party => {
|
||||
callMetaMap[call.metaData.id].speakers[party.speakerId] = party.name;
|
||||
});
|
||||
});
|
||||
|
||||
// Transform transcript data into content and include metadata
|
||||
transcriptData.callTranscripts.forEach(call => {
|
||||
const meta = callMetaMap[call.callId];
|
||||
if (!meta) {
|
||||
throw new Error(`Metadata for callId ${call.callId} not found.`);
|
||||
}
|
||||
|
||||
let content = '';
|
||||
call.transcript.forEach(segment => {
|
||||
const speakerName = meta.speakers[segment.speakerId] || "Unknown Speaker";
|
||||
|
||||
// Combine all sentences for the speaker into a paragraph
|
||||
const sentences = segment.sentences.map(sentence => sentence.text).join(' ');
|
||||
content += `${speakerName}: ${sentences}\n\n`; // Add a newline between speaker turns
|
||||
});
|
||||
|
||||
// Add metadata and content to the call object
|
||||
call.title = meta.title;
|
||||
call.started = meta.started;
|
||||
call.duration = meta.duration;
|
||||
call.url = meta.url;
|
||||
call.content = content;
|
||||
|
||||
delete call.transcript;
|
||||
});
|
||||
|
||||
// Return the modified transcript data
|
||||
return {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(transcriptData)
|
||||
};
|
||||
} catch (error) {
|
||||
context.log('[ERROR]', "Error processing request:", error);
|
||||
|
||||
return {
|
||||
status: error.response?.status || 500,
|
||||
body: {
|
||||
message: "An error occurred while fetching or processing call data.",
|
||||
details: error.response?.data || error.message
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
Here are the dependencies that you would include in your `package.json` file
|
||||
|
||||
```javascript
|
||||
"dependencies": {
|
||||
"@azure/functions": "^4.0.0",
|
||||
"axios": "^1.7.7"
|
||||
}
|
||||
```
|
||||
|
||||
## ChatGPT Steps
|
||||
|
||||
### Custom GPT Instructions
|
||||
|
||||
Once you've created a Custom GPT, copy the text below in the Instructions panel. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.
|
||||
|
||||
```
|
||||
# Trigger
|
||||
User enters the name of an account that they want to prepare for
|
||||
|
||||
# Steps
|
||||
1. Retrieve Account Names - Make a call to the `executeSOSLSearch` custom action searching for a Salesforce Account with that name (SOSL). Retrieve up to 5 accounts. This is what the query should look like - `FIND {Acme} IN ALL FIELDS RETURNING Account(Id, Name) LIMIT 5`
|
||||
|
||||
2. Show the accounts in this format - `Account Name - salesforceID`. Ask the user to confirm which account they are interested in.
|
||||
|
||||
3. Get Gong Call IDs for the account - For the confirmed account, make a call to `executeSOQLQuery` to get all the Gong Call IDs. It should look like this - `SELECT XXX, YYY, ZZZ
|
||||
FROM Gong__Gong_Call__c
|
||||
WHERE Gong__Primary_Account__c = '<AccountId>'
|
||||
ORDER BY Gong__Call_Start__c DESC
|
||||
LIMIT 2
|
||||
`
|
||||
|
||||
4. Pass in the callIds to `getTranscriptsByCallIds `
|
||||
|
||||
# Trigger
|
||||
User says "Summarize call"
|
||||
|
||||
# Steps
|
||||
|
||||
Use both the transcripts and provide the following output
|
||||
|
||||
## Account Name
|
||||
Print out the account name
|
||||
|
||||
## Details of calls
|
||||
>Please list the calls for which you retrieved the transcripts along with their dates and attendees in this table format:
|
||||
>>Headers: <Title of Call>, <Date>, <Attendees>, <Gong URL>
|
||||
|
||||
## Recommended Meeting Focus Areas:
|
||||
>Analyze the transcripts to identify themes, challenges, and opportunities. Based on this, generate a list of recommended focus areas for the next meeting. These should be actionable and specific to the client’s needs. Explain **why** each item should be a meeting focus.
|
||||
|
||||
For each of the following insights, specify **which call and date** you sourced the insight from:
|
||||
|
||||
### Metrics
|
||||
Quantifiable outcomes the customer is trying to achieve. These could be cost reduction, increased revenue, user growth, efficiency gains, etc. Look for KPIs or success measures mentioned.
|
||||
|
||||
### Economic Buyer
|
||||
Identify if the true economic decision-maker was mentioned or involved. This includes titles, names, or hints at budget ownership or final authority.
|
||||
|
||||
### Decision Criteria
|
||||
What are the key factors the customer will use to evaluate solutions? These could include price, performance, support, integrations, ease of use, etc.
|
||||
|
||||
### Decision Process
|
||||
Describe how the customer plans to make the buying decision: stages, stakeholders involved, approval processes, timelines.
|
||||
|
||||
### Paper Process
|
||||
Any mention of legal, procurement, compliance, or contract-related steps and timelines should be captured here.
|
||||
|
||||
### Identify Pain
|
||||
Highlight the core business challenges the customer is facing, ideally in their own words. Understand what’s driving urgency.
|
||||
|
||||
### Champion
|
||||
Is there someone internally who is championing our solution? Mention names, roles, or behaviors that indicate advocacy (e.g., “I’m pushing this internally”).
|
||||
|
||||
### (Optional) Competition
|
||||
Mention any competing vendors, internal builds, or alternative solutions discussed.
|
||||
```
|
||||
In the above example, replace the query in (3) to retrieves the Gong Call IDs from your custom Salesforce object.
|
||||
|
||||
You will now create 2 separate actions - one to connect to Salesforce and the other to connect to the middleware that calls the Gong APIs
|
||||
|
||||
### OpenAPI Schema for Salesforce custom action
|
||||
|
||||
Once you've created a Custom GPT, copy the text below in the Actions panel. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.
|
||||
|
||||
Below is an example of what connecting to Salesforce might look like. You'll need to insert your URL in this section.
|
||||
|
||||
```javascript
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: Salesforce API
|
||||
version: 1.0.0
|
||||
description: API for accessing Salesforce sObjects and executing queries.
|
||||
servers:
|
||||
- url: https://<subdomain>.my.salesforce.com/services/data/v59.0
|
||||
description: Salesforce API server
|
||||
paths:
|
||||
/query:
|
||||
get:
|
||||
summary: Execute a SOQL Query
|
||||
description: Executes a given SOQL query and returns the results.
|
||||
operationId: executeSOQLQuery
|
||||
parameters:
|
||||
- name: q
|
||||
in: query
|
||||
description: The SOQL query string to be executed.
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Query executed successfully.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/QueryResult'
|
||||
|
||||
/search:
|
||||
get:
|
||||
summary: Execute a SOSL Search
|
||||
description: Executes a SOSL search based on the given query and returns matching records.
|
||||
operationId: executeSOSLSearch
|
||||
parameters:
|
||||
- name: q
|
||||
in: query
|
||||
description: The SOSL search string (e.g., 'FIND {Acme}').
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Search executed successfully.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SearchResult'
|
||||
|
||||
components:
|
||||
schemas:
|
||||
QueryResult:
|
||||
type: object
|
||||
description: Result of a SOQL query.
|
||||
properties:
|
||||
totalSize:
|
||||
type: integer
|
||||
description: The total number of records matching the query.
|
||||
done:
|
||||
type: boolean
|
||||
description: Indicates if the query result includes all records.
|
||||
records:
|
||||
type: array
|
||||
description: The list of records returned by the query.
|
||||
items:
|
||||
$ref: '#/components/schemas/SObject'
|
||||
|
||||
SearchResult:
|
||||
type: object
|
||||
description: Result of a SOSL search.
|
||||
properties:
|
||||
searchRecords:
|
||||
type: array
|
||||
description: The list of records matching the search query.
|
||||
items:
|
||||
$ref: '#/components/schemas/SObject'
|
||||
|
||||
SObject:
|
||||
type: object
|
||||
description: A Salesforce sObject, which represents a database table record.
|
||||
properties:
|
||||
attributes:
|
||||
type: object
|
||||
description: Metadata about the sObject, such as type and URL.
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
description: The sObject type.
|
||||
url:
|
||||
type: string
|
||||
description: The URL of the record.
|
||||
Id:
|
||||
type: string
|
||||
description: The unique identifier for the sObject.
|
||||
additionalProperties: true
|
||||
```
|
||||
|
||||
### Authentication instructions for Salesforce custom actions
|
||||
Please follow the steps shown in [GPT Actions library - Salesforce](https://cookbook.openai.com/examples/chatgpt/gpt_actions_library/gpt_action_salesforce#in-chatgpt)
|
||||
|
||||
### OpenAPI Schema for the middleware that connects to Gong
|
||||
In this example, we are setting this up for an Azure Function that calls the Gong APIs. Replace `url` with your own Middleware URL
|
||||
|
||||
```
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: Call Transcripts API
|
||||
description: API to retrieve call transcripts and associated metadata by specific call IDs.
|
||||
version: 1.0.1
|
||||
servers:
|
||||
- url: https://<subdomain>.azurewebsites.net/api
|
||||
description: Production server
|
||||
paths:
|
||||
/callTranscripts:
|
||||
post:
|
||||
operationId: getTranscriptsByCallIds
|
||||
x-openai-isConsequential: false
|
||||
summary: Retrieve call transcripts by call IDs
|
||||
description: Fetches specific call transcripts based on the provided call IDs in the request body.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
callIds:
|
||||
type: array
|
||||
description: List of call IDs for which transcripts need to be fetched.
|
||||
items:
|
||||
type: string
|
||||
required:
|
||||
- callIds
|
||||
responses:
|
||||
'200':
|
||||
description: A successful response containing the requested call transcripts and metadata.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
requestId:
|
||||
type: string
|
||||
description: Unique request identifier.
|
||||
records:
|
||||
type: object
|
||||
description: Metadata about the pagination.
|
||||
properties:
|
||||
totalRecords:
|
||||
type: integer
|
||||
description: Total number of records available.
|
||||
currentPageSize:
|
||||
type: integer
|
||||
description: Number of records in the current page.
|
||||
currentPageNumber:
|
||||
type: integer
|
||||
description: The current page number.
|
||||
callTranscripts:
|
||||
type: array
|
||||
description: List of call transcripts.
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
callId:
|
||||
type: string
|
||||
description: Unique identifier for the call.
|
||||
title:
|
||||
type: string
|
||||
description: Title of the call or meeting.
|
||||
started:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Timestamp when the call started.
|
||||
duration:
|
||||
type: integer
|
||||
description: Duration of the call in seconds.
|
||||
url:
|
||||
type: string
|
||||
format: uri
|
||||
description: URL to access the call recording or details.
|
||||
content:
|
||||
type: string
|
||||
description: Transcript content of the call.
|
||||
'400':
|
||||
description: Invalid request. Possibly due to missing or invalid `callIds` parameter.
|
||||
'401':
|
||||
description: Unauthorized access due to invalid or missing API key.
|
||||
'500':
|
||||
description: Internal server error.
|
||||
```
|
||||
|
||||
|
||||
*Are there integrations that you’d like us to prioritize? Are there errors in our integrations? File a PR or issue in our github, and we’ll take a look.*
|
@ -1895,3 +1895,13 @@
|
||||
- audio
|
||||
- speech
|
||||
|
||||
- title: GPT Actions library - Salesforce & Gong
|
||||
path: examples/chatgpt/gpt_actions_library/gpt_action_salesforce_gong.md
|
||||
date: 2025-04-07
|
||||
authors:
|
||||
- girishd
|
||||
tags:
|
||||
- chatgpt
|
||||
- gpt-actions-library
|
||||
- chatgpt-productivity
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user