In a previous blog post, we showed you how to extend the power of Agentforce and gain in productivity thanks to custom actions built with Apex or Flow. In this post, we’ll share an example of how you can implement two custom Apex actions that let you retrieve an invoice PDF file from a third-party accounting system (or more generally, a file from any external system) and share it publicly. What’s amazing is that you can achieve this with less than 200 lines of basic code.
About the use case
The following screenshot illustrates how such a solution would be useful when drafting an email to a customer that includes a link to their invoice.
A user would request an email draft that holds a public link to an invoice for an order. The agent would then fetch the document from the third-party system and respond with an email draft that includes a public link to the document.
Before diving into the implementation details, here’s an annotated diagram that outlines the key steps of how such a use case would unfold.
- The user writes a prompt. The agent identifies the conversation’s topic and builds a plan to respond.
- The agent starts by running our custom Get Invoice action.
- The custom action makes a REST API call to the third-party accounting system to retrieve the invoice PDF file.
- The custom action stores the PDF as a Salesforce document.
- The agent calls the second Get Public Link custom action.
- The custom action creates a publicly shareable link for the invoice.
- The agent returns the public link to the invoice PDF file.
Now that we’ve identified the key steps, let’s take a look at the implementation of the first action that retrieves the invoice from the accounting system.
Retrieve file from a third-party system
In this example, we assume that the data for the invoice that we’re going to fetch is hosted by a third-party accounting system. We’ll call a REST API from the third-party system with our custom Apex agent action to retrieve the invoice PDF.
We start by configuring an Accounting_Service
external credential to identify to our remote host and authenticate our API call.
Then, we use Apex to make our HTTP GET call to fetch the invoice PDF file from the accounting system’s REST API.
Once we retrieve the binary content of our PDF as a Blob
, we create a new document version (a ContentVersion
record). Note that the Apex code below and in the second action is bulkified, so that it can also be used in a flow and does not hit governor limits.
You may have noticed that we didn’t create the document beforehand. Instead, we create a first version directly. Behind the scenes, the Salesforce Platform creates the document (ContentDocument
record) and attaches the first version to it. This is why we need to fetch the parent document ID, so that action returns it.
There are two important limitations to this approach:
- This implementation can not handle files that are larger than the Apex heap size limit. Consider using a middleware platform like Heroku to process files via APIs.
- Storing documents on the Salesforce Platform consumes data storage, and you’ll need to schedule some regular cleanup so that you org does not run out of space over time. Consider using Data Cloud for scalability and archival purposes.
Share file publicly
Salesforce allows you to share documents publicly with the ContentDistribution
object (see docs). This object is tied to a ContentVersion
(a version of a document). ContentDistribution
provides flexible options for sharing documents, such as:
- The generation of a publicly-accessible URL to serve the document
- A configurable expiry date
- An optional password protection (and the generation of the related password)
- The ability to be notified when the document is accessed
- The ability to track view count
Our custom Agentforce action requires the document ID and allows for several options, such as a custom expiry date and an optional password protection. Thanks to the power of Agentforce, these options are set at the conversation level based on the user prompt.
Then, our Apex custom action builds a ContentDistribution
record.
Before returning the link information from the action, there’s one extra step that is required which easy to overlook: we need to re-fetch the ContentDistribution
record that we just inserted. The reason why this is required is that we need to obtain the generated public URL and password (if the user chose to password-protect the file).
Conclusion
That’s a wrap — you saw how you can build custom Agentforce actions with Apex to fetch files from a third-party system and distribute them with publicly accessible URLs. You can combine these actions with an email drafting action to obtain powerful plans and boost your users’ productivity, thanks to the power of Agentforce. Check out the sample GitHub repository to explore the source code and give it a try.
Resources
- GitHub: Sample code
- Blog post: Build Custom Agent Actions Using Apex
- Documentation: External credentials
- Documentation ContentDistribution object
About the author
Philippe Ozil is a Principal Developer Advocate at Salesforce, where he focuses on the Salesforce Platform. He writes technical content and speaks frequently at conferences. He is a full-stack developer and enjoys working with APIs, DevOps, robotics, and VR projects. Follow him on X and LinkedIn, or check his GitHub projects.