Skip to Content
FrameworksCrewAI + Curate-Me

CrewAI

CrewAI reads OPENAI_BASE_URL and OPENAI_API_KEY directly from the environment. The integration is the simplest of any framework: two env vars.

Minimal example

import os os.environ["OPENAI_BASE_URL"] = f"{os.environ.get('CURATE_ME_GATEWAY_URL', 'https://api.curate-me.ai')}/v1/openai" os.environ["OPENAI_API_KEY"] = os.environ["CM_API_KEY"] # CrewAI sends this as Authorization: Bearer from crewai import Agent, Task, Crew researcher = Agent(role="Researcher", goal="Find AI governance trends", backstory="Senior analyst.") task = Task(description="3 key trends in AI governance", expected_output="bulleted list", agent=researcher) Crew(agents=[researcher], tasks=[task]).kickoff()

Full example at examples/integrations/crewai/basic_crew.py.

Why one env var works

CrewAI uses LiteLLM internally to talk to OpenAI. LiteLLM honours OPENAI_BASE_URL and treats OPENAI_API_KEY as a bearer token. The gateway accepts Authorization: Bearer cm_sk_... as an equivalent of X-CM-API-Key: cm_sk_....

Supported versions

LibraryTested range
crewai>=0.95.0,<2.0.0
litellm>=1.50.0,<2.0.0 (transitive)

Known limitations

  • Per-agent model selection: each Agent(llm=...) override has to point at the gateway. Set OPENAI_BASE_URL globally OR pass llm=ChatOpenAI(base_url=...) per agent.
  • CrewAI memory: long-term memory persistence runs entirely on your side; the gateway only sees per-tick LLM calls.
  • Tools: standard tools (SerperDevTool, FileReadTool, etc.) make their own network calls outside the gateway. Only the LLM step is governed.
  • Custom providers: if you use litellm’s non-OpenAI provider syntax (e.g. anthropic/claude-3-5-sonnet), CrewAI bypasses the OPENAI_BASE_URL for that call. Point CrewAI agents explicitly at openai/gpt-4o (or similar) to keep traffic through Curate-Me.