DS DevShelfHub Projects · AI tools
Tutorials / AI Agents / Production Deployment
Build with CrewAI Advanced · 15 min read Page 12 of 29

CrewAI Production: Ship Multi-Agent Crews Behind APIs

By DevShelfHub

Wrap crews in FastAPI, queue with Celery, package with Docker, manage secrets, scale workers, and structure your codebase with YAML config.

Series progress12 / 29
CrewAI production tutorial — CrewAI Production: Ship Multi-Agent Crews Behind APIs

Package Your Crew as a Service

Wrap the crew behind a thin API layer (FastAPI is the typical choice). Inputs in, structured output out.

FastAPI wrapper

PYTHON
from fastapi import FastAPI
from pydantic import BaseModel
from my_crew import build_crew     # your factory function

app = FastAPI()

class RunRequest(BaseModel):
    topic: str

@app.post("/run")
def run(req: RunRequest):
    crew = build_crew()
    result = crew.kickoff(inputs={"topic": req.topic})
    return {"output": str(result)}

Async Execution & Queuing

Crews can take 30s–10min. Synchronous HTTP is the wrong shape — use a job queue.

Celery worker

PYTHON
from celery import Celery
from my_crew import build_crew

app = Celery("crews", broker="redis://localhost:6379/0")

@app.task(bind=True, max_retries=3)
def run_crew_async(self, topic: str):
    try:
        crew = build_crew()
        result = crew.kickoff(inputs={"topic": topic})
        return str(result)
    except Exception as e:
        raise self.retry(exc=e, countdown=30)

Dockerizing

For the full Docker command reference — images, volumes, networking, multi-stage builds — see the Docker cheatsheet.

Dockerfile

BASH
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip3 install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Secrets Management

Never bake API keys into images. Inject at runtime.

Runtime secrets

BASH
docker run -e OPENAI_API_KEY=$OPENAI_API_KEY \
           -e SERPER_API_KEY=$SERPER_API_KEY \
           -p 8000:8000 my-crew:latest

In production: AWS Secrets Manager, GCP Secret Manager, or Kubernetes secrets.

Scaling Patterns

Horizontal worker pool

Each crew run is independent — spin up N workers behind a queue. Scale on queue depth.

LLM rate-limit handling

Catch RateLimitError at the worker level, exponential backoff, requeue. Don't let one crew's retry block the pool.

Caching

Cache deterministic tool calls (web scrapes of stable URLs, DB lookups). Cuts cost dramatically on retries.

YAML Config (Recommended)

For non-trivial crews, define agents and tasks in YAML — easier to review, version, and let non-engineers edit. Map rows to executable @task methods on a CrewBase class as shown below.

The CrewBase class decorator wires those YAML files to @agent, @task, and @crew methods in the pattern below.

agents.yaml

YAML
researcher:
  role: Senior Research Analyst
  goal: Find current information on {topic}
  backstory: >
    You are a meticulous analyst with a decade of experience.
    You cite sources and never speculate.

writer:
  role: Tech Writer
  goal: Turn research notes into a 200-word brief
  backstory: >
    You write punchy, jargon-light explainers for engineering managers.

Loading YAML in Python

Project crews typically combine @CrewBase with @before_kickoff for input checks, then factory methods marked @agent, @task, and a single @crew assembler.

PYTHON
from crewai.project import CrewBase, agent, task, crew, before_kickoff

@CrewBase
class ResearchCrew:
    agents_config = "config/agents.yaml"
    tasks_config = "config/tasks.yaml"

    @agent
    def researcher(self): return Agent(config=self.agents_config["researcher"])

    @task
    def research_task(self): return Task(config=self.tasks_config["research_task"])

    @crew
    def crew(self): return Crew(agents=self.agents, tasks=self.tasks, process=Process.sequential)

Notes

LLM workers are memory-heavy

Concurrency limits should account for model client buffers, not only CPU. Set worker autoscaling on queue latency and GPU or RAM pressure, not just request count.

Graceful shutdown must drain queues

Killing pods mid-kickoff creates zombie external actions. Stop accepting new jobs, wait for in-flight crews with budgets, and mark partial results explicitly.

Secrets belong in vaults, not repo config

Docker images should mount runtime secrets. Baking keys into layers is a common regression when moving from laptops to Kubernetes.

Health checks should validate model reachability

HTTP 200 on your API does not prove OpenAI or Anthropic is healthy. Lightweight provider probes prevent routing traffic into guaranteed failures.

CrewAI production FAQ

How should I expose CrewAI over HTTP?

Put a thin API layer in front that authenticates callers, validates inputs, enqueues work, and streams results or webhooks instead of blocking workers.

What queueing pattern fits CrewAI workloads?

Use a durable queue with retries and dead-letter handling because LLM calls are slow and may fail transiently. Never run unbounded synchronous crews inside web request threads.

How do I package CrewAI in Docker?

Bake dependencies, pin versions, inject secrets at runtime, and ship non-root users with read-only root filesystems where possible.

What health checks matter for CrewAI services?

Check dependency connectivity to model providers, queue depth, worker liveness, and periodic smoke kickoffs that validate credentials.

How do I roll out CrewAI changes safely?

Use feature flags, shadow traffic, and golden eval suites so prompt or model updates do not silently regress customer-facing automation.

See also: DevShelfHub's CrewAI tool review for a product-level comparison, pricing notes, and links back into this tutorial series.

Quick jump: API Reference