Configuration & Secrets¶
Every model provider needs a credential, and some need an endpoint or a region as well. There are four places you can keep them. Pick one; they all end up in the same place.
| Where | Best for | Picked up by |
|---|---|---|
A .env file in your project |
Local development — one file, git-ignored | Everything: python my_agent.py, the promptise CLI, .superagent files |
| Environment variables | CI, containers, servers — whatever your platform injects | Everything |
In code, with Model(...) |
When the key comes from your secret store (Vault, Key Vault, a settings object) | build_agent(model=Model(...)) |
A .superagent file |
Declarative agents; ${VAR} references keep secrets out of the file |
promptise agent, load_superagent_file() |
Every provider's variables¶
The exact variable names each provider reads (put them in .env or export
them), the provider= value for Model(...) or the string prefix, and the
words that carry the same values in code. This table is generated from the
code, so the names are exact.
| Provider | provider= |
Environment variables (exact names) | Model(...) words |
Route |
|---|---|---|---|---|
| OpenAI | openai also gpt |
OPENAI_API_KEYOPENAI_BASE_URL (optional) |
api_key=, endpoint= |
native (core) |
| Azure OpenAI | azure also azure_openai, azure-openai, azureopenai, aoai |
AZURE_OPENAI_ENDPOINTAZURE_OPENAI_API_KEYOPENAI_API_VERSION |
deployment=, api_key=, endpoint=, api_version= |
native (core) |
| Azure AI Foundry model catalog | foundry also azure_ai, azure-ai, azureai, ai-foundry |
AZURE_INFERENCE_ENDPOINTAZURE_INFERENCE_CREDENTIAL |
api_key=, endpoint=, api_version= |
OpenAI-compatible, URL built from the words |
| Anthropic Claude | anthropic also claude |
ANTHROPIC_API_KEY |
api_key=, endpoint= |
native (core) |
| Google Gemini | gemini also google_genai, google, google-genai, genai |
GOOGLE_API_KEY / GEMINI_API_KEY |
api_key=, endpoint= |
OpenAI-compatible: https://generativelanguage.googleapis.com/v1beta/openai/ |
| Google Vertex AI | vertex also google_vertexai, vertexai, google-vertex, gcp |
GOOGLE_CLOUD_PROJECTGOOGLE_CLOUD_LOCATION (optional)GOOGLE_OAUTH_ACCESS_TOKEN (optional) |
api_key=, endpoint=, region=, project= |
OpenAI-compatible, URL built from the words |
| Amazon Bedrock | bedrock also aws, amazon |
AWS_DEFAULT_REGION / AWS_REGIONAWS_BEARER_TOKEN_BEDROCK |
api_key=, endpoint=, region= |
OpenAI-compatible, URL built from the words |
| Ollama | ollama also local |
OLLAMA_HOST (optional) |
endpoint= |
OpenAI-compatible, URL built from the words |
| Cohere | cohere |
COHERE_API_KEY |
api_key=, endpoint= |
OpenAI-compatible: https://api.cohere.ai/compatibility/v1 |
| DeepSeek | deepseek |
DEEPSEEK_API_KEY |
api_key=, endpoint= |
OpenAI-compatible: https://api.deepseek.com/v1 |
| Fireworks AI | fireworks |
FIREWORKS_API_KEY |
api_key=, endpoint= |
OpenAI-compatible: https://api.fireworks.ai/inference/v1 |
| Groq | groq |
GROQ_API_KEY |
api_key=, endpoint= |
OpenAI-compatible: https://api.groq.com/openai/v1 |
| Hugging Face Inference Providers | huggingface also hf |
HF_TOKEN / HUGGINGFACEHUB_API_TOKEN |
api_key=, endpoint= |
OpenAI-compatible: https://router.huggingface.co/v1 |
| Mistral AI | mistral also mistralai |
MISTRAL_API_KEY |
api_key=, endpoint= |
OpenAI-compatible: https://api.mistral.ai/v1 |
| NVIDIA NIM | nvidia also nim |
NVIDIA_API_KEY |
api_key=, endpoint= |
OpenAI-compatible: https://integrate.api.nvidia.com/v1 |
| OpenRouter | openrouter |
OPENROUTER_API_KEY |
api_key=, endpoint= |
OpenAI-compatible: https://openrouter.ai/api/v1 |
| Perplexity | perplexity |
PPLX_API_KEY |
api_key=, endpoint= |
OpenAI-compatible: https://api.perplexity.ai |
| Together AI | together |
TOGETHER_API_KEY |
api_key=, endpoint= |
OpenAI-compatible: https://api.together.xyz/v1 |
| xAI Grok | xai also grok |
XAI_API_KEY |
api_key=, endpoint= |
OpenAI-compatible: https://api.x.ai/v1 |
Nothing to install for any row: pip install promptise covers every provider. native=True opts into a provider's own LangChain integration when you have it installed.
promptise models env <provider> prints the same variables as ready-to-fill
lines with a note on where each value is found in the provider's console.
The .env file¶
Create a file named .env in your project directory:
That is all. Promptise loads it before it checks a provider's variables —
from the directory you run in or a parent, up to your project's root — so a
plain script, the CLI and config files all see the same keys, with no
load_dotenv() call in your code:
import asyncio
from promptise import build_agent
async def main():
agent = await build_agent(model="openai:gpt-5-mini", instructions="Be concise.")
...
asyncio.run(main()) # OPENAI_API_KEY comes from .env
Rules of the file:
- A variable that is already set to a value in the environment wins over
the file — the file never overrides your shell or your platform. One that is
exported but empty (
export OPENAI_API_KEY=) counts as not set and takes the file's value;promptise models checksays which happened (MISSING (OPENAI_API_KEY is exported but empty — unset it or give it a value)when the file has nothing for it either). An empty value in the file sets nothing. - Where it is looked for. The directory you run in, then its parents,
stopping after the project root — the first directory holding
pyproject.tomlor.git. A.envabove your project (/tmp/.envon a shared host, another checkout, somebody's home directory) is never read. The first file found wins; nothing further up is merged in. - Which files are trusted. Only a regular file and, on POSIX, one that
you own and that nobody else can write (Windows has neither owners nor
mode bits in this sense, so only the regular-file check applies there).
A
.envthat is world-writable, owned by another user or not a regular file is skipped with a warning naming it (ignoring /srv/.env: world-writable (mode 666) — run: chmod o-w /srv/.env) and the search continues upward — a file a co-located user could plant or edit cannot redirect your endpoint or supply a key silently. - Where a value came from. The CLI prints
.env loaded from <path>on stderr,promptise models checkshowsset (from <path>)next to every variable the file filled, andpromptise.models.dotenv_origin("OPENAI_API_KEY")returns the path in code (Nonewhen the shell set it). - A file that cannot be read — a root-owned
0600file up the tree, one saved as Latin-1 or cp1252 — is one clean error, not a traceback:cannot read /app/.env: [Errno 13] Permission denied — fix its permissions/encoding, move it, or set PROMPTISE_NO_DOTENV=1. It is aModelSetupErrorfrombuild_agent()/resolve_model()and anError:line with exit code 2 from everypromptisecommand;promptise --versionandpromptise --helpnever touch the file. - It is loaded once per process (call
promptise.models.load_dotenv_if_present()after anos.chdirif you need another one). - Set
PROMPTISE_NO_DOTENV=1to turn the loading off entirely (hermetic deployments, tests). - Never commit it. Add
.envto.gitignore; commit a.env.examplewith the variable names and no values instead.
promptise models env <provider> prints exactly the lines a provider needs,
with a note on where each value is found — paste them in:
# Azure OpenAI (OpenAI models deployed in Azure AI Foundry) — model string example: azure:chat-prod
export AZURE_OPENAI_ENDPOINT=https://my-resource.openai.azure.com/
# ↳ Azure AI Foundry portal → your resource → Overview → Endpoint (https://<resource>.openai.azure.com/, no path)
export AZURE_OPENAI_API_KEY=...
# ↳ Azure AI Foundry portal → your resource → Keys and Endpoint → KEY 1 (or Entra ID: pass extra={'azure_ad_token_provider': ...})
export OPENAI_API_VERSION=2024-10-21
# ↳ the REST API version your deployment supports, e.g. 2024-10-21 (Azure docs → 'API version lifecycle')
(export lines are valid .env syntax; python-dotenv accepts them.)
Environment variables¶
Export them in your shell, or let your platform inject them (Docker -e,
Kubernetes secrets, GitHub Actions secrets, systemd Environment=):
The variable each provider reads is listed in Model Setup
and printed by promptise models env <provider>.
In code — Model(...)¶
When the key lives in your own secret store, hand it over in code. The same words work for every provider; nothing needs to be in the environment:
from promptise import Model, build_agent
secrets = my_vault.get("llm") # wherever your secrets come from
agent = await build_agent(
model=Model(
"gpt-4o",
provider="azure",
deployment="chat-prod",
endpoint=secrets["endpoint"],
api_key=secrets["key"],
api_version="2024-10-21",
),
servers=...,
)
A value given in code counts as provided — the matching variable is not
looked for. None or a blank string does not count as given:
Model(..., api_key="") leaves the key to the environment and .env, so a
${OPENAI_API_KEY} reference that resolves to an empty export never shadows
the value in your file. See Model Setup
for every word and what it maps to per provider.
In a .superagent file¶
Keep the secret out of the file with a ${VAR} reference; the variable is
resolved from the environment (and therefore from .env) when the file is
loaded:
agent:
model:
provider: azure
model: gpt-4o
deployment: chat-prod
endpoint: https://my-resource.openai.azure.com/
api_key: ${AZURE_OPENAI_API_KEY}
api_version: "2024-10-21"
${VAR:-default} supplies a fallback. promptise validate agent.superagent
--check-env reports any reference that is not set. See
SuperAgent Files.
Precedence¶
When the same setting is available in more than one place:
- A value in code (
Model(api_key=...), or a.superagentfield) — always used, nothing else is consulted for that word. An empty or blank value is not a value: it falls through to the next two. - An environment variable already set when the process started.
- The
.envfile — only fills in what is still missing. A variable that is exported but empty counts as missing, so the file's value is used;promptise models checksays so when that happens, and names the file a value came from.
Model(...) never shows api_key or extra in its repr()/str() — the
object is safe to log, put in an error message or print in a traceback.
Check what is missing¶
Before running anything:
promptise models check azure:chat-prod # what resolves, what is missing, where to find it
promptise models check openai:gpt-5-mini --ping # plus a real one-token call
When the string is not usable the command lists every problem with its fix
— an unset variable, one exported but empty, a native=True package that is
not installed — and exits with 1. Every error Promptise raises for a
missing credential names the variable, where its value lives in the
provider's console, and the three ways to supply it:
Cannot use model openai:'gpt-5-mini' (OpenAI) yet:
- OPENAI_API_KEY is not set — platform.openai.com → API keys (e.g. sk-...)
- put OPENAI_API_KEY in a .env file next to your script (loaded automatically, never
overrides a set variable), export it, or pass it in code: Model(..., api_key=) — see
promptise models env openai
Other secrets¶
The model key is the one every project needs. The same four places work for the rest:
| Secret | Read by | Variable |
|---|---|---|
| Upstream API token for a generated MCPcast server | server.py from promptise mcpcast --auth env-token |
MCPCAST_UPSTREAM_TOKEN (put it in the MCP client's own env block for desktop clients — see MCPcast) |
| JWT signing key for an MCP server | JWTAuth(secret=...) |
your choice — pass it from os.environ |
| Redis / Postgres URLs | conversation stores, caches | your choice |
| Agent identity credentials (Entra, AWS, GCP, SPIFFE) | AgentIdentity providers |
the cloud's own variables — see Agent Identity |
See also¶
- Model Setup — every provider, the
Modelobject, Azure AI Foundry in depth - Quick Start — your first agent
- CLI reference —
promptise models - Environment Resolver —
${VAR}syntax in config files