# CrewAI

CrewAI reads `OPENAI_API_KEY` and `OPENAI_BASE_URL` from the environment, and its
`LLM` class takes `api_key` and `base_url` directly. All three shapes are short.

> **Note:** **Start here if seekrit is new:** [three commands](/docs/guides/frameworks#get-running-in-five-minutes) put the keys in an environment, mint a token bound to it, and export `SEEKRIT_TOKEN`. A token reads [everything in its environment](/docs/guides/frameworks#which-secrets-does-the-agent-get), so there is no per-key or per-framework setup to do before any of the below.

## 1. Wrap the process

```bash
seekrit run -- python crew.py
seekrit run -- crewai run
```

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

researcher = Agent(role="Research Specialist", goal="Conduct comprehensive analysis")
search = Task(description="Research the topic: {topic}", expected_output="A report", agent=researcher)

crew = Crew(agents=[researcher], tasks=[search])
print(crew.kickoff(inputs={"topic": "AI safety"}))
```

CrewAI's own docs tell you never to commit API keys and to use secret
management; this is that, without the `.env` step in between.

## 2. Resolve in code

```python
import seekrit
from crewai import LLM

secrets = seekrit.Client().resolve()

llm = LLM(model="openai/gpt-5.6-terra", api_key=secrets["OPENAI_API_KEY"])
researcher = Agent(role="Research Specialist", goal="Analyse", llm=llm)
```

## 3. Never hold the key

```python
from crewai import LLM

llm = LLM(
    model="openai/gpt-5.6-terra",
    base_url="http://127.0.0.1:8080/openai/v1",
    api_key="{{seekrit:OPENAI_API_KEY}}",
)
```

```toml
# seekrit-proxy.toml
listen = "127.0.0.1:8080"

[[route]]
prefix = "/openai"
upstream = "https://api.openai.com"
allow = ["OPENAI_API_KEY"]
methods = ["POST"]
paths = ["/v1/chat/completions"]

# The crew's tools, bounded to the operations they actually need.
[[route]]
prefix = "/github"
upstream = "https://api.github.com"
allow = ["GITHUB_TOKEN"]
methods = ["GET", "POST"]
paths = ["/repos/*/*/issues", "/repos/*/*/issues/*"]
```

### Without running the proxy

CrewAI reaches the network through LiteLLM, whose only seam is a module global:

```python
import httpx, litellm
from seekrit.transport import AsyncSeekritTransport, SeekritTransport

allow = {"api.openai.com": ["OPENAI_API_KEY"]}
litellm.client_session = httpx.Client(transport=SeekritTransport(allow=allow))
litellm.aclient_session = httpx.AsyncClient(transport=AsyncSeekritTransport(allow=allow))
```

It works, and being process-wide it cannot scope per request.
[In-process injection](/docs/guides/agent-proxy/in-process) sets out the
trade-off against the proxy.

## Gotchas

- **The tools are the reason to bother.** A crew is several agents sharing one
  process, so every agent effectively has every tool's credentials. The proxy's
  `methods` and `paths` are how you stop a research agent from being able to
  perform a write the delegation graph never intended.
- **`kickoff` is one long process.** Values resolved at start hold for the whole
  run. For a crew that runs for hours, either restart on rotation or use shape 3,
  where the proxy re-resolves on its own interval.
- **Delegation crosses no security boundary.** `allow_delegation` moves work
  between agents in the same process with the same environment. If two agents
  must have different reach, that is two processes, or the proxy's session
  tickets.
