Skip to main content

Build agents with CrewAI

CrewAI is an open-source Python framework where you describe agents by role ("Research Buddy"), give them tasks, and group them into a crew that works through the tasks. The platform runs unmodified CrewAI crews. This page gives you the author contract, the Crusoe helpers, and a complete crew you can deploy right now.

Before you begin

  • You can deploy: account, CLI, and sign-in per deploy an agent.
  • Python knowledge. You do not need CrewAI installed locally to deploy — the build happens on the platform.

The contract

Your directory must contain a crew.py that defines a module-level variable named crew — either a crewai.Crew object, or a zero-argument function that returns one (a factory, useful if you want a fresh crew per request).

There is one CrewAI-specific rule on top of that: a task description must reference {message}. That placeholder is how the user's incoming message reaches your crew — the harness fills it in on every turn. Reference {history} too, and prior turns of the conversation are handed to your crew explicitly:

  • With {history} in a task description: the harness replays earlier turns into it, and {message} carries only the current message. This is the clear, recommended form.
  • Without {history}: the harness folds the prior turns into {message} instead, so turn 2 still sees turn 1 — multi-turn chat works either way.

If the module-level crew is missing, your agent crash-loops at startup and the harness startup error appears in the agent's status message.

An optional requirements.txt is installed at build time, constrained against the base image's frozen dependency set: a conflicting version pin fails the build with a readable error in the status message field, rather than crash-looping the pod later.

What the base image already provides

The CrewAI base image ships crewai, crewai-tools, and the first-party crusoe_crewai package (plus its crusoe_core support library), on Python 3.12. Most crews need no extra dependencies.

The Crusoe helpers: crusoe_crewai

import crusoe_crewai as crusoe
  • crusoe.foundry_model() — returns a CrewAI-compatible LLM wired to the platform's managed inference endpoint (OpenAI-compatible). With no arguments it uses the configured CHAT_MODEL; the platform default when nothing is set is zai/GLM-5.2. Pin one in code with crusoe.foundry_model("nvidia/NVIDIA-Nemotron-3-Super-120B-A12B"), or bring your own native model (for example crewai.LLM(model="gemini/gemini-2.5-flash") with your own credentials) — the harness runs it as-is.
  • crusoe.RunPython() — a tool class (note: you instantiate it) that runs Python in the platform's code sandbox — isolated, single-use, capped at 20 seconds.
  • crusoe.SearchMemory() — a tool class that searches the agent's long-term memory bank and returns the top 5 snippets.

The platform tools run in-process; tools you author yourself are sandboxed by default (TOOL_SANDBOX, set env TOOL_SANDBOX=false to opt out). See tools.

Complete example: crewai-minimal

The platform's canonical CrewAI example, complete and runnable as-is. Two files.

my-crew-agent/crew.py:

"""crewai-minimal - a trivial CrewAI agent for the Crusoe platform.

THE AUTHOR CONTRACT:
* Expose a module-level ``crew`` (a crewai.Crew or a zero-arg factory
returning one).
* A task description MUST reference ``{message}`` (that is how the user's
input reaches the model). Reference ``{history}`` too so multi-turn
resume is explicit - the harness replays prior turns from the canonical
event log into ``{history}``. (If a crew omits ``{history}``, the
adapter folds prior turns into ``{message}`` instead, so turn 2 still
sees turn 1 - but referencing it here is the clear form.)
"""
from crewai import Agent, Crew, Process, Task

import crusoe_crewai as crusoe

research_buddy = Agent(
role="Research Buddy",
goal="Help the user by computing things and recalling what you were told to remember.",
backstory=(
"A concise research assistant running on the Crusoe AI Platform. You use tools "
"for calculations and to recall remembered facts, and you answer plainly."
),
# foundry_model() with no args uses the platform default (zai/GLM-5.2
# unless CHAT_MODEL is injected/overridden). Override by name with
# crusoe.foundry_model("nvidia/NVIDIA-Nemotron-3-Super-120B-A12B"), or
# bring your own native model (e.g. crewai.LLM(model="gemini/gemini-2.5-flash")).
llm=crusoe.foundry_model(),
tools=[crusoe.RunPython(), crusoe.SearchMemory()],
verbose=False,
)

respond = Task(
description=(
"Prior conversation (may be empty on the first turn):\n{history}\n\n"
"Now respond to the user's current message:\n{message}\n\n"
"Use the run_python tool for any calculation, and the search_memory tool to "
"recall things you were told to remember."
),
expected_output="A helpful, concise answer to the user's current message.",
agent=research_buddy,
)

# The module-level object the platform discovers.
crew = Crew(
agents=[research_buddy],
tasks=[respond],
process=Process.sequential,
verbose=False,
)

my-crew-agent/requirements.txt:

# No extra dependencies - crewai, crewai-tools and crusoe_crewai (+ crusoe_core)
# are provided by the harness-crewai base image. Add any agent-specific PyPI
# packages here; they are installed on top of the base image and constrained
# against its frozen dependency set, so a conflicting pin fails at build time,
# not at cold start.

Deploy and test it

  1. Deploy. The CLI sees crew.py and auto-detects the framework as crewai:
platformctl deploy ./my-crew-agent --name my-crew-agent

You should see:

packaging ./my-crew-agent...
uploading my-crew-agent (1.9 KiB, framework=crewai)...
build 4e5f6a7b-8c9d-4e0f-a1b2-c3d4e5f6a7b8 accepted
status: -> building
status: building -> deploying
status: deploying -> ready
my-crew-agent is ready at http://my-crew-agent.cai-p-x7k2q.svc.cluster.local
  1. Talk to it. Once deployed, a CrewAI agent answers the exact same HTTP API as every other agent — callers can't tell the frameworks apart:
platformctl invoke my-crew-agent "Compute 2**32 in python."

You should see:

2**32 is 4294967296.
(session: 1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d)
tool_call: run_python called with args={'code': 'print(2**32)'}
  1. Clean up when you're done:
platformctl delete my-crew-agent

Next steps

  • Invoke — sessions, streaming, and the full request/response shapes.
  • Sessions — how {history} gets filled in.
  • Tools — write your own tool functions.
  • Same agent, other frameworks: ADK, LangGraph.