Custom integrations let you connect any API-enabled tool to an assistant. This opens up endless possibilities. Below you find a short introduction of how build it. We will use the example of our Google Calendar integration.
Integrations are standardized connections between Langdock and third-party tools that handle authentication and API communication. Within each integration, you can build actions that let assistants interact with specific API endpoints. Here’s how to create an integration and set up ready-to-use actions.
Next, specify an integration name and upload an icon (shown in chat when using actions and in the integrations overview). Add a description to help assistants know when to use this integration. Hit Save to create it.
After selecting API Key authentication, add custom input fields in step 2 (like API key or client ID). These inputs are collected when users set up connections and can be marked as “required.”
Step 3 lets you set up a test API endpoint to validate authentication. Replace the URL parameter and add references to your input fields using data.auth.fieldId.
Use the built-in ld.request and ld.log functions for requests and logging.
Test your action and create your first connection.
Custom integrations support OAuth 2.0 authentication.
Step 2 allows custom input fields (collected during connection setup). Client ID and Client Secret are entered in step 4, so this covers additional parameters only.
Create an OAuth client
Set up an OAuth client/App/Project in your target application and enable the required APIs. This is application-specific, which is why our interface supports custom code in step 5.
For Google Calendar, create a Google Service Account, generate a new key to get the client ID and secret, add them to Langdock in step 4, save the OAuth Redirect URL, and enable the Google Calendar API.
Change Authorization URL
Check the OAuth documentation for your service and extract the Authorization URL. Usually, changing the BASE_URL in our template is sufficient.
Provide a test API endpoint (like /me) to verify authentication. The return value of that test request can be used inside the OAuth Client Label to influence the naming of the established connections. You can access the return value via: {{data.input}}
For Google Calendar: Google Sheets - {{data.input.useremail.value}}
Test by adding a connection and verifying the authorization flow works.
Use data.input.{inputFieldId} for input field values and data.auth.{authenticationFieldId} for authentication field values from the user’s current connection.
The custom client library ld contains the core functionality needed for implementing authentication flows.
ld.request() creates a web request using the format specified by the passed object and returns the response. The parameters must be valid JSON objects since JSON.stringify() is called internally. For complex JSON objects, you’ll need to apply JSON.parse() first.
ld.log() outputs the passed values to the Logs field, which appears below the Test Action button after running an action.
Example usage from the Google Calendar integration:
Both JSON.stringify() (converting a JavaScript JSON object into a string) and JSON.parse() (converting a string into a JavaScript JSON object) are available in custom code blocks.
The parameters passed to the ld.request() function must be valid JSON objects since JSON.stringify() is called internally. For complex JSON structures, you’ll need to apply JSON.parse() beforehand to ensure proper formatting.
Most API calls require specific internal IDs. The challenge is that assistants can’t guess these IDs, which creates a poor user experience when calling actions like “get specific contact in HubSpot” or “add event to specific calendar in Google Calendar.”
The solution: Create helper actions that retrieve and return these IDs to the assistant first. For example, our Get deal context function for HubSpot uses GET endpoints to gather internal IDs for available pipelines and stages. This enables assistants to use actions like Create deal or Update deal much more effectively since they now have the required context.
Native actions allow you to natively search and download files that aren’t stored locally on a user’s device. We’ve already built native actions for SharePoint, OneDrive, Google Drive, and Confluence. You can access these via the Select files button to search and attach files directly to Chat or Assistant Knowledge.
Attach files to the chat using native integrations.
Attach files to the Assistant knowledge by using a native integration.
Building native actions for other tools enables you to search and download files from those platforms in the same way.
To set up a native action, begin building your integration as usual. Add another action, and in Step 1 under Advanced, select either “Search files” or “Download file” as the action type.
Afterwards, you build the action as any other action, but your function needs to return a specific object structure. This ensures compatibility and enables assistants to handle files and search results correctly.
Depending on the action you select, your function must return a specific object structure. This ensures compatibility and enables assistants to handle files and search results correctly.
Search files: When building a native search integration, your function must return an array of objects matching the following schema:
The web URL where users can view or edit the file. This should be a direct link that opens the file in the source application (e.g., Google Docs editor, SharePoint viewer). Must be a valid HTTPS URL that the user can access with their credentials.
documentId
string
The unique identifier of the file in the source system. This ID is used internally to reference the file and should remain stable across searches. Can be any string format (UUID, numeric ID, etc.) as long as it uniquely identifies the file.
title
string
The display name of the file. This is what users will see in search results. Should include the file extension if relevant (e.g., “Report.pdf”, “Budget.xlsx”).
mimeType
string
The MIME type of the file. Used to determine the file type icon and category. Common values include: application/pdf, application/vnd.google-apps.document, application/vnd.openxmlformats-officedocument.wordprocessingml.document, text/plain, etc.
Information about who created the file. Helps users identify file ownership and origin.
author.id
string
Unique identifier of the author. Typically an email address or user ID in the source system.
author.name
string
Display name of the author. The human-readable name shown to users (e.g., “John Doe”).
lastSeenByUser
string
When the current user last viewed this file. ISO 8601 date string (e.g., “2024-01-15T10:30:00Z”). Used for “Recently viewed” sorting. Return null or omit if the user has never viewed the file.
createdDate
string
When the file was originally created. ISO 8601 date string. Helps users understand file age and sort by creation date.
lastModifiedByAnyone
string
When the file was last modified by any user. ISO 8601 date string. Critical for identifying recently updated content and collaborative work.
lastModifiedByUserId
object
Information about who last modified the file. Helps track recent changes in collaborative environments. Entire object should be omitted if any required sub-field is missing.
lastModifiedByUserId.id
string
Unique identifier of the last editor. Typically an email or user ID.
lastModifiedByUserId.name
string
Display name of the last editor. Human-readable name of who made the last changes.
lastModifiedByUserId.lastModifiedByUserIdDate
string
Timestamp of the last modification. ISO 8601 date string. Usually matches lastModifiedByAnyone.
parent
object
Information about the file’s location/container. Helps users understand file organization and navigate to parent folders.
parent.id
string
Unique identifier of the parent folder/container. Used for folder-based operations and navigation.
parent.title
string
Display name of the parent folder. Shown to help users understand file location (e.g., “Marketing Materials”, “Q1 Reports”).
parent.url
string
Web URL to view the parent folder. Direct link to open the folder in the source application.
parent.type
string
Type of parent container. Optional classifier (e.g., “folder”, “workspace”, “site”).
parent.driveId
string
Identifier of the drive/library containing the file. For services with multiple storage locations (e.g., SharePoint sites, Google Shared Drives).
parent.siteId
string
Identifier of the site containing the file. Specific to SharePoint and similar platforms with site-based organization.
parent.listId
string
Identifier of the list containing the file. For list-based storage systems.
parent.listItemId
string
Identifier of the list item associated with the file. For files attached to list items.
contentPreview
string
A text snippet from the file’s content. Provides context about file contents in search results. Should be plain text, typically 100-200 characters. Useful for showing relevant excerpts that match search queries. Set to null if content preview is not available.
The complete filename including extension. This is the name that will be used when saving the file. Should match the original filename from the source system (e.g., “Budget_2024.xlsx”, “Design_Final.pdf”). If the file doesn’t have an extension in the source, add the appropriate one based on mimeType.
mimeType
string
Yes
The MIME type identifying the file format. Determines how the file will be processed and what icon to display. Must be a valid MIME type (e.g., “application/pdf”, “image/png”, “text/plain”). For Google Workspace files, use the original MIME type, not the exported format’s type.
buffer
Buffer
Conditional
The binary content of the file as a Buffer. Required for binary files (PDFs, images, Office docs). The actual file data that will be saved. Can be provided as: native Buffer object, base64 encoded string, or object with format type:“Buffer”, data: [byte array].
url
string
Yes
The web URL to view/edit the file in its source application. Should be a direct link that opens the file when clicked (e.g., Google Drive viewer URL, SharePoint document URL). Used for users to access the original file and for reference tracking.
lastModified
string/Date
Yes
ISO 8601 timestamp of the file’s last modification. Indicates when the file content was last changed. Can be a Date object or ISO string like “2024-01-15T10:30:00Z”. Used for version tracking and determining file freshness.
data
any
No
Raw response data from the API call. Optional field that can include additional metadata from the source system. This is typically the raw JSON response and is used for debugging or accessing extra properties not mapped to other fields. Not processed by the system.
text
string
Conditional
The text content of the file as a UTF-8 string. Required for text-based files instead of buffer. Use for plain text, HTML, JSON, CSV, or any human-readable format. Should contain the complete file content. Cannot be used together with buffer.
Content Fields: You must provide either buffer OR text, never both:
Use buffer for: Images, PDFs, Office documents, videos, any binary format
Use text for: Plain text, HTML, source code, JSON, XML, any text format
Data Field: The data field is optional and typically contains the raw API response. It’s not used by the core system but can be helpful for:
Debugging integration issues
Preserving additional metadata
Passing through vendor-specific properties
MIME Type Accuracy: The mimeType must accurately reflect the content being returned:
For native Google Docs exported as HTML, still use “application/vnd.google-apps.document”
For converted files, use the original source MIME type, not the export format
File Naming: The fileName should:
Include the correct file extension
Match what users expect from the source system
Be sanitized to remove invalid filesystem characters
URL Requirements: The url must:
Be accessible with the user’s authentication
Open the file in the source application (not a download link)
Be a stable link that won’t expire quickly
Below you can find an example implementation for the native SharePoint Download file action.
Show SharePoint Example
Copy
Ask AI
async function downloadOneDriveFile() { try { // Construct the API path based on the input configuration const config = JSON.parse(data.input.parent); let apiPath = ''; if (config.listId && config.listItemId) { apiPath = `/sites/${config.siteId}/lists/${config.listId}/items/${data.input.itemId}/driveItem`; } else if (config.driveId) { apiPath = `/drives/${config.driveId}/items/${data.input.itemId}`; } else if (config.groupId) { apiPath = `/groups/${config.groupId}/drive/items/${data.input.itemId}`; } else if (config.userId) { apiPath = `/users/${config.userId}/drive/items/${data.input.itemId}`; } else if (config.siteId) { apiPath = `/sites/${config.siteId}/drive/items/${data.input.itemId}`; } else { throw new Error('Insufficient information to construct API path'); } // Make the request to get the file metadata including download URL const options = { method: 'GET', url: `https://graph.microsoft.com/v1.0${apiPath}`, headers: { 'Authorization': 'Bearer ' + data.auth.access_token, 'Accept': 'application/json', }, }; const response = await ld.request(options); if (response.json['@microsoft.graph.downloadUrl']) { const downloadUrl = response.json['@microsoft.graph.downloadUrl']; // Request to download the file content const contentOptions = { method: 'GET', url: downloadUrl, responseType: 'stream' }; const contentResponse = await ld.request(contentOptions); if (contentResponse.status !== 200) { throw new Error( `Error fetching file content: ${JSON.stringify(contentResponse)}` ); } return { fileName: response.json.name, mimeType: response.json.file.mimeType, buffer: contentResponse.buffer, url: response.json.webUrl, lastModified: response.json.lastModifiedDateTime, }; } else { throw new Error('Could not download file!'); } } catch (error) { ld.log('Error downloading item from OneDrive: ' + error.message); throw error; }}return downloadOneDriveFile();