AI frameworks
Every agent framework draws the same line: orchestration in, credential management out. LangGraph, Mastra, CrewAI, Pydantic AI, both Agents SDKs — none of them wants to be where your provider keys live, and all of them hand the question back to you. This section answers it, once per framework.
There are three shapes, ordered by how little your process ends up holding.
1. Wrap the process
seekrit run -- python agent.py
Zero code, every framework, every language. seekrit run
resolves your environment, decrypts locally, and injects the values as
environment variables in the child process only — nothing on disk, nothing
in shell history, and nothing for a coding agent to find in a file later.
This works because the frameworks all read provider credentials from the
environment: OPENAI_API_KEY, ANTHROPIC_API_KEY, GOOGLE_API_KEY. You are
not integrating with seekrit so much as declining to write a .env file.
For containers and CI, seekrit-run is the same behaviour as
a static binary with no Node dependency.
2. Resolve in code
import seekrit
seekrit.Client().into_env() # or: secrets = seekrit.Client().resolve()
Three lines at startup, using the SDKs —
Python,
JS/TS, Go, Ruby. Reach for this
when the process has no wrapper to hang seekrit run off (a serverless
handler, a Worker, a notebook), or when different requests need different
credentials — a multi-tenant agent resolving per tenant rather than per process.
3. Never hold the key
ChatOpenAI(base_url="http://127.0.0.1:8080/openai/v1", api_key="{{seekrit:OPENAI_API_KEY}}")
The egress proxy holds the token; your process holds a placeholder. On the way out the proxy swaps in the real value — and only toward hosts, methods, and paths you allowlisted, default-deny.
Use it when the code holding the credential is not code you trust: a sandbox, model-generated code, an agent whose next action you cannot predict. Anything in an environment variable can be printed, logged, or POSTed somewhere else; a placeholder cannot.
This shape is often zero-code too. OPENAI_BASE_URL is a de facto standard
— Pydantic AI, CrewAI, and the OpenAI Agents SDK all read it, and Claude Code
and the Claude Agent SDK take ANTHROPIC_BASE_URL. Where a framework honours
it, shape 3 is two environment variables and no source change:
export OPENAI_BASE_URL=http://127.0.0.1:8080/openai/v1
export OPENAI_API_KEY='{{seekrit:OPENAI_API_KEY}}'
Neither of those is a secret, so they belong in your compose file or Procfile, not in seekrit.
And often no proxy either. The SDKs ship the same substitution engine as a
fetch wrapper and an httpx transport, so your code can hold the placeholder
without a sidecar — see
in-process injection. It is a weaker
boundary than the proxy, because it runs in the same process as the code holding
the placeholder, and a much stronger one than an environment variable. On
LangChain it also buys something neither of the others can express: an
allowlist scoped to a single tool call.
Which shape
| If… | Use |
|---|---|
You just don't want a .env file | 1 — wrap the process |
| It's a Worker, Lambda, or notebook with no wrapper | 2 — resolve in code |
| Each request serves a different tenant | 2 — resolve per run, not per process |
| The process runs code you didn't write | 3 — the proxy |
| A key must work for one operation but not others | 3 — methods and paths on the route |
| You want a placeholder but not a sidecar | 3 — in-process |
| One tool may spend a key and the others may not | 3 — in-process, with LangChain middleware |
| You want all three | Nothing conflicts; the proxy just sees a placeholder where a key used to be |
Per framework
| Framework | Best fit | |
|---|---|---|
| LangGraph / LangChain | Python | 1, then 3 for tool keys |
| Mastra | TypeScript | 1 for dev, 2 for deploys |
| Pydantic AI | Python | 2 — deps is a real per-run seam |
| AI SDK | TypeScript | 2 on serverless, 1 locally |
| OpenAI Agents SDK | Python | 1, and read the tracing note |
| Claude Agent SDK | Python / TS | 1 — it deliberately ignores .env |
| CrewAI | Python | 1, then 3 for the crew's tool keys |
| LlamaIndex | Python | 1, then 3 |
Not listed doesn't mean not supported: shape 1 needs nothing from the framework
at all. If a framework starts a process, seekrit run is in front of it.
Agents that manage their own secrets
The pages above are for you wiring up an agent. If the agent itself should store and inject credentials — a coding agent setting up a project, say — install the agent plugin instead. It carries both MCP servers and the skills that keep values out of files.