Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1 +1 @@
web: python app.py
web: heroku-applink-service-mesh python app.py
142 changes: 134 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,162 @@
Creating Agentforce Custom Actions with Heroku - Python
========================================================

> 💡 **Heroku Integration Pilot:**<br/> These steps utilize generally availble features in Heroku and Salesforce. If you have joined the Heroku Integration pilot program please refer to these alternative [instructions](https://github.com/heroku-examples/heroku-agentforce-tutorial/tree/heroku-integration-pilot).
>
This tutorial explains how to deploy a Heroku application written in Python that can be used to build an Agentforce custom action, extending the capabilities of any Agentforce agent with the power of Heroku's fully managed, elastic compute services.

> **_IN A HURRY?_** This application has already been deployed publicly and is available at [https://agentforce-tutorial-python-7894e9215571.herokuapp.com/](https://agentforce-tutorial-python-7894e9215571.herokuapp.com/), allowing you to skip straight to [configuring Heroku-based actions in your Salesforce organization](https://github.com/heroku-examples/heroku-agentforce-tutorial?tab=readme-ov-file#step-2---creating-a-named-credential) to try it out first.

## Prerequisites

**Salesforce Org Requirements:**
- Use a **Salesforce Developer Edition org** (not Trailhead Playground)
- Ensure you have access to Agentforce by searching for `Agents` in the `Setup` menu
- If needed, get a free [Salesforce Developer Edition org here](https://developer.salesforce.com/signup)
- Enable Einstein and Agentforce in `Einstein Setup` under the `Setup` menu

**Network Requirements:**
- **Disable VPN connections** during setup - they interfere with OAuth flows
- Ensure you have a stable internet connection for the authentication process

App Authentication
------------------

Regardless of how you access this app, you will need to complete or configure basic authentication. We have included this as a reminder that best practice is to always consider authentication for APIs, especially those involved in AI interactions like this. For APIs in general, it is typical to use JWT-based authentication. For the basic authentication setup here, the default username is `heroku`, and the password is `agent`.

> **WARNING**: Carefully review your app authentication needs and requirements before deploying to production.

Deploying to Heroku
-------------------
Deploying to Heroku and Connecting to Salesforce
-------------------------------------------------

### Step 1: Deploy to Heroku

You can deploy this application to your Heroku account using the button below or manually via the CLI.

[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/heroku-examples/heroku-agentforce-tutorial-python)

To proceed with a CLI deployment, install the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli) and log in with your Heroku account (or [sign up](https://signup.heroku.com/)). Then, execute the following CLI commands:

```
```bash
git clone https://github.com/heroku-examples/heroku-agentforce-tutorial-python
cd heroku-agentforce-tutorial-python
heroku create myagentaction
heroku create your-app-name # Choose a unique name
git push heroku main
```

Once this has been deployed, take note of the web URL and then refer to the instructions in [configuring Heroku-based actions in your Salesforce organization](https://github.com/heroku-examples/heroku-agentforce-tutorial?tab=readme-ov-file#step-2---creating-a-named-credential).
### Step 2: Set Up Heroku AppLink Integration

**Add Heroku AppLink addon:**
```bash
heroku addons:create heroku-applink
```

**Configure the application ID:**
```bash
heroku config:set HEROKU_APP_ID="$(heroku apps:info --json | jq -r '.app.id')"
```

> 💡 **jq utility:** If you don't have the `jq` utility, run `heroku apps:info --json` manually and extract the value from the `app.id` field.

**Add the Heroku AppLink Service Mesh buildpack:**
```bash
heroku buildpacks:add https://github.com/heroku/heroku-buildpack-heroku-applink-service-mesh
```

**Deploy the updated configuration:**
```bash
git commit --allow-empty -m "Add AppLink configuration"
git push heroku main
```

### Step 3: Connect to Your Salesforce Org

**Important:** Make sure you're using a Salesforce Developer Edition org and have disabled any VPN connections.

```bash
heroku salesforce:connect your-connection-name -a your-app-name --addon your-applink-addon-name
```

To find your addon name, run: `heroku addons` and look for the `heroku-applink` entry.

Example:
```bash
heroku salesforce:connect my-salesforce-org -a my-badge-app --addon applink-example-12345
```

### Step 4: Publish Your API Specification

```bash
heroku salesforce:publish api-spec.json --client-name BadgeService --connection-name your-connection-name --authorization-connected-app-name BadgeServiceConnectedApp --authorization-permission-set-name BadgeServicePermissions -a your-app-name --addon your-applink-addon-name
```

**Verify the publication worked:**
```bash
heroku salesforce:publications
```

You should see your connection listed with a "Connected" status.

## Troubleshooting

### Common Issues and Solutions

**VPN Interference:**
- **Problem**: Connection fails with "Invalid record" or "UNTRUSTED_CALLER" errors
- **Solution**: Disable VPN connections during the setup process. VPNs interfere with OAuth flows.

**Port Configuration Issues:**
- **Problem**: App crashes with "Address already in use" errors in logs
- **Solution**: The app is already configured to use port 3000 when AppLink service mesh is enabled. If you modify the port logic, ensure it uses port 3000 when `HEROKU_APPLINK_TOKEN` environment variable is present.

**Connection Timeout:**
- **Problem**: Browser shows successful authentication but CLI shows timeout
- **Solution**: This is normal behavior. Check `heroku salesforce:publications` to verify the connection worked.

**Explicit Parameters Required:**
- **Problem**: Commands fail with ambiguous errors
- **Solution**: Always specify explicit app and addon parameters:
```bash
heroku salesforce:connect connection-name -a your-app-name --addon your-addon-name
```

**API Spec File Missing:**
- **Problem**: "The API spec file path api-spec.json doesn't exist"
- **Solution**: Ensure you have the `api-spec.json` file in your project directory. It should be created automatically, but if missing, it describes your `/process` endpoint.

### Getting Help

If you continue to experience issues:
1. Check `heroku logs --tail` for application errors
2. Verify your Salesforce org has Agentforce enabled
3. Ensure all config variables are set: `heroku config`
4. Check connection status: `heroku salesforce:publications`

### Important: Heroku AppLink CLI Configuration

To use Heroku AppLink features with the CLI, you need to install the AppLink plugin:

```bash
heroku plugins:install @heroku-cli/plugin-applink
```

This plugin provides the necessary commands for working with AppLink add-ons and Salesforce connections.

**Alternative: Environment Variable Workaround**

If you encounter errors referencing the old add-on name `heroku-integration`, you can also set the following environment variable:

```bash
export HEROKU_INTEGRATION_ADDON=heroku-applink
```

**For permanent setup, add this to your shell profile:**
- **macOS/Linux**: Add `export HEROKU_INTEGRATION_ADDON=heroku-applink` to your `~/.zshrc` or `~/.bashrc`
- **Windows**: Set the environment variable in your system settings

After installing the plugin or setting the environment variable, you can successfully run:
```bash
heroku addons:create heroku-applink -a your-app-name
heroku salesforce:connect your-org -a your-app-name
```

Running and Testing Locally
---------------------------
Expand Down
78 changes: 78 additions & 0 deletions api-spec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
{
"openapi": "3.0.0",
"info": {
"title": "Badge Service API",
"description": "API for generating Heroku badges with custom names",
"version": "1.0.0"
},
"servers": [
{
"url": "https://myagentaction-ben.herokuapp.com",
"description": "Heroku deployment"
}
],
"paths": {
"/process": {
"post": {
"summary": "Generate a badge",
"description": "Generates a Heroku badge with the provided name",
"operationId": "generateBadge",
"security": [
{
"basicAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name to be placed on the badge",
"example": "Astro"
}
},
"required": ["name"]
}
}
}
},
"responses": {
"200": {
"description": "Badge generated successfully",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "HTML fragment containing the generated badge"
}
}
}
}
}
},
"400": {
"description": "Invalid request - name field is required"
},
"401": {
"description": "Authentication required"
}
}
}
}
},
"components": {
"securitySchemes": {
"basicAuth": {
"type": "http",
"scheme": "basic"
}
}
}
}
42 changes: 32 additions & 10 deletions app.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,33 @@
{
"name": "Creating Agentforce Custom Actions with Heroku - Python",
"description": "This tutorial explains how to deploy a Heroku application written in Python that can be used to build an Agentforce custom action, extending the capabilities of any Agentforce agent with the power of Heroku's fully managed, elastic compute services.",
"repository": "https://github.com/heroku-examples/heroku-agentforce-tutorial-python",
"keywords": [
"python",
"openapi",
"flask",
"agentforce"
]
}
"name": "Creating Agentforce Custom Actions with Heroku - Python",
"description": "This tutorial explains how to deploy a Heroku application written in Python that can be used to build an Agentforce custom action, extending the capabilities of any Agentforce agent with the power of Heroku's fully managed, elastic compute services.",
"repository": "https://github.com/heroku-examples/heroku-agentforce-tutorial-python",
"keywords": [
"python",
"openapi",
"flask",
"agentforce"
],
"buildpacks": [
{
"url": "heroku/python"
}
],
"formation": {
"web": {
"quantity": 1,
"size": "standard-1x"
}
},
"env": {
"FLASK_ENV": {
"description": "Flask environment setting",
"value": "production"
},
"PYTHON_VERSION": {
"description": "Python version to use",
"value": "3.12.11"
}
},
"stack": "heroku-24"
}
9 changes: 7 additions & 2 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ def post(self):
"""
Entry point for the application. Starts the Flask server and runs the application.
"""
# Use the PORT environment variable if present, otherwise default to 5000
port = int(os.environ.get('PORT', 5000))
# When using service mesh, app should run on port 3000, otherwise use PORT env var
if 'HEROKU_APPLINK_TOKEN' in os.environ:
# Running with AppLink service mesh - use port 3000
port = 3000
else:
# Running without service mesh - use PORT env var
port = int(os.environ.get('PORT', 5000))
app.run(debug=True, host='0.0.0.0', port=port)