docs/edge/en/enterprise/guides/prepare-for-deployment.mdx
In CrewAI AMP, automations is the umbrella term for deployable Agentic AI projects. An automation can be either:
Understanding which type you're deploying is essential because they have different project structures and entry points.
| Aspect | Crew | Flow |
|---|---|---|
| Project structure | Project root with crew.jsonc and agents/ | src/project_name/ with crews/ folder |
| Main logic location | crew.jsonc (classic: src/project_name/crew.py) | src/project_name/main.py (Flow class) |
| Entry point function | Loaded from crew.jsonc (classic: run() in main.py) | kickoff() in main.py |
| pyproject.toml type | type = "crew" | type = "flow" |
| CLI create command | crewai create crew name | crewai create flow name |
| Config location | crew.jsonc, agents/, optional tools/ | src/project_name/crews/crew_name/config/ or embedded JSON crew folders |
| Can contain other crews | No | Yes (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:
CrewAI uses uv for dependency management. The uv.lock file ensures reproducible builds and is required for deployment.
# 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:
uv lock
git add uv.lock
git commit -m "Add uv.lock for deployment"
git push
```jsonc crew.jsonc
{
"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.
```python
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:
```bash
crewai run
```
```python
# 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()
```
```python
# 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:
Run these commands from your project root to quickly verify your setup:
# 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"
| Mistake | Symptom | Fix |
|---|---|---|
Missing uv.lock | Build fails during dependency resolution | Run uv lock and commit |
Wrong type in pyproject.toml | Build succeeds but runtime fails | Change to correct type |
Missing crew.jsonc or agents/ in a JSON-first crew | Crew definition not found | Keep crew.jsonc and agents/ at the project root |
Missing @CrewBase decorator in a classic crew | "Config not found" errors | Add decorator to all classic crew classes |
Classic files at root instead of src/ | Entry point not found | Move classic Python files to src/project_name/ |
Missing run() or kickoff() | Cannot start automation | Add correct entry function |
Once your project passes all checklist items, you're ready to deploy:
<Card title="Deploy to AMP" icon="rocket" href="/en/enterprise/guides/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. </Card>