How to Deploy Claude Agents to Modal and Trigger.dev: A No-Code Guide
Learn how to deploy Claude Code skills to Modal (Python) or Trigger.dev (TypeScript) so your AI agents run 24/7 without your machine staying on.
Why Running Claude Agents Locally Doesn’t Scale
If you’ve built a Claude-powered agent that works great on your laptop, you’ve already hit the core problem: the moment you close the terminal, the agent stops.
That’s fine for experiments. It’s not fine for anything production-ready — scheduled jobs, webhook listeners, background processors, or agents that need to handle requests at any hour. Deploying Claude agents to Modal (Python) or Trigger.dev (TypeScript) solves this by giving your agent a persistent, cloud-based home that runs 24/7 without your machine staying on.
This guide walks through both deployment paths step by step. Whether you’re working in Python or TypeScript, you’ll have a running Claude agent in the cloud by the end.
What Modal and Trigger.dev Actually Are
Before touching any code, it’s worth being clear about what each platform does — and why they’re worth using over raw cloud VMs or serverless functions.
Modal: Serverless Python Infrastructure
Modal is a serverless compute platform built specifically for Python workloads. You write a normal Python function, decorate it with Modal-specific decorators, and Modal handles all the infrastructure: containerization, scaling, GPU access, scheduling, and cold start optimization.
For Claude agents, Modal is a strong fit if:
- Your agent code is Python-based
- You’re using Anthropic’s Python SDK directly
- You want scheduled runs (cron jobs) or on-demand execution via a web endpoint
- You need access to GPU resources for hybrid AI workloads
Trigger.dev: Background Jobs for TypeScript
Day one: idea. Day one: app.
Not a sprint plan. Not a quarterly OKR. A finished product by end of day.
Trigger.dev is an open-source background job platform for TypeScript and Node.js. It provides durable execution — meaning if a job fails halfway through, it can resume from where it left off rather than starting over. It also has built-in support for long-running tasks, retries, concurrency limits, and a clean dashboard for monitoring runs.
For Claude agents, Trigger.dev is a strong fit if:
- Your agent logic is TypeScript/Node.js
- You’re calling the Anthropic SDK via
@anthropic-ai/sdk - You need webhook-triggered agents or event-driven execution
- Reliability and observability matter more than raw speed
Both platforms have generous free tiers that are more than enough to get started.
Prerequisites
Before deploying, make sure you have the following ready regardless of which platform you choose:
- An Anthropic API key — Get one from the Anthropic Console
- A basic Claude agent already working locally — This guide assumes you have agent code running on your machine
- Node.js 18+ or Python 3.10+ depending on your path
- A Modal or Trigger.dev account — both are free to create
Deploying a Claude Agent to Modal (Python Path)
Step 1: Install Modal and Set Up Authentication
Install Modal with pip:
pip install modal
Then authenticate with your Modal account:
modal setup
This opens a browser window to link your account. Once done, Modal stores your credentials locally so future deployments work without re-authenticating.
Step 2: Store Your Anthropic API Key as a Modal Secret
Never hardcode API keys in your code. Modal has a built-in secrets system.
In the Modal dashboard, go to Secrets, click Create new secret, and add:
- Key:
ANTHROPIC_API_KEY - Value: your actual API key
Name the secret something like anthropic-secret. You’ll reference this name in your code.
Step 3: Write Your Modal-Compatible Agent
Here’s a minimal Claude agent structure that Modal can run:
import modal
import anthropic
app = modal.App("claude-agent")
image = modal.Image.debian_slim().pip_install("anthropic")
@app.function(
image=image,
secrets=[modal.Secret.from_name("anthropic-secret")],
schedule=modal.Cron("0 9 * * *") # runs every day at 9am UTC
)
def run_claude_agent():
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-opus-4-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": "Summarize the key actions I should take this week based on the following data..."
}
]
)
result = message.content[0].text
print(result)
return result
A few things to note here:
modal.Image.debian_slim().pip_install("anthropic")builds a container image with the Anthropic SDK installedmodal.Secret.from_name("anthropic-secret")injects your API key as an environment variablemodal.Cron("0 9 * * *")schedules the function to run daily at 9am UTC — remove this for on-demand runs
Step 4: Add a Web Endpoint (Optional but Useful)
If you want to trigger your agent via HTTP — for example, from a webhook — add a web endpoint:
@app.function(
image=image,
secrets=[modal.Secret.from_name("anthropic-secret")]
)
@modal.web_endpoint(method="POST")
def agent_webhook(request: dict):
client = anthropic.Anthropic()
user_input = request.get("message", "")
message = client.messages.create(
model="claude-opus-4-5",
max_tokens=1024,
messages=[{"role": "user", "content": user_input}]
)
return {"response": message.content[0].text}
Modal will give you a public HTTPS URL for this endpoint after deployment.
Step 5: Deploy to Modal
Run this from your project directory:
modal deploy your_agent_file.py
Modal builds the container, pushes it, and gives you a deployment URL. Scheduled functions will now run on their own schedule. Web endpoints will be live immediately.
To test a function manually before the schedule triggers:
modal run your_agent_file.py::run_claude_agent
Step 6: Monitor Your Agent
- ✕a coding agent
- ✕no-code
- ✕vibe coding
- ✕a faster Cursor
The one that tells the coding agents what to build.
The Modal dashboard shows every function invocation, stdout output, errors, and execution time. You can also set up log streaming in your terminal:
modal app logs claude-agent
Deploying a Claude Agent to Trigger.dev (TypeScript Path)
Step 1: Install the Trigger.dev CLI and Initialize a Project
Install the CLI globally:
npm install -g @trigger.dev/cli
If you’re starting from scratch, initialize a new project:
npx trigger.dev@latest init
If you’re adding Trigger.dev to an existing Node.js project:
npx trigger.dev@latest init --existing
The CLI will ask for your Trigger.dev project reference (found in your dashboard after creating an account). It creates a trigger folder in your project with a sample task file.
Step 2: Install the Anthropic SDK
npm install @anthropic-ai/sdk
Step 3: Store Your API Key
In the Trigger.dev dashboard, navigate to Environment Variables and add:
ANTHROPIC_API_KEY= your API key
This makes the variable available to all your tasks at runtime without exposing it in code.
Step 4: Write Your Trigger.dev Task
Tasks are the core unit of work in Trigger.dev. Here’s a Claude agent task:
import { task, schedules } from "@trigger.dev/sdk/v3";
import Anthropic from "@anthropic-ai/sdk";
export const claudeAgentTask = task({
id: "claude-agent-task",
maxDuration: 300, // 5 minutes max
run: async (payload: { userMessage: string }) => {
const client = new Anthropic();
const message = await client.messages.create({
model: "claude-opus-4-5",
max_tokens: 1024,
messages: [
{
role: "user",
content: payload.userMessage
}
]
});
const response = message.content[0].type === "text"
? message.content[0].text
: "";
console.log("Claude response:", response);
return { response };
}
});
For a scheduled version that runs on a cron, use Trigger.dev’s schedules:
import { schedules } from "@trigger.dev/sdk/v3";
import Anthropic from "@anthropic-ai/sdk";
export const scheduledClaudeAgent = schedules.task({
id: "scheduled-claude-agent",
cron: "0 9 * * 1-5", // weekdays at 9am UTC
run: async (payload) => {
const client = new Anthropic();
const message = await client.messages.create({
model: "claude-opus-4-5",
max_tokens: 1024,
messages: [
{
role: "user",
content: "Generate today's morning briefing..."
}
]
});
return { result: message.content[0] };
}
});
Step 5: Run in Dev Mode to Test
Before deploying, test locally with:
npx trigger.dev@latest dev
This connects your local environment to Trigger.dev’s servers. You can trigger test runs from the dashboard and see real-time logs in your terminal. Your API key is pulled from the environment variables you set in the dashboard.
Step 6: Deploy
When you’re ready to go live:
npx trigger.dev@latest deploy
Trigger.dev builds your project in its cloud environment and registers your tasks. Scheduled tasks activate automatically. On-demand tasks wait for a trigger — either a manual run from the dashboard or an API call.
Step 7: Trigger Tasks via API
Once deployed, you can trigger any task via HTTP from any system:
curl -X POST https://api.trigger.dev/v1/tasks/claude-agent-task/trigger \
-H "Authorization: Bearer YOUR_TRIGGER_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"payload": {"userMessage": "What are the key trends in Q3 data?"}}'
The response includes a run ID you can use to poll for results or stream logs.
Building Multi-Step Claude Agents
A single message to Claude is rarely a complete agent. Real-world agents need to call tools, make decisions across multiple steps, and act on results. Both Modal and Trigger.dev support this, but the patterns differ slightly.
Multi-Step Agents in Modal
Modal functions can call other Modal functions, making it easy to chain steps:
@app.function(image=image, secrets=[modal.Secret.from_name("anthropic-secret")])
def analyze_data(data: str) -> str:
# Step 1: ask Claude to analyze
...
@app.function(image=image, secrets=[modal.Secret.from_name("anthropic-secret")])
def run_full_pipeline(raw_data: str):
analysis = analyze_data.remote(raw_data)
# Step 2: use analysis result in next call
...
The .remote() call runs the function in a separate container, which means each step scales independently.
Multi-Step Agents in Trigger.dev
Trigger.dev is purpose-built for this. Use subtasks or just chain await calls within a single task:
export const researchAndSummarizeTask = task({
id: "research-and-summarize",
run: async (payload: { topic: string }) => {
const client = new Anthropic();
// Step 1: gather questions
const questionsResponse = await client.messages.create({
model: "claude-opus-4-5",
max_tokens: 512,
messages: [{ role: "user", content: `Generate 5 research questions about: ${payload.topic}` }]
});
const questions = questionsResponse.content[0].type === "text"
? questionsResponse.content[0].text
: "";
// Step 2: synthesize answers
const summaryResponse = await client.messages.create({
model: "claude-opus-4-5",
max_tokens: 1024,
messages: [
{ role: "user", content: `Answer each of these questions concisely:\n${questions}` }
]
});
return { summary: summaryResponse.content[0] };
}
});
Trigger.dev’s durable execution means if your task hits a timeout or error partway through, you can configure it to retry from the last successful checkpoint rather than starting over.
Common Mistakes and How to Avoid Them
Forgetting to Handle Rate Limits
Anthropic enforces rate limits per API key. If your agent runs many calls in a short window, you’ll get 429 errors. Always add retry logic:
In Python:
from anthropic import RateLimitError
import time
def call_claude_with_retry(client, messages, max_retries=3):
for attempt in range(max_retries):
try:
return client.messages.create(
model="claude-opus-4-5",
max_tokens=1024,
messages=messages
)
except RateLimitError:
if attempt < max_retries - 1:
time.sleep(2 ** attempt) # exponential backoff
else:
raise
In TypeScript (Trigger.dev): Set retry on the task config:
export const claudeTask = task({
id: "claude-task",
retry: {
maxAttempts: 3,
factor: 2,
minTimeoutInMs: 1000,
},
run: async (payload) => { ... }
});
Hardcoding Model Names
Anthropic updates model names regularly. Hardcoding claude-opus-4-5 in 20 places means 20 edits when a new version releases. Store the model name in an environment variable and reference it throughout.
Not Setting Max Execution Timeouts
By default, cloud functions have short timeouts. A complex Claude agent doing 10+ API calls can easily run for several minutes. Always set maxDuration in Trigger.dev and timeout in Modal explicitly to match your expected execution time.
Logging Too Much (or Too Little)
Log the inputs, outputs, and key decision points of your agent — but don’t log full message histories on every run at production scale. This inflates costs and makes it harder to find relevant logs. Use structured logging with severity levels.
Where MindStudio Fits Into This
Modal and Trigger.dev solve the infrastructure layer — where your agent runs and when. But they don’t solve what your agent can actually do. A Claude agent running in Modal can reason and generate text, but actually sending an email, writing to a spreadsheet, posting to Slack, or triggering another workflow requires extra code for each integration.
That’s where MindStudio’s Agent Skills Plugin changes the picture. It’s an npm SDK (@mindstudio-ai/agent) that gives any agent — including Claude agents deployed on Trigger.dev or Modal — access to 120+ pre-built capabilities as simple method calls.
Instead of writing custom integration code, your agent just calls:
import { MindStudioAgent } from "@mindstudio-ai/agent";
const agent = new MindStudioAgent({ apiKey: process.env.MINDSTUDIO_KEY });
// Send an email without writing email integration code
await agent.sendEmail({ to: "team@company.com", subject: "Agent Report", body: result });
// Generate an image
const image = await agent.generateImage({ prompt: "quarterly results chart" });
// Search the web
const searchResults = await agent.searchGoogle({ query: "latest AI benchmarks" });
The SDK handles auth, rate limiting, and retries for every integration — your agent just calls the method and gets the result. This pairs naturally with Claude agents deployed to Trigger.dev, where your task file can import both @anthropic-ai/sdk and @mindstudio-ai/agent and combine Claude’s reasoning with real-world actions in a single durable job.
If you’d rather skip the deployment complexity entirely, you can also build and host Claude-powered agents directly on MindStudio’s no-code platform. Agents run in the cloud by default, support custom JavaScript functions, and connect to 1,000+ integrations without any deployment configuration. You can try it free at mindstudio.ai.
Choosing Between Modal and Trigger.dev
Neither platform is universally better — they suit different situations.
| Factor | Modal | Trigger.dev |
|---|---|---|
| Language | Python | TypeScript / Node.js |
| Scheduling | Built-in cron | Built-in cron |
| Durable execution | No (restart on failure) | Yes (resume from checkpoint) |
| GPU access | Yes | No |
| Observability | Good | Excellent |
| Open source | No | Yes |
| Free tier | Generous compute credits | Generous task runs |
| Best for | Data-heavy Python agents | Long-running TypeScript workflows |
If you’re already writing Python and your agent is compute-intensive or needs GPU access, Modal is the better fit. If you’re in TypeScript and need reliable, observable background jobs with durable execution, Trigger.dev is worth choosing.
Frequently Asked Questions
Do I need to know Docker or Kubernetes to deploy Claude agents to Modal or Trigger.dev?
No. Both platforms abstract away container management entirely. Modal builds containers from Python function definitions. Trigger.dev handles its own build process. You write application code — not infrastructure config.
How much does it cost to run a Claude agent on Modal or Trigger.dev?
Both have free tiers. Modal gives new accounts $30 in free compute credits per month, which is substantial for most agent workloads. Trigger.dev’s free plan includes 5,000 task runs per month. Costs scale with usage after that — a Claude agent running once per day or responding to occasional webhooks will likely stay in the free tier for a long time.
Can I use Claude’s tool use (function calling) feature with these platforms?
Everyone else built a construction worker.
We built the contractor.
One file at a time.
UI, API, database, deploy.
Yes. Both platforms are just runtime environments — they don’t restrict how you call the Anthropic API. You can use Claude’s full API surface including tool use, vision, multi-turn conversations, and streaming responses. The deployment code in this guide is a starting point; add tool definitions to your client.messages.create() calls as you normally would.
What happens if my Claude agent fails mid-run?
In Modal, failed functions can be configured to retry automatically. In Trigger.dev, durable execution means tasks can resume from the last successful step rather than starting over — which is particularly valuable for long-running, multi-step agents. Either way, both platforms surface failure reasons in their dashboards so you can debug quickly.
Can I run a Claude agent that responds to webhooks on both platforms?
Yes. Modal supports web endpoints via @modal.web_endpoint, which gives you a public HTTPS URL. Trigger.dev tasks can be triggered via their REST API, and you can point any webhook at a lightweight API route that calls claudeAgentTask.trigger(). Both approaches work well for event-driven agent patterns.
Is it possible to run a Claude agent on a schedule without any server?
Yes — and that’s the main point of both platforms. Modal’s schedule=modal.Cron(...) and Trigger.dev’s schedules.task with a cron expression both run on cloud infrastructure without needing a server you manage. The agent wakes up on schedule, runs, and shuts down — you pay only for execution time.
Key Takeaways
- Modal is the right choice for Python-based Claude agents, especially if you need GPU access or want a simple serverless function model.
- Trigger.dev is better for TypeScript agents where durable execution, observability, and long-running jobs matter.
- Both platforms handle secrets management, scheduling, and scaling — don’t store API keys in code.
- Add retry logic for Anthropic rate limits regardless of which platform you use.
- The MindStudio Agent Skills Plugin extends deployed Claude agents with 120+ real-world capabilities — sending emails, generating images, searching the web — without writing custom integration code.
If you want to skip deployment entirely and build agents that run in the cloud by default, MindStudio lets you create and host Claude-powered workflows visually, with built-in integrations, in a fraction of the time. Try it free at mindstudio.ai.