> ## Documentation Index
> Fetch the complete documentation index at: https://docs.onecortex.io/llms.txt
> Use this file to discover all available pages before exploring further.

# CrewAI

> Deploy a CrewAI crew as it is: the prompt fills its task placeholder, and the crew's answer comes back streamed or whole.

## What is supported

CrewAI 1.x. Onecortex recognises a `Crew` and calls `kickoff`.

## A complete agent

```yaml agent.yml theme={null}
apiVersion: v1
runtime: python3.12
entrypoint: agent.py:crew
dependencies: requirements.txt
```

```text requirements.txt theme={null}
crewai>=1.0
```

```python agent.py theme={null}
from crewai import LLM, Agent, Crew, Task

# Reads OPENAI_API_KEY, which you add as a secret on the agent's Config tab.
llm = LLM(model="openai/gpt-5", stream=True)

researcher = Agent(
    role="Researcher",
    goal="Find the key facts about {topic}",
    backstory="You research topics thoroughly.",
    llm=llm,
)

research = Task(
    description="Research {topic} and list the five most important facts.",
    expected_output="Five facts about {topic}, one per line.",
    agent=researcher,
)

crew = Crew(agents=[researcher], tasks=[research])
```

Add `OPENAI_API_KEY` as a secret on the agent's **Config** tab, then deploy. Any model works: this one is an example. See [Configuration and secrets](/build/configuration).

<Card title="A complete CrewAI example" icon="github" href="https://github.com/onecortex-io/examples/tree/main/research-crew">
  `research-crew`: A researcher and a writer on two sequential tasks sharing one `{topic}` placeholder. It runs with no model key.
</Card>

## The prompt and the reply

A crew has no single input, so Onecortex fills a placeholder in its tasks with the prompt:

* One placeholder, such as `{topic}`: the prompt fills it.
* Several: the prompt fills the first of `{topic}`, `{question}`, `{input}` or `{query}` that appears.
* Several, none with those names: the call fails with a message listing them. Rename one, or wrap the crew in a function that builds the inputs.
* None: the crew runs with no inputs.

The reply is the crew's final output.

## Events it reports

| Events | From |
| - | - |
| `text` | The model's streamed text, when the model streams; otherwise the final output, once |
| `tool_call_start`, `tool_call_args`, `tool_call_end` | Each tool call, when the model streams |
| `step_start`, `step_end` | Each task, by name |
| `done` or `error` | The end of the run: always exactly one |

See [Streaming and events](/build/streaming).

## The caller's fields

A crew has no per run context, so fields beyond the prompt do not reach it. To use them, point the entrypoint at a function that reads them and calls `kickoff` itself:

```python theme={null}
def agent(prompt: str, request: dict) -> str:
    params = request["params"]
    return crew.kickoff(inputs={"topic": prompt, "audience": params.get("audience", "general")}).raw
```

See [A Python function](/frameworks/python-function).

## Known limits

* CrewAI reports no tool results, so tool calls appear without their outputs.
* A crew whose model does not stream sends its answer once, at the end, with no tool calls.
* A crew with several placeholders and none named `topic`, `question`, `input` or `query` needs a function wrapper.

## Troubleshooting

| You see | Do this |
| - | - |
| `This crew's tasks take more than one input and Onecortex cannot tell which one your prompt belongs in.` | Name the prompt's placeholder `{topic}`, `{question}`, `{input}` or `{query}`, or wrap the crew in a function. |
| The answer arrives all at once | Turn on streaming on the crew's model: `LLM(..., stream=True)`. |

More on [Troubleshooting](/production/troubleshooting) and [Errors](/production/errors).
