Skip to main content

Overview

CrewAI can plan at two levels:
  • Agent planning: an agent writes a step-by-step plan for its own work, then executes and checks each step. Configure it with Agent(planning_config=PlanningConfig(...)).
  • Crew planning: before the crew runs, a CrewPlanner writes a plan for every task and adds it to each task description. Enable it with Crew(planning=True).
You can use either one, or both together.

Agent planning

Pass a PlanningConfig to an agent to enable planning:
The presence of a PlanningConfig turns planning on. To turn it off, leave planning_config unset.

How it works

When the agent starts a task, it runs a plan-and-execute loop:
  1. Plan. The planning LLM writes a plan, asked to stay within max_steps steps, and says whether the plan is ready.
  2. Refine. If the plan is not ready, the planner refines it until it is ready or max_attempts is reached.
  3. Execute. Each step becomes a todo item and runs in its own tool loop, limited by max_step_iterations and step_timeout.
  4. Observe. After each step, the agent checks the result. How much it checks depends on reasoning_effort.
  5. Replan. Depending on reasoning_effort, a failed step or a plan that no longer fits makes the agent write a new plan, up to max_replans times.
  6. Answer. The agent builds the final answer from the step results.
The plan is kept in the agent’s execution state. It is not added to the task description. Step-by-step execution needs a ready plan with structured steps, which the planner gets through function calling. If the plan is still not ready after max_attempts, or the planning LLM does not support function calling, the agent runs its standard execution loop instead.

Reasoning effort

reasoning_effort controls what happens after each step: observe_steps overrides the LLM review at any level: True adds it to "low", and False removes it from "medium" and "high". With observe_steps=True, "low" also replans when the review says a failed step needs a new plan.

Configuration options

str
default:"medium"
How much the agent checks and adapts after each step: "low", "medium", or "high".
bool
default:"None"
Run an LLM review after each step. None reviews on "medium" and "high" only.
int
default:"None"
Maximum number of planning attempts, counting the first plan. None keeps refining until the planner marks the plan ready, which can add LLM calls. Set a number to bound it.
int
default:"20"
The step limit the planner is asked to respect. It is passed to the prompt as {max_steps} and is not enforced on the returned plan. Must be at least 1.
int
default:"3"
Maximum number of full replans before the agent finalizes its answer. 0 disables replanning.
int
default:"15"
Maximum LLM iterations for a single step. Lower values make steps faster but less thorough.
int
default:"None"
Maximum seconds for a single step, checked before each LLM call in the step. When it is exceeded, the step stops and returns what it has so far. The step is not marked as failed, and an LLM or tool call already running is not interrupted. None means no timeout.
str | BaseLLM
default:"None"
The LLM used for planning and for the review after each step. None uses the agent’s LLM.
str
default:"None"
Custom system prompt for planning. None uses the built-in prompt.
str
default:"None"
Custom prompt for the first plan. See Custom prompts below.
str
default:"None"
Custom prompt for refining a plan. See Custom prompts below.
Here is an agent that uses a separate, cheaper model for planning and bounds every part of the loop:

Custom prompts

plan_prompt and refine_prompt are filled in with Python’s str.format. These placeholders are available: If your prompts leave out {max_steps}, the planner is given no step limit.
Any other placeholder, or a literal { or }, makes planning fail. The agent then logs the error and runs without a plan. Write literal braces as {{ and }}.

Planning without a task

Planning also runs when you call an agent directly with kickoff(), without a Task or a Crew. The input message is used as the task description:

The planning=True shortcut

Agent(planning=True) enables a bounded, low-cost configuration. It is the same as PlanningConfig(reasoning_effort="low", max_attempts=1): one planning attempt and no LLM review after each step.
If you also pass planning_config, it takes precedence.

When planning fails

If an error occurs while the agent is planning, the error is logged and the agent runs the task without a plan.
reasoning=True and max_reasoning_attempts are deprecated. See Reasoning for how to migrate.

Crew planning

When crew planning is enabled, all crew information is sent to a CrewPlanner before the tasks run. It plans each task step by step and adds the plan to that task’s description.

Using crew planning

Add planning=True to your Crew. Each time the crew is kicked off, the CrewPlanner writes a plan like the one in the Result tab and adds each task’s part to that task’s description:

Planning LLM

Crew planning uses gpt-5.4-mini by default. Set planning_llm to a model name or an LLM instance to use another model, for example Crew(..., planning=True, planning_llm="gpt-5").
With the default planning LLM, crew planning needs a valid OpenAI API key, even if your agents use other providers. If you don’t have an OpenAI API key configured, set planning_llm to a model you can access.