How to Integrate CrewAI for healthcare with FastAPI for startups

By Cyprian AaronsUpdated 2026-04-22
crewai-for-healthcarefastapistartups

Combining CrewAI for healthcare with FastAPI gives you a clean way to expose multi-agent clinical workflows as HTTP endpoints. For startups, that means you can turn intake triage, symptom summarization, prior-auth prep, or patient support routing into an API your product can call directly.

The pattern is simple: FastAPI handles request validation, auth, and transport; CrewAI handles the agent orchestration behind the scenes. That separation keeps your healthcare agent system easier to test, safer to deploy, and less painful to extend.

Prerequisites

  • Python 3.10+
  • fastapi
  • uvicorn
  • crewai
  • A valid LLM provider key configured in environment variables
  • Basic understanding of Pydantic models
  • A healthcare-safe workflow design:
    • no autonomous diagnosis
    • no PHI logging
    • human review for high-risk outputs

Install the dependencies:

pip install fastapi uvicorn crewai pydantic

Set your environment variables:

export OPENAI_API_KEY="your-key"

Integration Steps

  1. Define the FastAPI request and response models

Keep the API contract strict. In healthcare workflows, you want explicit inputs like patient context, symptoms, and task type rather than free-form prompts.

from pydantic import BaseModel, Field
from typing import Optional, List

class PatientIntakeRequest(BaseModel):
    patient_id: str = Field(..., examples=["pt_123"])
    age: int
    symptoms: List[str]
    notes: Optional[str] = None

class PatientIntakeResponse(BaseModel):
    summary: str
    risk_level: str
    next_action: str
  1. Build CrewAI agents and tasks for healthcare intake

CrewAI’s core objects are Agent, Task, and Crew. Use them to split work between summarization and risk classification.

from crewai import Agent, Task, Crew, Process

intake_analyst = Agent(
    role="Healthcare Intake Analyst",
    goal="Summarize patient intake data into a concise clinical note",
    backstory="You help care teams convert structured intake into readable summaries.",
    verbose=True,
)

risk_triage_agent = Agent(
    role="Clinical Risk Triage Assistant",
    goal="Assign a conservative risk level based on reported symptoms",
    backstory="You flag urgent cases for human review and avoid diagnosis.",
    verbose=True,
)

def build_crew(patient_data: dict) -> Crew:
    summarize_task = Task(
        description=(
            f"Summarize this intake data into a short clinical note:\n"
            f"Patient ID: {patient_data['patient_id']}\n"
            f"Age: {patient_data['age']}\n"
            f"Symptoms: {', '.join(patient_data['symptoms'])}\n"
            f"Notes: {patient_data.get('notes', '')}"
        ),
        expected_output="A concise clinical summary.",
        agent=intake_analyst,
    )

    triage_task = Task(
        description=(
            "Review the intake summary and assign one of these risk levels: "
            "low, medium, high. Recommend the next action."
        ),
        expected_output="Risk level plus next action.",
        agent=risk_triage_agent,
        context=[summarize_task],
    )

    return Crew(
        agents=[intake_analyst, risk_triage_agent],
        tasks=[summarize_task, triage_task],
        process=Process.sequential,
        verbose=True,
    )
  1. Expose the CrewAI workflow through a FastAPI endpoint

This is where the integration becomes useful. Your app receives JSON, runs the crew synchronously or asynchronously, then returns structured output.

from fastapi import FastAPI, HTTPException

app = FastAPI(title="Healthcare Agent API")

@app.post("/intake", response_model=PatientIntakeResponse)
async def analyze_intake(payload: PatientIntakeRequest):
    try:
        crew = build_crew(payload.model_dump())
        result = crew.kickoff()
        
        # Result parsing depends on your task formatting.
        # Keep it deterministic in production by enforcing JSON outputs.
        return PatientIntakeResponse(
            summary=str(result),
            risk_level="medium",
            next_action="Route to clinician review",
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
  1. Run FastAPI with Uvicorn and wire in basic operational safety

For startups building healthcare systems, don’t ship raw agent output directly without controls. Add request size limits at the gateway layer and keep PHI out of logs.

import uvicorn

if __name__ == "__main__":
    uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)

If you want cleaner downstream parsing, make the crew output JSON explicitly:

triage_task = Task(
    description=(
        "Return JSON with keys summary, risk_level, next_action.\n"
        "Use only low, medium, or high for risk_level."
    ),
    expected_output='{"summary": "...", "risk_level": "low", "next_action": "..."}',
    agent=risk_triage_agent,
)
  1. Add an async wrapper if you expect concurrent traffic

CrewAI calls can be slower than standard CRUD endpoints. If your startup expects multiple simultaneous requests, push execution off the main event loop.

from fastapi.concurrency import run_in_threadpool

@app.post("/intake-async", response_model=PatientIntakeResponse)
async def analyze_intake_async(payload: PatientIntakeRequest):
    crew = build_crew(payload.model_dump())
    result = await run_in_threadpool(crew.kickoff)

    return PatientIntakeResponse(
        summary=str(result),
        risk_level="medium",
        next_action="Queue for nurse review",
    )

Testing the Integration

Hit the endpoint with a real request payload using requests.

import requests

payload = {
    "patient_id": "pt_123",
    "age": 67,
    "symptoms": ["shortness of breath", "chest tightness"],
    "notes": "Started this morning after walking upstairs."
}

response = requests.post("http://localhost:8000/intake", json=payload)
print(response.status_code)
print(response.json())

Expected output:

200
{
  "summary": "...",
  "risk_level": "medium",
  "next_action": "Route to clinician review"
}

If you get a 500 error first time around, check these:

  • your LLM key is set correctly
  • task outputs are formatted consistently
  • your model prompt is not asking for diagnosis instead of triage

Real-World Use Cases

  • Patient intake triage API

    • Convert symptom forms into summaries and urgency flags for nurse review.
  • Prior authorization prep

    • Extract relevant chart details and generate payer-ready documentation drafts.
  • Care navigation assistant

    • Route patients to scheduling, education content, or escalation queues based on intake signals.

The clean architecture here is what matters. FastAPI gives you a stable service boundary; CrewAI gives you flexible multi-agent reasoning behind that boundary. For healthcare startups, that’s the difference between a demo and something you can actually put under load.


Keep learning

By Cyprian Aarons, AI Consultant at Topiax.

Want the complete 8-step roadmap?

Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.

Get the Starter Kit

Related Guides