Skip to main content
When you create a session, you can pass a secrets dictionary containing API keys and other sensitive values your environment or sandbox needs at runtime:
async with environment.session(
    task=task,
    secrets={
        "OPENAI_API_KEY": "sk-...",
        "ANTHROPIC_API_KEY": "sk-ant-...",
    }
) as session:
    ...
Your environment’s __init__ method receives these via the secrets parameter:
class MyEnvironment(Environment):
    def __init__(self, task_spec: JSONObject, secrets: dict[str, str] = {}) -> None:
        super().__init__(task_spec, secrets=secrets)
Rather than exposing raw secret values inside your environment or sandbox, OpenReward replaces them with placeholders before they reach your server. The actual values are injected on egress - when outbound HTTP requests leave the environment or sandbox, OpenReward swaps the placeholders back in for allowed destination hosts only. This means your environment code never handles raw API keys directly, and secrets cannot be leaked to unauthorised hosts.

How It Works

  1. The client passes secrets when creating a session
  2. OpenReward stores the real values and replaces them with opaque placeholders
  3. Your environment receives only the placeholders
  4. When an outbound request leaves your environment or sandbox, OpenReward injects the real value - but only if the destination host is allowed

Allowed Outbound Hosts

Each secret has a list of allowed hosts that it can be sent to. For common API keys, OpenReward provides sensible defaults:
Secret NameDefault Allowed Hosts
OPENAI_API_KEYapi.openai.com
ANTHROPIC_API_KEYapi.anthropic.com
GEMINI_API_KEYgenerativelanguage.googleapis.com
GOOGLE_API_KEYgenerativelanguage.googleapis.com
TAVILY_API_KEYapi.tavily.com
MISTRAL_API_KEYapi.mistral.ai
COHERE_API_KEYapi.cohere.com
GROQ_API_KEYapi.groq.com
TOGETHER_API_KEYapi.together.xyz
REPLICATE_API_TOKENapi.replicate.com
HUGGINGFACE_API_KEYapi-inference.huggingface.co, huggingface.co
HF_TOKENhuggingface.co, api-inference.huggingface.co
HUGGING_FACE_HUB_TOKENhuggingface.co, api-inference.huggingface.co
PERPLEXITY_API_KEYapi.perplexity.ai
FIREWORKS_API_KEYapi.fireworks.ai
DEEPSEEK_API_KEYapi.deepseek.com
KAGGLE_KEYwww.kaggle.com
KAGGLE_USERNAMEwww.kaggle.com
KAGGLE_API_KEYwww.kaggle.com
E2B_API_KEYapi.e2b.app
MODAL_TOKEN_IDapi.modal.com
MODAL_TOKEN_SECRETapi.modal.com
DAYTONA_API_KEYapp.daytona.io
For secrets without defaults, or to override the defaults, pass a (value, [hosts]) tuple instead of a plain string:
secrets = {
    # Uses default allowed hosts (api.openai.com)
    "OPENAI_API_KEY": "sk-...",

    # Custom hosts for a secret without defaults
    "CUSTOM_API_KEY": ["my-secret-value", ["api.example.com", "api2.example.com"]],
}
Secrets with default allowed hosts can be passed as plain strings. Secrets without defaults must use the (value, [hosts]) format — otherwise the request will be rejected.