Running Bots on Fission | Medplum

On this page

Medplum Bots provide powerful automation capabilities within your Medplum environment. While Medplum offers a built-in execution environment for bots, this page details how to deploy and manage your Medplum Bots using Fission, an open-source, Kubernetes-native serverless framework. This approach can be beneficial for organizations seeking advanced scalability, custom runtime environments, or deeper integration with existing Kubernetes infrastructure.

What are Medplum Bots?

Medplum bots are JavaScript code snippets that automate workflows within Medplum by reacting to changes in healthcare data (FHIR resources) and performing operations like data validation, notifications, or integrations. They are a core component of building dynamic and responsive healthcare applications on Medplum.

What is Fission?

Fission.io is an open-source, Kubernetes-native serverless framework that allows developers to deploy and run short-lived functions in any language, triggered by various events, without having to manage the underlying container infrastructure. It seamlessly integrates with Kubernetes, leveraging its orchestration capabilities for efficient function execution and scaling.

This guide focuses on setting up the necessary infrastructure to run Medplum Bots as Fission functions. It covers the configuration, deployment, and management of these serverless functions, enabling them to respond to events originating from your Medplum instance.

Fission Router Configuration

To enable your Medplum application to communicate with your Fission functions, you must correctly configure the Fission Router's address. The routerHost and routerPort settings within your FissionConfig dictate how your application establishes a connection to the Fission Router.

These settings specify the network address (hostname or IP address) and the port through which the Fission Router can be accessed. The optimal configuration depends on where your Medplum application is deployed relative to your Fission cluster.

Medplum Server Configuration for Fission

Add your Fission router configuration to your Medplum server configuration.

For example, when running a local development setup with Fission in a Docker Desktop Kubernetes cluster, add the following to medplum.config.json:

"fission": {
  "namespace": "default",
  "fieldManager": "medplum-fission-example",
  "environmentName": "nodejs",
  "routerHost": "localhost",
  "routerPort": 31314
}

When using AWS Parameter Store, you can add a single fission parameter with the following JSON value:

{
  "namespace": "default",
  "fieldManager": "medplum-fission-example",
  "environmentName": "nodejs",
  "routerHost": "localhost",
  "routerPort": 31314
}

Local Development Setup for Fission

To run a pre-configured Medplum + Fission environment, you can follow the instructions in GitHub Medplum Local K8s.

Otherwise, to get started with Fission for local development or testing, follow these steps to install it on your Kubernetes cluster. For detailed and up-to-date installation instructions, always refer to the official Fission documentation: Fission Installation.

# Define the namespace for Fission

export FISSION_NAMESPACE="fission"

# Create the Fission namespace

kubectl create namespace $FISSION_NAMESPACE

# Apply Fission's Custom Resource Definitions (CRDs)

# Check Fission's official documentation for the latest stable release.

kubectl create -k "github.com/fission/fission/crds/v1?ref=v1.21.0"

# Add the Fission Helm repository

helm repo add fission-charts https://fission.github.io/fission-charts/

# Update your Helm repositories

helm repo update

# Install Fission using Helm

helm install --version v1.21.0 --namespace $FISSION_NAMESPACE fission \
  --set serviceType=NodePort,routerServiceType=NodePort \
  fission-charts/fission-all

This setup will install Fission with NodePort services for its components, making it accessible from outside the cluster, which is ideal for local development and testing.

Working with Dependencies in Fission Bots

Medplum Bots often rely on external npm packages. When running your bots on Fission, Medplum handles the packaging and deployment of your bot code along with its package.json file. This allows Fission to install the necessary dependencies during the build process.

Refer to the official Fission documentation for the most current information on managing dependencies: Fission - Working with Dependencies.

Here's a general workflow for preparing your bot:

  1. Create a Node.js Environment in Fission:
fission environment create --name nodejs --image ghcr.io/fission/node-env --builder ghcr.io/fission/node-builder
  1. Prepare your Medplum Bot Code:
import { BotEvent, MedplumClient } from '@medplum/core';
import { Patient } from '@medplum/fhirtypes';

export async function handler(medplum: MedplumClient, event: BotEvent): Promise<any> {
     const patient = event.input as Patient;
     const firstName = patient.name?.[0]?.given?.[0];
     const lastName = patient.name?.[0]?.family;
     console.log(`Hello ${firstName} ${lastName}!`);
     return true;
}

See Bot Basics - Editing a Bot for more details on writing Medplum Bot code.

  1. Deploying your Bot with Medplum:

See Bot Basics - Deploying a Bot for more details on deploying your bot.

  1. Check Fission Build Status (for debugging):
fission package info --name <medplum-generated-fission-package-name>
  1. Test Your Fission Function (for debugging):
curl -X POST -H "Content-Type: application/json" \
     -d '{ "resourceType": "Patient", "id": "123", "name": [{ "given": ["John"], "family": "Doe" }] }' \
     "https://api.medplum.com/fhir/R4/Bot/<your-bot-id>/\$execute"

See Bot Basics - Executing a Bot for more details on executing your bot.

Troubleshooting Fission Deployments

When working with Fission, especially during initial setup or debugging, these commands can be invaluable:

kubectl get functions -n <your-fission-namespace>
kubectl get function <function-name> -o json -n <your-fission-namespace>
kubectl get pods -n fission
# Find builder pod name

kubectl get pods -n fission -l fission.io/function=builder -o jsonpath='{.items[0].metadata.name}'

# Tail logs

kubectl logs -f -n fission $(kubectl get pods -n fission -l fission.io/function=builder -o jsonpath='{.items[0].metadata.name}')
kubectl logs -n fission <pod-name> --previous
kubectl delete httptriggers --all -n default
kubectl delete functions --all -n default
kubectl delete packages --all -n default
kubectl delete httptriggers --all -n default
kubectl delete functions --all -n default
kubectl delete packages --all -n default

Note: Always be careful when using --all and ensure you are in the correct namespace to avoid unintended deletions.