Bot Management¶
PyMedplum provides comprehensive support for managing Medplum Bots, including deploying bot code, saving source code, and executing bots.
Overview¶
Medplum Bots are serverless functions that run as AWS Lambda functions within the Medplum infrastructure. They can be triggered by various events and are written in TypeScript/JavaScript.
PyMedplum’s bot management features allow you to:
- Create and manage bots with full CRUD operations
- Deploy bot code to AWS Lambda using the
$deployoperation - Save source code to Bot resources for version control
- Execute bots with custom input data
- Combine operations for streamlined workflows
Bot Runtime Requirements¶
IMPORTANT: For bots to execute successfully, you must specify a runtime_version when creating the bot. Without this, deployment and execution will fail with an “Unsupported bot runtime” error.
Medplum supports two runtime versions:
awslambda: Runs bots on AWS Lambda (most common)vmcontext: Runs bots in a VM context (advanced use cases)
Creating Bots with Runtime¶
The client authenticates automatically on the first request and refreshes tokens proactively, so the examples below just construct a client and start making calls.
Always specify the runtime version when creating a bot:
from pymedplum import MedplumClient
client = MedplumClient(base_url="https://api.medplum.com")
# Create bot with AWS Lambda runtime (required for execution!)
bot = client.create_bot(
name="My Bot",
description="Processes patient data",
runtime_version="awslambda" # This is required!
)
Without runtime_version, your bot will be created but cannot be deployed or executed.
Installation¶
Bot management is built directly into the MedplumClient:
from pymedplum import MedplumClient
client = MedplumClient(base_url="https://api.medplum.com")
# All bot methods are available on the client
client.create_bot(...)
client.deploy_bot(...)
client.execute_bot(...)
Basic Usage¶
Deploying a Bot¶
Deploy compiled JavaScript code to a bot:
from pymedplum import MedplumClient
# Initialize the client — auth happens on the first request
client = MedplumClient(base_url="https://api.medplum.com")
# Read your compiled bot code
with open("dist/my-bot.js") as f:
compiled_code = f.read()
# Deploy the bot
result = client.deploy_bot(
bot_id="your-bot-id-here",
code=compiled_code,
filename="index.js" # optional, defaults to "index.js"
)
print(f"Bot deployed: {result}")
Saving Bot Source Code¶
Save TypeScript source code to a Bot resource:
# Read your bot source code
with open("src/my-bot.ts") as f:
source_code = f.read()
# Save the source code to the Bot resource
updated_bot = client.save_bot_code(
bot_id="your-bot-id-here",
source_code=source_code
)
print(f"Source code saved to bot: {updated_bot['id']}")
Save and Deploy in One Step¶
For convenience, you can save source code and deploy compiled code together:
# Read both source and compiled code
with open("src/my-bot.ts") as f:
source_code = f.read()
with open("dist/my-bot.js") as f:
compiled_code = f.read()
# Save and deploy
bot, deploy_result = client.save_and_deploy_bot(
bot_id="your-bot-id-here",
source_code=source_code,
compiled_code=compiled_code
)
print(f"Bot updated: {bot['id']}")
print(f"Deployment result: {deploy_result}")
Executing a Bot¶
Execute a deployed bot with custom input data:
# Execute the bot
result = client.execute_bot(
bot_id="your-bot-id-here",
input_data={
"resourceType": "Parameters",
"parameter": [
{
"name": "patientId",
"valueString": "patient-123"
}
]
}
)
print(f"Bot execution result: {result}")
Async Support¶
All bot management methods are available on AsyncMedplumClient:
from pymedplum import AsyncMedplumClient
async with AsyncMedplumClient(base_url="https://api.medplum.com") as client:
# Deploy bot asynchronously
with open("dist/my-bot.js") as f:
compiled_code = f.read()
result = await client.deploy_bot(
bot_id="your-bot-id-here",
code=compiled_code
)
# Execute bot asynchronously
exec_result = await client.execute_bot(
bot_id="your-bot-id-here",
input_data={"resourceType": "Parameters", "parameter": []}
)
Complete Workflow Example¶
Here’s a complete example showing how to create, deploy, and execute a bot:
from pymedplum import MedplumClient
# Initialize — auth happens on the first request
client = MedplumClient(base_url="https://api.medplum.com")
# Create a new Bot resource
bot = client.create_bot(
name="My Custom Bot",
description="A bot that processes patient data",
runtime_version="awslambda"
)
bot_id = bot["id"]
# TypeScript source code
source_code = """
export async function handler(medplum, event) {
const { input } = event;
console.log('Processing input:', input);
// Your bot logic here
const result = {
resourceType: 'Parameters',
parameter: [{
name: 'status',
valueString: 'success'
}]
};
return result;
}
"""
# Compiled JavaScript code
compiled_code = """
exports.handler = async function(medplum, event) {
const { input } = event;
console.log('Processing input:', input);
const result = {
resourceType: 'Parameters',
parameter: [{
name: 'status',
valueString: 'success'
}]
};
return result;
};
"""
# Save and deploy
bot, deploy_result = client.save_and_deploy_bot(
bot_id=bot_id,
source_code=source_code,
compiled_code=compiled_code
)
print(f"✓ Bot {bot_id} deployed successfully")
# Execute the bot
result = client.execute_bot(
bot_id=bot_id,
input_data={
"resourceType": "Parameters",
"parameter": [
{
"name": "input",
"valueString": "test data"
}
]
}
)
print(f"✓ Bot execution result: {result}")
API Reference¶
client.create_bot()¶
Create a new Bot resource.
Parameters:
- name (str): The name of the bot
- description (str, optional): Bot description
- source_code (str, optional): Initial source code
- runtime_version (str, optional): Runtime (“awslambda” or “vmcontext”)
- **kwargs: Additional Bot resource properties
Returns: dict[str, Any] - The created Bot resource
client.deploy_bot()¶
Deploy compiled bot code to AWS Lambda.
Parameters:
- bot_id (str): The ID of the Bot resource
- code (str): The compiled JavaScript code to deploy
- filename (str, optional): The filename for the bot code (default: “index.js”)
Returns: dict[str, Any] - The response from the $deploy operation
client.save_bot_code()¶
Save source code to a Bot resource’s code property.
Parameters:
- bot_id (str): The ID of the Bot resource
- source_code (str): The source code to save (typically TypeScript)
Returns: dict[str, Any] - The updated Bot resource
client.save_and_deploy_bot()¶
Save source code and deploy compiled code in one operation.
Parameters:
- bot_id (str): The ID of the Bot resource
- source_code (str): The source code to save
- compiled_code (str): The compiled JavaScript code to deploy
- filename (str, optional): The filename for the bot code (default: “index.js”)
Returns: tuple[dict[str, Any], dict[str, Any]] - A tuple of (updated Bot resource, deploy response)
client.execute_bot()¶
Execute a deployed bot.
Parameters:
- bot_id (str): The ID of the Bot to execute
- input_data (Any): Input data to pass to the bot
- content_type (str, optional): Content type (default: “application/json”)
Returns: dict[str, Any] - Bot execution result
client.read_bot()¶
Read a Bot resource by ID.
Parameters:
- bot_id (str): The ID of the Bot resource
Returns: dict[str, Any] - The Bot resource
client.update_bot()¶
Update a Bot resource.
Parameters:
- bot (dict[str, Any]): The Bot resource with updates
Returns: dict[str, Any] - The updated Bot resource
client.delete_bot()¶
Delete a Bot resource.
Parameters:
- bot_id (str): The ID of the Bot resource to delete
Returns: None
client.list_bots()¶
List Bot resources with optional search parameters.
Parameters:
- **search_params (Any): Optional FHIR search parameters
Returns: dict[str, Any] - A Bundle of Bot resources
Async Methods¶
All methods are available on AsyncMedplumClient and must be awaited:
- await client.create_bot(...)
- await client.deploy_bot(...)
- await client.save_bot_code(...)
- await client.save_and_deploy_bot(...)
- await client.execute_bot(...)
- await client.read_bot(...)
- await client.update_bot(...)
- await client.delete_bot(...)
- await client.list_bots(...)
Best Practices¶
1. Version Control¶
Always save source code to the Bot resource for version control and auditing:
# Good: Save source before deploying
client.save_and_deploy_bot(bot_id, source_code, compiled_code)
# Not recommended: Deploy without saving source
client.deploy_bot(bot_id, compiled_code)
2. Error Handling¶
Wrap bot operations in try-except blocks:
try:
result = client.deploy_bot(bot_id, compiled_code)
print(f"Deployment successful: {result}")
except Exception as e:
print(f"Deployment failed: {e}")
# Handle error appropriately
3. Testing¶
Test bots locally before deploying:
# Deploy to a test bot first
test_bot_id = "test-bot-id"
client.deploy_bot(test_bot_id, compiled_code)
# Execute and verify
result = client.execute_bot(test_bot_id, test_data)
assert result["parameter"][0]["valueString"] == "expected_value"
# Then deploy to production
client.deploy_bot(production_bot_id, compiled_code)
4. Deployment Timing¶
Note that bot deployments may take a moment to propagate:
import time
# Deploy the bot
client.deploy_bot(bot_id, compiled_code)
# Wait a moment for deployment to complete
time.sleep(2)
# Then execute
result = client.execute_bot(bot_id, input_data)
Comparison with Medplum CLI¶
PyMedplum’s bot management features provide similar functionality to the Medplum CLI’s bot deploy command, but within Python:
| Feature | Medplum CLI | PyMedplum |
|---|---|---|
| Deploy bot code | npx medplum bot deploy <name> |
client.deploy_bot(bot_id, code) |
| Save source code | Handled automatically | client.save_bot_code(bot_id, source) |
| Execute bot | Via API calls | client.execute_bot(bot_id, data) |
| Language | Node.js/TypeScript | Python |
| Use case | CLI automation | Python applications |
Choose PyMedplum when: - You’re building Python applications - You need programmatic bot management - You want to integrate bot deployment into Python workflows
Choose Medplum CLI when:
- You’re working primarily in Node.js/TypeScript
- You need medplum.config.json support
- You prefer command-line tools