Advanced: editorial pipeline with a crew (CrewAI)
One agent asked to "research this and write a well-checked article" will do all four jobs in a single pass and grade its own work. The failure is specific and predictable: the fact-check never happens, because the model that just wrote a claim is the worst available reviewer of it.
This guide builds four specialists instead, and the thing that makes it work is not the number of agents — it is that each one has a different toolset.
Source: examples/agents/crewai-editorial.
What you need
- A project, and
platformctl logindone once. - About 20 minutes.
- Optional: one or more MCP servers in the project. The crew runs without them.
The shape
| Agent | Tools | Why those |
|---|---|---|
| Researcher | memory, sandbox, research MCP | Needs to look things up. |
| Writer | memory only | A writer that can look things up mid-sentence drifts off the brief. |
| Fact checker | memory, research MCP | Needs sources; is given no writing task, so it reports rather than quietly rewrites. |
| Editor | memory, publishing MCP | Resolves findings and produces the final text. |
The writer's missing tools are not tidiness. They are the mechanism.
Per-agent toolsets
mcp_tools(names=...) narrows an agent to named MCP servers:
research_tools = crusoe.mcp_tools(names=_research_names) if _research_names else []
publishing_tools = crusoe.mcp_tools(names=_publishing_names) if _publishing_names else []
mcp_tools(names=[...]) raises UnknownMCPServer and the agent fails to
start, restarting in a loop.
It does not return the subset it found.
That is the right default — an agent that quietly loses half its tools looks
like a model that suddenly got worse — but it means a literal
names=["research"] in an example would break for every reader whose project
has no server by that name. So this example reads the names from the
environment:
platformctl agents env set editorial RESEARCH_MCP=research,docs
platformctl agents env set editorial PUBLISHING_MCP=publishing
Unset means "no MCP tools for that role", and the crew still runs.
The default — mcp_tools() with no names — attaches every server the
project has. That is right for a general assistant, because publishing a new
tool then needs no agent change, and wrong here, where the whole point is that
the writer cannot research.
Shared memory
Every agent gets the same SearchMemory, reading the project's VectorDB:
memory = crusoe.SearchMemory()
So a fact established in an earlier run is available to all four, and the fact checker can recognise a claim the team already verified instead of re-deriving it. The researcher's task says to call it first, for the same reason a lookup beats a search.
The tasks
Each task names its context — the earlier tasks whose output it may read:
check = Task(
description=(
"Check the draft against the findings. List every claim the findings do "
"not support, quoting the sentence. Do NOT rewrite the draft - a rewrite "
"hides the problem instead of reporting it. If everything checks out, say "
"so in one line."
),
expected_output="A list of unsupported claims, each quoted, or a one-line all-clear.",
agent=fact_checker,
context=[research, draft],
)
"Do NOT rewrite" is load-bearing. Without it a checking model edits the draft and reports success, and the reader never learns which claims were weak.
process=Process.sequential
The order is the editorial process. Under Process.hierarchical a manager
agent re-decides that order on every run, which turns four specialists back into
one prompt with extra steps.
Deploy and run it
platformctl deploy ./examples/agents/crewai-editorial \
--name editorial --framework crewai
platformctl invoke editorial \
'Write 300 words on how our retention policy changed this year.'
The numbers to compare against
Measured on a warm instance, asking for a 120-word piece:
| What | Number |
|---|---|
| Four stages, brief to finished text | ~17 s |
| Same job as a single prompt | 5-8 s |
| Tool calls in the run | search_memory first, then run_python to count the words |
That is the trade this guide is making, and it is worth being explicit: four specialists is roughly 2-3x the latency and 3-4x the tokens of one prompt doing the job badly. What you get is a fact-check that actually ran, and a word count the writer verified rather than estimated - the run above hit exactly 120. For a chat assistant it is the wrong trade; for anything published under your name it is usually the right one.
Cold start adds 8-12 seconds — more than the LangGraph agent, because the CrewAI base image is larger.
Traps, at the point you hit them
| Trap | What you see | Why |
|---|---|---|
names= a server you do not have | The agent fails to start, in a restart loop | UnknownMCPServer. Fail-closed on purpose. Check platformctl mcp list. |
| Writer given research tools | Drafts wander off the brief and runs get slower | It looks things up mid-sentence. Keep its toolset to memory. |
| Fact checker allowed to rewrite | Every run reports "all clear" | It fixed the problems silently. The "Do NOT rewrite" line is what stops it. |
Process.hierarchical | Stage order changes run to run | A manager agent re-plans the pipeline. Use sequential. |
No {message} in the first task | The crew ignores what you asked | The harness substitutes {message} and {history}; a task without them gets no input. |
| Timeout at 60 s | 504 on a long piece | Four stages exceed the default request timeout. Raise it: platformctl agents config set editorial --timeout 300. |
That last one is the trap most people hit first. A single-agent prompt fits comfortably inside the 60-second default; a four-stage pipeline often does not.
Teardown
platformctl delete editorial
What it costs to leave running. The agent scales to zero, so an idle crew costs no compute. Its memory bank holds VectorDB storage until the agent is deleted, and each revision holds two entries against the Services quota. The attached MCP servers are separate resources with their own lifecycle — deleting this agent does not delete them.
Where next
- Multi-step research agent (LangGraph) — graph state and a scheduled refresh.
- MCP servers — publishing the tools this crew narrows to.
- Memory — what the shared store holds, and its scopes.