Skip to main content
The unified deploy command replaces the legacy serve and modal-serve commands, providing a consistent interface for running task apps locally or deploying to Modal.

Quick Start

# Local development (uvicorn)
uvx synth-ai deploy --runtime uvicorn --port 8001

# Deploy to Modal (production)
uvx synth-ai deploy --runtime modal

# Deploy specific registered app
uvx synth-ai deploy my-task-app --runtime modal --name my-task-app-prod

Runtimes

The --runtime flag determines where your task app runs:

uvicorn - Local Development

Run your task app locally with hot reload, perfect for development and testing. Basic usage:
uvx synth-ai deploy --runtime uvicorn
Full example with options:
uvx synth-ai deploy grpo-crafter \
  --runtime uvicorn \
  --host 0.0.0.0 \
  --port 8001 \
  --env-file .env \
  --trace traces/v3 \
  --trace-db traces/v3/local.db \
  --reload \
  --force
Uvicorn options:
  • --host TEXT - Bind address (default: 0.0.0.0)
  • --port INTEGER - Port number (prompted if not provided)
  • --env-file PATH - Load environment variables (repeatable)
  • --reload - Auto-reload on code changes
  • --force - Kill existing process on port
  • --trace DIR - Enable trace output directory
  • --trace-db PATH - SQLite database for traces
Deploy to Modal’s cloud platform for production or remote access during RL training. Basic usage:
uvx synth-ai deploy --runtime modal
Full example with options:
uvx synth-ai deploy my-task-app \
  --runtime modal \
  --name my-task-app-prod \
  --modal-mode deploy \
  --env-file .env.production \
  --dry-run
Modal options:
  • --name TEXT - Override Modal app name
  • --modal-mode [deploy|serve] - Deployment mode:
    • deploy (default) - Persistent production deployment
    • serve - Ephemeral development deployment (shuts down on exit)
  • --modal-app PATH - Custom Modal wrapper file (rarely needed)
  • --modal-cli PATH - Path to Modal CLI binary
  • --dry-run - Print Modal command without executing (only works with --modal-mode deploy)

App Discovery

You can deploy in three ways: Deploy a registered task app by ID:
uvx synth-ai deploy grpo-crafter --runtime uvicorn --port 8001

2. File-based

Deploy from a task app file directly:
uvx synth-ai deploy \
  --task-app ./my_app/task_app.py \
  --runtime uvicorn \
  --port 8001
For Modal, you’ll also need to specify the Modal wrapper:
uvx synth-ai deploy \
  --task-app ./my_app/task_app.py \
  --modal-app ./my_app/modal_main.py \
  --runtime modal

3. Interactive discovery

If you don’t specify an app ID or --task-app, the CLI will discover and prompt you to select from:
  • Registered task apps
  • Demo apps
  • Task apps in your current directory

Common Workflows

Local Development Loop

# 1. Start local server with hot reload
uvx synth-ai deploy my-app \
  --runtime uvicorn \
  --port 8001 \
  --reload \
  --trace traces/v3

# 2. In another terminal, smoke-test it
uvx synth-ai smoke \
  --url http://localhost:8001 \
  --env-name my-env \
  --max-steps 10

# 3. Make changes to your task app code
# → Server auto-reloads (thanks to --reload)

Preview on Modal Before Production

# 1. Test with ephemeral Modal deployment
uvx synth-ai deploy my-app \
  --runtime modal \
  --modal-mode serve \
  --env-file .env

# → Logs stream to terminal
# → App shuts down when you exit

# 2. When ready, deploy to production
uvx synth-ai deploy my-app \
  --runtime modal \
  --modal-mode deploy \
  --name my-app-prod

Production Deployment

# 1. Deploy to Modal
uvx synth-ai deploy my-task-app \
  --runtime modal \
  --name my-task-app-prod \
  --env-file .env.production

# 2. Verify health
curl -H "X-API-Key: $ENVIRONMENT_API_KEY" \
  https://my-task-app-prod.modal.run/health

# 3. Smoke-test the deployment
uvx synth-ai smoke \
  --url https://my-task-app-prod.modal.run \
  --env-name my-env

# 4. Use in RL training config
# Set task_url in your RL TOML:
# [services]
# task_url = "https://my-task-app-prod.modal.run"

Environment Variables

The deploy command respects:
  • SYNTH_API_KEY - Your Synth platform API key
  • ENVIRONMENT_API_KEY - Task app authentication (forwarded as X-API-Key)
  • TASK_APP_URL - Default task app URL
  • DEMO_DIR / SYNTH_DEMO_DIR - Demo directory paths
Use --env-file to load additional environment files:
uvx synth-ai deploy \
  --runtime uvicorn \
  --env-file .env.local \
  --env-file .env.secrets

Prerequisites

For uvicorn runtime:

  • Python 3.11+
  • Task app dependencies installed

For modal runtime:

  1. Modal account - Sign up at modal.com
  2. Modal authentication:
    pip install modal
    modal token new
    
  3. Environment API key:
    uvx synth-ai setup
    

Troubleshooting

”ENVIRONMENT_API_KEY is required”

Run setup to configure your credentials:
uvx synth-ai setup

“Modal CLI not found”

Install Modal and authenticate:
pip install modal
modal token new

“Port already in use” (uvicorn)

Use --force to kill the existing process:
uvx synth-ai deploy --runtime uvicorn --port 8001 --force
Or specify a different port:
uvx synth-ai deploy --runtime uvicorn --port 8002

“Task app not found”

  • Verify the app ID matches your task app registration
  • Use --task-app to specify the file path explicitly
  • Check that the task app file exists and is valid
  • Verify Modal authentication: modal token new
  • Check that ENVIRONMENT_API_KEY is set
  • Review Modal logs in the terminal output
  • Try --dry-run to preview the Modal command

Migration from Legacy Commands

If you were using the old serve or modal-serve commands: Old:
uvx synth-ai serve my-app --port 8001
uvx synth-ai modal-serve my-app
New:
uvx synth-ai deploy my-app --runtime uvicorn --port 8001
uvx synth-ai deploy my-app --runtime modal --modal-mode serve
The legacy commands are deprecated and will be removed in a future release.

Next Steps