n4nAI

Getting started with CrewAI and n4n.ai

A hands-on tutorial to crewai n4n.ai getting started: install CrewAI, point it at the OpenAI-compatible gateway, and run a multi-agent workflow.

n4n Team3 min read587 words

Audio narration

Coming soon — every post will get a voice note here.

If you’re working through crewai n4n.ai getting started, the fastest path is to treat the gateway as a drop-in OpenAI-compatible endpoint and point CrewAI’s LLM wrapper at it. This tutorial builds a two-agent research and writing crew that runs entirely against that endpoint, with no framework forks or custom adapters.

Prerequisites

  • Python 3.10 or newer
  • pip and a clean virtual environment
  • An API key for the gateway, exported as N4N_API_KEY
  • The gateway base URL https://api.n4n.ai/v1 (OpenAI-compatible)

CrewAI installs cleanly from PyPI. The only integration work is telling its LLM class where to send requests and which model name to route.

Step 1: Install CrewAI

Create and activate a virtual environment, then install the framework:

python -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install crewai

Verify the import works:

python -c "import crewai; print(crewai.__version__)"

Expected output is a version string like 0.30.0 (exact number depends on release).

Step 2: Export credentials

CrewAI reads standard OpenAI-style environment variables if you let it, but we’ll be explicit in code. Still, export the secrets so they don’t land in source control:

export N4N_API_KEY="sk-your-real-key"
export N4N_BASE_URL="https://api.n4n.ai/v1"

If you use a .env file, load it with python-dotenv before constructing the LLM.

Step 3: Construct the LLM handle

CrewAI’s LLM class wraps LangChain’s ChatOpenAI and accepts base_url. The gateway routes by model string, so you can request a provider/model pair directly.

import os
from crewai import LLM

llm = LLM(
    model="anthropic/claude-3.5-sonnet",
    base_url=os.environ["N4N_BASE_URL"],
    api_key=os.environ["N4N_API_KEY"],
    temperature=0.2,
    max_tokens=1024,
)

The model field is forwarded unchanged. A string like openai/gpt-4o-mini or meta-llama/llama-3.1-70b-instruct works as long as the gateway addresses it. Because the endpoint is OpenAI-compatible, CrewAI’s token counting and streaming behave exactly as they would against OpenAI.

Step 4: Define agents and tasks

We’ll build a research analyst and a technical writer. The writer depends on the researcher’s output via context.

from crewai import Agent, Task, Crew

researcher = Agent(
    role="Research Analyst",
    goal="Find concise facts about the Python GIL",
    backstory="You are a meticulous engineer who cites sources.",
    llm=llm,
    verbose=True,
)

writer = Agent(
    role="Technical Writer",
    goal="Turn research into a short briefing",
    backstory="You write crisp internal docs for backend teams.",
    llm=llm,
    verbose=True,
)

research_task = Task(
    description="Summarize what the Python GIL is and why it matters in 3 bullet points.",
    expected_output="Three bullet points with factual claims about the GIL.",
    agent=researcher,
)

write_task = Task(
    description="Convert the research into a 100-word internal briefing in markdown.",
    expected_output="A 100-word markdown briefing referencing the bullets.",
    agent=writer,
    context=[research_task],
)

crew = Crew(
    agents=[researcher, writer],
    tasks=[research_task, write_task],
    verbose=True,
)

Step 5: Run the crew

Kick off execution synchronously:

result = crew.kickoff()
print("=== FINAL RESULT ===")
print(result)

You’ll see agent thinking logs (because verbose=True) and then the final concatenated output. A representative truncated run looks like:

[Research Analyst] Task output:
- The GIL is a mutex that prevents multiple native threads from executing Python bytecodes simultaneously.
- It simplifies CPython memory management but blocks true multi-core parallelism for CPU-bound code.
- Workers often use multiprocessing or offload to C extensions to bypass it.

[Technical Writer] Task output:
# Python GIL Briefing
The Global Interpreter Lock (GIL) is a CPython mutex serializing bytecode execution. While it eases memory safety, it caps CPU-bound throughput on multi-core hosts. Teams typically adopt multiprocessing or native extensions to recover parallelism.

=== FINAL RESULT ===
# Python GIL Briefing
...

The result object exposes .raw and .tasks_output for programmatic consumption.

Step 6: Inspect usage and routing

The gateway returns OpenAI-compatible usage metadata. CrewAI doesn’t surface it directly on the result, but you can wrap the LLM call or inspect logs. If you need per-token metering, capture the response headers from a lower-level client:

from openai import OpenAI

client = OpenAI(
    base_url=os.environ["N4N_BASE_URL"],
    api_key=os.environ["N4N_API_KEY"],
)
resp = client.chat.completions.create(
    model="anthropic/claude-3.5-sonnet",
    messages=[{"role": "user", "content": "ping"}],
)
print(resp.usage.model_dump())

This prints prompt_tokens, completion_tokens, and total_tokens. The same metering applies to CrewAI runs because every agent turn goes through that endpoint.

Handling degradation without code changes

The OpenAI-compatible gateway you configured handles automatic fallback when an upstream provider is rate-limited or degraded. If you specify model="openai/gpt-4o-mini" and that provider errors, the request is retried against a healthy route without modifying your CrewAI definition. You can also send provider cache-control hints via the extra_headers parameter on the LLM if you want to reuse prompt prefixes across agent steps:

llm = LLM(
    model="anthropic/claude-3.5-sonnet",
    base_url=os.environ["N4N_BASE_URL"],
    api_key=os.environ["N4N_API_KEY"],
    extra_headers={"x-cache-control": "ephemeral"},
)

CrewAI forwards extra_headers to the underlying client, so the gateway honors your directive.

Debugging common failures

401 Unauthorized – Your N4N_API_KEY is missing or malformed. Print os.environ.get("N4N_API_KEY") outside production.

404 Model not found – The model string isn’t addressed by the gateway. List supported routes from your dashboard or hit the /v1/models endpoint.

Timeout on kickoff – Agent verbose mode helps, but set LLM(..., timeout=60) to avoid default 10s hangs on slow provider routes.

Context overflow – Long agent backstories plus task descriptions eat tokens fast. Keep max_tokens modest and trim backstory to one sentence.

Running async

For concurrent crews, use crew.kickoff_async():

import asyncio

async def main():
    result = await crew.kickoff_async()
    print(result)

asyncio.run(main())

The same llm object is safe to share across agents; the underlying HTTP client is thread-safe and connection-pooled.

Wrapping up

You now have a reproducible pattern: install CrewAI, bind its LLM to the OpenAI-compatible endpoint, and describe agents/tasks normally. No custom transport code is required to get multi-agent workflows with fallback and per-token metering. From here, extend the crew with a third validator agent, or swap the model string to compare provider quality on the same tasks.

Tagscrewain4n-aisetuptutorial

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →

All crewai getting started with n4n.ai posts →