Secrets
Use secrets to give your tools a credential, such as a third-party API key, without putting its value in your code. Declare each secret once, by name, and point it at a secret in the Mistral Secrets Manager. Deployed, the agent gets it as an environment variable, and a missing secret fails before a session starts, rather than in the middle of one.
Each kind of credential has its own mechanism:
| You want to… | Use |
|---|---|
| Give a tool an API key | secrets= on the Agent |
| Call GitHub from a sandbox command | header_bindings= on the sandbox |
| Call a user's connector, such as Gmail | The user's sign-in |
| Call your own MCP server with a token | auth_header_env_vars= |
This page covers secrets=. The guides for the others are Header binding, Sign-in and Pass a credential.
Here the payment reviewer screens a beneficiary with a vendor's API:
import asyncio
import os
from mistralai import agents
@agents.tool(annotations=agents.ToolAnnotations(read_only_hint=True))
async def screen_beneficiary(name: str) -> str:
"""Screen a payment beneficiary against the sanctions lists."""
api_key = os.environ["SCREENING_API_KEY"] # set from the secret when deployed
return f"{name}: no match" # call your screening vendor with api_key
payment_reviewer = agents.Agent(
model="mistral-large-4",
name="payment-reviewer",
instructions="Screen the beneficiary. Reply in one sentence.",
tools=[screen_beneficiary],
secrets={
"SCREENING_API_KEY": agents.MistralSecret.workspace("screening-api-key", worker_env=True),
},
)
async def main() -> None:
state = await payment_reviewer.run("Screen the beneficiary Jane Roe.")
if isinstance(state, agents.Completed):
print(state.text)
if __name__ == "__main__":
asyncio.run(main())To run it in your process: SCREENING_API_KEY=... uv run python screening.py.
The key, here SCREENING_API_KEY, is the name of the environment variable your tools read. Each value is an agents.MistralSecret:
agents.MistralSecret.workspace("NAME", worker_env=True)points at the workspace secretNAME, by its bare name as the console shows it.agents.MistralSecret(worker_env=True)points at no secret in your code. Bind it when you deploy, withagents deploy --secret-binding NAME=secret:workspace:.... A binding also overrides the secret ofworkspace(), so staging and production can each use their own secret without a code change.
Set worker_env=True on every MistralSecret. Any code where the agent runs can read the variable, so the SDK asks you to opt in, and building the Agent fails without it.
Do not declare a connector's token as a secret: it never leaves the Connectors Gateway.
The value your tools read depends on how the agent runs:
| Run mode | Where the value comes from | When it is missing |
|---|---|---|
agents deploy | The Secrets Manager secret named by --secret-binding, or by workspace() when there is no binding | The deploy fails |
agents serve | The variable with the same name in your shell | agents serve does not start |
In your process (agent.run()) | The variable with the same name in your process's environment | Nothing checks it before the run: the run completes, and only the tool call fails |
The CLI does not read .env itself. To load the variables of .env for agents serve, run
uv run --env-file .env agents serve.
Deploy shows how to create the secret and bind it when you deploy.
Next
Guardrails: block a tool call your policy forbids.