diff --git a/Procfile b/Procfile index e6cb5ad..752f1a4 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -web: python app.py \ No newline at end of file +web: heroku-applink-service-mesh python app.py \ No newline at end of file diff --git a/README.md b/README.md index cbf4b42..1af35cd 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,22 @@ Creating Agentforce Custom Actions with Heroku - Python ======================================================== -> 💡 **Heroku Integration Pilot:**
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 ------------------ @@ -15,23 +25,139 @@ Regardless of how you access this app, you will need to complete or configure ba > **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 --------------------------- diff --git a/api-spec.json b/api-spec.json new file mode 100644 index 0000000..c7f60ee --- /dev/null +++ b/api-spec.json @@ -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" + } + } + } +} diff --git a/app.json b/app.json index f23d9d3..506e94c 100644 --- a/app.json +++ b/app.json @@ -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" - ] - } \ No newline at end of file + "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" +} \ No newline at end of file diff --git a/app.py b/app.py index cd37b02..e9ea186 100644 --- a/app.py +++ b/app.py @@ -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)