Direct Answer
CrewAI is an agent-orchestration framework organized around Agents, Tasks, Crews, Processes, and Flows. Current documentation distinguishes two useful levels:
- a Crew is a unit of collaborative model work;
- a Flow owns application state and explicit control around one or more Crews.
New standalone Crew projects are documented as JSON-first, using crew.jsonc and agents/*.jsonc. The classic Python/YAML structure remains available. For production, current CrewAI guidance recommends starting with a Flow so state transitions, branches, persistence, and recovery are explicit.
The framework does not prove that multiple agents are better than one. Build the smallest baseline first, then add a Crew only when role separation creates measurable value.
Choose the Right Abstraction
| Need | Simplest useful abstraction |
|---|---|
| Deterministic transformation | ordinary code |
| One bounded model judgment | one model call with a typed result |
| One agent with tools | Agent |
| Role-separated collaborative task | Crew |
| State, branches, waits, recovery, several Crews | Flow |
| Durable business side effect | application service with authorization and idempotency |
A role name or backstory influences model behavior; it does not enforce capability. A tool list narrows what an Agent can request, but the tool service must still authenticate the caller, authorize the tenant and object, validate arguments, and control side effects.
Current Project Paths
JSON-first standalone Crew
The current Build Your First Crew guide documents this shape:
research_crew/
├── crew.jsonc
├── agents/
│ ├── researcher.jsonc
│ └── analyst.jsonc
├── tools/
├── knowledge/
├── skills/
├── pyproject.toml
└── uv.lock
Create and run it with the CLI version pinned by your project:
crewai create crew research_crew
cd research_crew
crewai install
crewai run
Do not copy an unversioned tutorial into production. Record the CrewAI package and CLI version, lock dependencies, and keep generated configuration under review.
Classic Python/YAML Crew
The classic project path still exists for decorator-based Python crews:
crewai create crew research_crew --classic
Use it when you need Python-level customization that the JSON-first surface does not express. Do not mix file layouts from different documentation versions and assume the loader will discover them.
Flow-first production application
The CrewAI production architecture guide recommends a Flow-first design. A Flow can own typed state, conditionals, waits, direct code, model calls, and Crew invocations.
The Flow is not a security boundary by itself. Identity, object authorization, network policy, secrets, and durable effects remain application responsibilities.
Build a Minimal JSON-First Research Crew
The example keeps the model identifier as a deployment value. Replace it with a provider/model ID supported by your pinned CrewAI version.
Define the researcher
agents/researcher.jsonc:
{
"role": "Research specialist for {topic}",
"goal": "Collect relevant claims and attach a source URL to each claim",
"backstory": "You separate sourced facts from analysis and mark missing evidence.",
"llm": "provider/model-id",
"tools": ["SerperDevTool"],
"settings": {
"verbose": false,
"allow_delegation": false,
"max_iter": 6,
"max_execution_time": 180
}
}
Tool names and settings are runtime contracts. Verify them against the exact release. A custom tool can execute local code when the project loads, so run only trusted Crew projects and review everything under tools/.
Define the analyst
agents/analyst.jsonc:
{
"role": "Evidence analyst for {topic}",
"goal": "Turn sourced findings into a concise report without inventing support",
"backstory": "You reject claims that lack a source and preserve uncertainty.",
"llm": "provider/model-id",
"settings": {
"verbose": false,
"allow_delegation": false,
"max_iter": 4,
"max_execution_time": 120
}
}
The analyst intentionally has no search tool. It can transform the research result but cannot silently fetch a new source outside the declared evidence path.
Define tasks and process
crew.jsonc:
{
"name": "Evidence Research Crew",
"agents": ["researcher", "analyst"],
"tasks": [
{
"name": "research",
"description": "Research {topic}. For every factual claim, include a source URL and a short statement of what that source supports.",
"expected_output": "Markdown with sections ## Findings, ## Unverified, and ## Sources. Every finding must cite a URL.",
"agent": "researcher"
},
{
"name": "report",
"description": "Use only the research task output. Remove unsupported claims and preserve disagreements or uncertainty.",
"expected_output": "A report with ## Findings, ## Unverified, and ## Sources. Do not introduce a new factual claim.",
"agent": "analyst",
"context": ["research"],
"output_file": "output/report.md",
"markdown": true
}
],
"process": "sequential",
"verbose": false,
"inputs": {
"topic": "retrieval evaluation"
}
}
This is intentionally sequential because the second task depends on the first. Two role names do not make the work parallel.
Sequential and Hierarchical Processes
The official Processes documentation defines:
sequential: tasks run in declared order and can pass prior output as context;hierarchical: a manager LLM or custom manager Agent plans, delegates, and validates tasks.
Hierarchical mode is useful when decomposition cannot be specified in advance and the available workers have meaningfully different capabilities. It adds calls, routing decisions, and possible loops. Set iteration, request-rate, wall-clock, and spend limits outside model control.
Do not use a manager as the only verifier. A manager is another model interaction and can share the workers' blind spots. Verify final artifacts with deterministic checks, executable tests, source review, or calibrated evaluators.
Why Production Guidance Is Flow-First
A Crew process is not a durable business workflow. Production systems often need:
- typed state that survives a process restart;
- idempotency keys and authoritative status checks;
- pause and resume for user input or approval;
- branches based on trusted policy, not model prose;
- cancellation and deadlines;
- compensation for partially committed work;
- versioned events for replay and incident analysis.
A Flow makes those transitions explicit, while Crews remain focused work units. Keep external side effects behind application services. A Crew may draft an email; a trusted service decides recipient, authorization, final content, idempotency, and send status.
Tool and Data Security
Least privilege per Agent
Give the researcher read-only search. Do not give the analyst shell, database write, or publishing tools merely because its role says “senior.” Capability follows actual tool credentials and server policy.
Treat tool output as untrusted
Search results, documents, issue comments, web pages, OCR, and other Agent messages can contain prompt injection. Preserve source identity and trust metadata, delimit content for model clarity, and keep authorization outside the prompt.
Keep secrets outside the workspace
Load provider keys from an approved secret mechanism. Do not write them into crew.jsonc, Agent files, generated reports, traces, or committed .env files. Review whether observability exports prompts, tool arguments, or customer data.
Bound custom code
Current JSON-first documentation warns that custom tool references load local Python code. Review source, dependencies, network access, filesystem access, and package lockfiles before running a third-party Crew project.
Output Contracts and Verification
An expected_output improves instructions but does not validate the result. Task guardrails and structured outputs can reject malformed artifacts, but the application still owns semantic and policy checks.
For a sourced report, verify:
- required sections exist;
- every factual finding has an allowed source;
- sources were actually fetched and support the claim;
- no secret or private source was copied into the output;
- duplicated or contradictory claims are resolved or marked;
- the report is within size and time budgets;
- an evaluator failure produces review, not silent acceptance.
Runnable Go Report Gate
This standard-library program validates a minimal structural contract for the generated Markdown. With a file path argument, it checks a real Crew output; without one, it uses a built-in fixture.
package main
import (
"fmt"
"os"
"regexp"
"strings"
)
var sourceURL = regexp.MustCompile(`https://[^\s)]+`)
func validate(report string) (int, error) {
for _, heading := range []string{"## Findings", "## Unverified", "## Sources"} {
if !strings.Contains(report, heading) {
return 0, fmt.Errorf("missing heading %q", heading)
}
}
sources := sourceURL.FindAllString(report, -1)
if len(sources) < 2 {
return 0, fmt.Errorf("need at least two source URLs")
}
if strings.Contains(report, "TODO") || strings.Contains(report, "source needed") {
return 0, fmt.Errorf("unresolved placeholder")
}
return len(sources), nil
}
func main() {
report := `# Report
## Findings
- Retrieval quality must be evaluated separately from generation.
## Unverified
- None.
## Sources
- https://example.com/source-a
- https://example.org/source-b
`
if len(os.Args) == 2 {
data, err := os.ReadFile(os.Args[1])
if err != nil {
panic(err)
}
report = string(data)
}
count, err := validate(report)
if err != nil {
panic(err)
}
fmt.Printf("report=valid sources=%d\n", count)
}
Expected output:
report=valid sources=2
This gate checks structure, not factual truth. A source-aware review must still confirm that each claim is supported by the cited page.
Evaluate Whether Multiple Agents Earn Their Cost
Compare at least three baselines:
- deterministic workflow without a model where possible;
- one Agent with the combined instructions and minimum tools;
- the proposed Crew or Flow.
Use the same cases, model snapshots, tools, timeouts, output contract, and evaluator. Measure:
- task success and harmful-error rate;
- source support and citation precision;
- handoff loss between tasks;
- loop, retry, and timeout rate;
- p95 completion time;
- total model and tool calls;
- cost per accepted result;
- operator review time.
Multi-agent architecture is justified only when role separation, parallel work, or dynamic delegation improves the target outcome enough to pay for coordination and operations.
Production Checklist
- Pin CrewAI, CLI, Python, provider SDK, tools, and model IDs.
- Choose JSON-first or classic layout explicitly; do not mix tutorials.
- Use a Flow when state, branches, waits, or recovery cross Crew boundaries.
- Make tool credentials task-scoped and enforce authorization inside each tool.
- Set iteration, request, time, byte, and spend limits.
- Persist durable state outside model context and reconcile unknown outcomes.
- Validate structured output and business semantics outside the model.
- Redact and bound traces; test deletion and tenant isolation.
- Compare against single-Agent and deterministic baselines.
- Shadow and canary changes with rollback.
Frequently Asked Questions
Should a new project start with a Crew or a Flow?
Start from the application boundary. A small standalone collaboration can begin as a JSON-first Crew. If the system needs durable state, branching, waits, several Crews, or recovery, use a Flow as the outer control plane.
Does allow_delegation: false enforce security?
No. It limits one framework behavior; it does not authenticate the caller, constrain a tool credential, authorize an object, or isolate code execution. Enforce those properties in trusted services and infrastructure.
Is hierarchical mode better for complex work?
Only if dynamic allocation improves measured outcomes. It adds a manager model, calls, latency, and loop risk. Compare it with a sequential Crew, a Flow with explicit branches, and a single Agent.
Can a Task guardrail replace application validation?
No. A guardrail can reject an output and request another attempt, but it runs inside the framework's execution path. Authorization, source verification, business invariants, and durable effects still belong to the application boundary.
How should CrewAI upgrades be tested?
Pin the old and new environments, replay permission-safe fixtures, and compare task outputs, tool calls, state transitions, retries, token usage, latency, and failure recovery. Verify both JSON-first and Flow loaders used by the deployed project.