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 configuredCHAT_MODEL; the platform default when nothing is set iszai/GLM-5.2. Pin one in code withcrusoe.foundry_model("nvidia/NVIDIA-Nemotron-3-Super-120B-A12B"), or bring your own native model (for examplecrewai.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
- Deploy. The CLI sees
crew.pyand auto-detects the framework ascrewai:
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
- 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)'}
- Clean up when you're done:
platformctl delete my-crew-agent