Skip to content

Prepare for Deployment

In CrewAI AMP, automations is the umbrella term for deployable Agentic AI projects. An automation can be either:

  • A Crew: A standalone team of AI agents working together on tasks
  • A Flow: An orchestrated workflow that can combine multiple crews, direct LLM calls, and procedural logic

Understanding which type you’re deploying is essential because they have different project structures and entry points.

Crew Projects

Standalone AI agent teams. New crews are JSON-first with crew.jsonc and agents/; classic crews can still use crew.py.

Flow Projects

Orchestrated workflows with embedded crews in a crews/ folder. Best for complex, multi-stage processes.

AspectCrewFlow
Project structureProject root with crew.jsonc and agents/src/project_name/ with crews/ folder
Main logic locationcrew.jsonc (classic: src/project_name/crew.py)src/project_name/main.py (Flow class)
Entry point functionLoaded from crew.jsonc (classic: run() in main.py)kickoff() in main.py
pyproject.toml typetype = "crew"type = "flow"
CLI create commandcrewai create crew namecrewai create flow name
Config locationcrew.jsonc, agents/, optional tools/src/project_name/crews/crew_name/config/ or embedded JSON crew folders
Can contain other crewsNoYes (in crews/ folder)

When you run crewai create crew my_crew, you get the JSON-first structure:

my_crew/
├── .gitignore
├── pyproject.toml # Must have type = "crew"
├── README.md
├── .env
├── uv.lock # REQUIRED for deployment
├── crew.jsonc # Crew settings, tasks, process, inputs
├── agents/
│ └── researcher.jsonc # Agent definitions
├── tools/ # Optional custom:<name> tools
├── knowledge/
└── skills/

When you run crewai create flow my_flow, you get this structure:

my_flow/
├── .gitignore
├── pyproject.toml # Must have type = "flow"
├── README.md
├── .env
├── uv.lock # REQUIRED for deployment
└── src/
└── my_flow/
├── __init__.py
├── main.py # Entry point with kickoff() function + Flow class
├── crews/ # Embedded crews folder
│ └── poem_crew/
│ ├── __init__.py
│ ├── poem_crew.py # Crew with @CrewBase decorator
│ └── config/
│ ├── agents.yaml
│ └── tasks.yaml
└── tools/
├── __init__.py
└── custom_tool.py

Use this checklist to verify your project is ready for deployment.

Your pyproject.toml must include the correct [tool.crewai] section:

For Crews
[tool.crewai]
type = "crew"
For Flows
[tool.crewai]
type = "flow"

CrewAI uses uv for dependency management. The uv.lock file ensures reproducible builds and is required for deployment.

Terminal window
# Generate or update the lock file
uv lock
# Verify it exists
ls -la uv.lock

If the file doesn’t exist, run uv lock and commit it to your repository:

Terminal window
uv lock
git add uv.lock
git commit -m "Add uv.lock for deployment"
git push
JSON-first Crews

JSON-first crews must have a crew.jsonc or crew.json file at the project root. The agents array must reference files in agents/, and each task should reference a valid agent name.

{
"name": "Research Crew",
"agents": ["researcher"],
"tasks": [
{
"name": "research_task",
"description": "Research {topic}.",
"expected_output": "A concise report.",
"agent": "researcher"
}
],
"inputs": {
"topic": "AI Agents"
}
}

Custom tools are referenced as "custom:<name>" and must be implemented in tools/<name>.py with a BaseTool subclass.

Classic Python/YAML Crews

Classic crews and Python crews embedded in Flows must use the @CrewBase decorator.

from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from crewai.agents.agent_builder.base_agent import BaseAgent
from typing import List
@CrewBase
class MyCrew():
"""My crew description"""
agents: List[BaseAgent]
tasks: List[Task]
@agent
def my_agent(self) -> Agent:
return Agent(
config=self.agents_config['my_agent'], # type: ignore[index]
verbose=True
)
@task
def my_task(self) -> Task:
return Task(
config=self.tasks_config['my_task'] # type: ignore[index]
)
@crew
def crew(self) -> Crew:
return Crew(
agents=self.agents,
tasks=self.tasks,
process=Process.sequential,
verbose=True,
)

JSON-first standalone crews do not need a hand-written src/project_name/main.py; crewai run and deployment packaging load crew.jsonc directly. Classic crews and Flows use Python entry points:

JSON-first Crews

Run locally from the project root:

Terminal window
crewai run
Classic Crews

The entry point uses a run() function:

src/my_crew/main.py
from my_crew.crew import MyCrew
def run():
"""Run the crew."""
inputs = {'topic': 'AI in Healthcare'}
result = MyCrew().crew().kickoff(inputs=inputs)
return result
if __name__ == "__main__":
run()
For Flows

The entry point uses a kickoff() function with a Flow class:

src/my_flow/main.py
from crewai.flow import Flow, listen, start
from my_flow.crews.poem_crew.poem_crew import PoemCrew
class MyFlow(Flow):
@start()
def begin(self):
# Flow logic here
result = PoemCrew().crew().kickoff(inputs={...})
return result
def kickoff():
"""Run the flow."""
MyFlow().kickoff()
if __name__ == "__main__":
kickoff()

Before deployment, ensure you have:

  1. LLM API keys ready (OpenAI, Anthropic, Google, etc.)
  2. Tool API keys if using external tools (Serper, etc.)

Run these commands from your project root to quickly verify your setup:

Terminal window
# 1. Check project type in pyproject.toml
grep -A2 "\[tool.crewai\]" pyproject.toml
# 2. Verify uv.lock exists
ls -la uv.lock || echo "ERROR: uv.lock missing! Run 'uv lock'"
# 3. For JSON-first crews, verify crew.jsonc and agents/ exist
([ -f crew.jsonc ] || [ -f crew.json ]) || echo "No crew.jsonc or crew.json found"
test -d agents || echo "No agents/ directory found"
# 4. For classic Crews - verify crew.py exists
ls -la src/*/crew.py 2>/dev/null || echo "No crew.py (expected for Crews)"
# 5. For Flows - verify crews/ folder exists
ls -la src/*/crews/ 2>/dev/null || echo "No crews/ folder (expected for Flows)"
# 6. For classic Python crews - check for CrewBase usage
grep -r "@CrewBase" . --include="*.py"
MistakeSymptomFix
Missing uv.lockBuild fails during dependency resolutionRun uv lock and commit
Wrong type in pyproject.tomlBuild succeeds but runtime failsChange to correct type
Missing crew.jsonc or agents/ in a JSON-first crewCrew definition not foundKeep crew.jsonc and agents/ at the project root
Missing @CrewBase decorator in a classic crew”Config not found” errorsAdd decorator to all classic crew classes
Classic files at root instead of src/Entry point not foundMove classic Python files to src/project_name/
Missing run() or kickoff()Cannot start automationAdd correct entry function

Once your project passes all checklist items, you’re ready to deploy:

Deploy to AMP

Follow the deployment guide to deploy your Crew or Flow to CrewAI AMP using the CLI, web interface, or CI/CD integration.