This crewai n4n.ai first agent tutorial gets you from an empty directory to a running multi-agent crew in about ten minutes. We’ll point CrewAI at the n4n.ai OpenAI-compatible endpoint so you immediately get access to 240+ models behind one base URL, then write a small research-and-review crew that actually does useful work.
Step 1: Install CrewAI and create a project
Start in a clean Python environment. CrewAI ships as a standard package and pulls in LangChain components for LLM wiring.
python -m venv .venv
source .venv/bin/activate
pip install "crewai" "crewai-tools" "langchain-openai"
Create a working file main.py. In this crewai n4n.ai first agent tutorial we keep everything in one module so you can read top-to-bottom. If you prefer a package layout, split the agent and task definitions later.
Verify the install succeeded:
python -c "import crewai; print(crewai.__version__)"
You should see a version string like 0.30.0 or newer. CrewAI moves fast; the API below is stable across recent 0.3x releases.
Step 2: Configure the LLM endpoint
CrewAI uses LangChain’s ChatOpenAI under the hood, so any OpenAI-compatible base URL works. Set two environment variables before launching your process:
export OPENAI_API_KEY="sk-your-n4n-key"
export OPENAI_API_BASE="https://api.n4n.ai/v1"
The n4n.ai gateway forwards provider cache-control hints and honors client routing directives, so you can pin a model or let it fall back automatically when a provider is degraded. Your key is per-token metered, so you only pay for what the crew consumes.
In Python, read those vars and build the LLM client explicitly so the configuration is visible:
import os
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="openai/gpt-4o-mini",
temperature=0.7,
api_key=os.environ["OPENAI_API_KEY"],
base_url=os.environ["OPENAI_API_BASE"],
max_retries=3,
)
Use a model string that matches the gateway’s catalog. The openai/ prefix routes to OpenAI; anthropic/claude-3-5-sonnet would route to Anthropic. Because the endpoint is OpenAI-compatible, no other code changes are required to swap providers.
Step 3: Define your first agent
An agent in CrewAI is a role with a goal and a backstory. The backstory is not flavor text—it directly shapes the system prompt. Keep it concrete.
from crewai import Agent
researcher = Agent(
role="Senior Research Analyst",
goal="Find concise, authoritative facts on a given topic and structure them clearly",
backstory=(
"You have 10 years of experience distilling complex engineering "
"subjects into bullet points for busy CTOs."
),
llm=llm,
verbose=True,
allow_delegation=False,
)
verbose=True streams the agent’s reasoning to stdout, which is the fastest way to debug a misbehaving crew. allow_delegation=False prevents the agent from spawning sub-tasks in this minimal example.
Step 4: Define a task and assemble the crew
A task binds a description and an expected output format to an agent. Being strict about expected_output dramatically improves reliability.
from crewai import Task, Crew
research_task = Task(
description=(
"Research the current state of server-side WebAssembly runtimes. "
"Identify at least 3 mature options."
),
expected_output=(
"A markdown table with columns: name, maturity, language_support. "
"Each row must be one runtime."
),
agent=researcher,
)
crew = Crew(
agents=[researcher],
tasks=[research_task],
verbose=True,
)
Run it synchronously:
if __name__ == "__main__":
result = crew.kickoff()
print("\n--- FINAL CREW OUTPUT ---\n")
print(result)
By the end of this crewai n4n.ai first agent tutorial you will have executed this exact pattern and seen a structured table printed to your terminal.
Step 5: Run and verify success
Execute the script:
python main.py
You should see the agent’s internal steps (tool calls, thoughts) stream by, followed by the markdown table. A successful run looks like:
--- FINAL CREW OUTPUT ---
| name | maturity | language_support |
|--------------|----------|-------------------------|
| Wasmtime | High | Rust, C, C++, Python |
| Wasmer | High | Rust, JS, Go, Python |
| WasmEdge | Medium | Rust, C, JS |
Verification checklist:
- The process exits 0.
- The output contains a valid markdown table with ≥3 rows.
- Your gateway usage dashboard shows token consumption for the
openai/gpt-4o-miniroute.
If you get a 401, check the OPENAI_API_KEY. A 404 on the model usually means the model string prefix is wrong for the gateway’s catalog.
Step 6: Add a reviewer agent for collaboration
Real crews rarely consist of one agent. Add a second agent that consumes the first agent’s output and refines it. CrewAI runs tasks in the order they are listed unless you specify async execution.
reviewer = Agent(
role="Technical Editor",
goal="Ensure research output is accurate and well-structured",
backstory=(
"You are a meticulous editor with a background in developer "
"documentation at a cloud infrastructure company."
),
llm=llm,
verbose=True,
allow_delegation=False,
)
review_task = Task(
description=(
"Review the research table. Fix any factual errors and improve wording. "
"Do not add new runtimes unless clearly missing."
),
expected_output=(
"The same table, corrected and polished, plus a one-line note on changes made."
),
agent=reviewer,
)
crew = Crew(
agents=[researcher, reviewer],
tasks=[research_task, review_task],
verbose=True,
)
Because review_task depends on research_task, CrewAI resolves the dependency graph and passes the first result into the second agent’s context automatically. Run the script again; the final print now reflects the editor’s version.
Step 7: Control cost and routing
When you move past the quickstart, set temperature=0 for research agents to reduce hallucination, and use smaller models for editing passes. The gateway lets you mix providers in one crew without extra clients:
research_llm = ChatOpenAI(model="anthropic/claude-3-5-sonnet", base_url=os.environ["OPENAI_API_BASE"], api_key=os.environ["OPENAI_API_KEY"])
edit_llm = ChatOpenAI(model="openai/gpt-4o-mini", base_url=os.environ["OPENAI_API_BASE"], api_key=os.environ["OPENAI_API_KEY"])
researcher.llm = research_llm
reviewer.llm = edit_llm
This pattern keeps latency and cost down while preserving quality where it matters. The per-token metering means you can see exactly how much each agent spent.
Troubleshooting
Agent loops or produces empty output. Tighten expected_output. CrewAI agents obey format constraints far better when the contract is explicit.
Rate limit errors. The OpenAI-compatible gateway you configured handles automatic fallback when a provider is rate-limited or degraded, but you can also set max_retries on the LangChain client and add time.sleep between crew runs in batch jobs.
Model not found. List available model strings from the gateway’s /v1/models endpoint with curl -H "Authorization: Bearer $OPENAI_API_KEY" $OPENAI_API_BASE/models. Use the exact id field as your model argument.
Dependency conflicts. CrewAI pins LangChain versions. If you see ImportError, create a fresh venv as shown in Step 1 rather than mixing with an existing project.
Where to go next
You now have a reproducible skeleton: environment vars, one or more agents, typed tasks, and a crew that runs locally against a single inference endpoint. Extend it with crewai-tools (web search, file read) or break the main.py into agents.py, tasks.py, and run.py once the crew grows. The same code works if you later point OPENAI_API_BASE at a different compatible gateway—no agent logic changes.