# CrewAI

[CrewAI](https://docs.crewai.com) builds crews of role-playing agents that hand
work to each other. Point its `LLM` class at Hyphen and every agent in the crew
uses it.

```bash
pip install crewai
export HYPHEN_API_KEY="sk-..."
```

*Setup guide: this config comes from CrewAI's official documentation and has
not been run end to end against the gateway. Corrections to [support@hyphen-solution.com](mailto:support@hyphen-solution.com).*

## The model

```python
import os
from crewai import LLM

llm = LLM(
    model="openai/minimax-m3",
    custom_openai=True,
    base_url="https://api.hyphen-solution.com/v1",
    api_key=os.environ["HYPHEN_API_KEY"],
    max_tokens=4000,
)
```

:::note[On the `openai/` prefix and `custom_openai`]
CrewAI 1.x infers a provider from the model string. A name with no slash falls
through to an OpenAI-shaped client by default, so bare `model="minimax-m3"`
usually works. Do not rely on inference.

`custom_openai=True` forces the native OpenAI client and makes `base_url`
mandatory, which is exactly the behaviour you want for a gateway. The `openai/`
prefix is stripped before the request, so Hyphen still receives `minimax-m3`.

If `custom_openai` is rejected by your installed version, drop the flag and use
`model="minimax-m3"` with no prefix.
:::

## A crew

```python
import os
from crewai import LLM, Agent, Task, Crew

llm = LLM(
    model="openai/minimax-m3",
    custom_openai=True,
    base_url="https://api.hyphen-solution.com/v1",
    api_key=os.environ["HYPHEN_API_KEY"],
    max_tokens=4000,
)

researcher = Agent(
    role="Researcher",
    goal="Find concise, verifiable facts about {topic}",
    backstory="You are a meticulous research analyst who hates padding.",
    llm=llm,
    verbose=True,
)

writer = Agent(
    role="Writer",
    goal="Turn research notes into tight prose",
    backstory="You write like a developer. Short sentences. No filler.",
    llm=llm,
    verbose=True,
)

research_task = Task(
    description="Write three key facts about {topic}.",
    expected_output="A bullet list of exactly three facts.",
    agent=researcher,
)

write_task = Task(
    description="Turn the research into a single paragraph a developer would read.",
    expected_output="One paragraph, at most five sentences.",
    agent=writer,
    context=[research_task],
)

crew = Crew(agents=[researcher, writer], tasks=[research_task, write_task], verbose=True)
print(crew.kickoff(inputs={"topic": "the Voyager probes"}))
```

## Mixing models in one crew

Crews are where per-agent model choice actually pays off. Put the flagship on
the agent that plans, and the fast model on the agents that do bulk work.

```python
flagship = LLM(
    model="openai/minimax-m3",
    custom_openai=True,
    base_url="https://api.hyphen-solution.com/v1",
    api_key=os.environ["HYPHEN_API_KEY"],
    max_tokens=4000,
)

fast = LLM(
    model="openai/minimax-m2.5",
    custom_openai=True,
    base_url="https://api.hyphen-solution.com/v1",
    api_key=os.environ["HYPHEN_API_KEY"],
    max_tokens=4000,
)

planner = Agent(role="Planner", goal="...", backstory="...", llm=flagship)
summariser = Agent(role="Summariser", goal="...", backstory="...", llm=fast)
```

Both meter at the same per-token rate. The saving is that `minimax-m2.5` is
terser, not that it is cheaper per token. See
[Choosing a model](/choosing-a-model).

## Watch the budget

Crews are the easiest way to spend a monthly cap by accident. Every agent
handoff is a fresh request carrying the accumulated context, so a five-agent
crew on a long task can burn through tokens fast.

Two things help. Set `max_iter` on agents so a stuck agent cannot loop forever,
and test with `minimax-m2.5` before switching the crew to `minimax-m3`.

```python
researcher = Agent(
    role="Researcher",
    goal="...",
    backstory="...",
    llm=llm,
    max_iter=8,
)
```

The hard cap is still the backstop. A runaway crew returns 429 rather than an
invoice. See [Rate limits & caps](/rate-limits).

## Gotchas

- **`max_tokens` of 4000.** CrewAI agents use tools heavily and the M-series
  reason before every call. See
  [Choosing a model](/choosing-a-model#the-max_tokens-gotcha).
- **No embedding models.** CrewAI's memory features need an embedder. Configure
  a local or third-party one, since the Hyphen catalog has none.
- **`429`** means the monthly budget is spent. See
  [Handling the 429 cap](/recipes/handling-429).

## Related

- [CrewAI LLM docs](https://docs.crewai.com/en/concepts/llms)
- [CrewAI LLM connections](https://docs.crewai.com/en/learn/llm-connections)
- [Choosing a model](/choosing-a-model): which agent gets which model.
