> ## Documentation Index
> Fetch the complete documentation index at: https://docs.openreward.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Keeping Secrets Secret

> How OpenReward protects sensitive API keys using placeholder injection and egress-time substitution

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:

```python theme={null}
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:

```python theme={null}
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 Name              | Default Allowed Hosts                            |
| ------------------------ | ------------------------------------------------ |
| `OPENAI_API_KEY`         | `api.openai.com`                                 |
| `ANTHROPIC_API_KEY`      | `api.anthropic.com`                              |
| `GEMINI_API_KEY`         | `generativelanguage.googleapis.com`              |
| `GOOGLE_API_KEY`         | `generativelanguage.googleapis.com`              |
| `TAVILY_API_KEY`         | `api.tavily.com`                                 |
| `MISTRAL_API_KEY`        | `api.mistral.ai`                                 |
| `COHERE_API_KEY`         | `api.cohere.com`                                 |
| `GROQ_API_KEY`           | `api.groq.com`                                   |
| `TOGETHER_API_KEY`       | `api.together.xyz`                               |
| `REPLICATE_API_TOKEN`    | `api.replicate.com`                              |
| `HUGGINGFACE_API_KEY`    | `api-inference.huggingface.co`, `huggingface.co` |
| `HF_TOKEN`               | `huggingface.co`, `api-inference.huggingface.co` |
| `HUGGING_FACE_HUB_TOKEN` | `huggingface.co`, `api-inference.huggingface.co` |
| `PERPLEXITY_API_KEY`     | `api.perplexity.ai`                              |
| `FIREWORKS_API_KEY`      | `api.fireworks.ai`                               |
| `DEEPSEEK_API_KEY`       | `api.deepseek.com`                               |
| `KAGGLE_KEY`             | `www.kaggle.com`                                 |
| `KAGGLE_USERNAME`        | `www.kaggle.com`                                 |
| `KAGGLE_API_KEY`         | `www.kaggle.com`                                 |
| `E2B_API_KEY`            | `api.e2b.app`                                    |
| `MODAL_TOKEN_ID`         | `api.modal.com`                                  |
| `MODAL_TOKEN_SECRET`     | `api.modal.com`                                  |
| `DAYTONA_API_KEY`        | `app.daytona.io`                                 |

For secrets without defaults, or to override the defaults, pass a `(value, [hosts])` tuple instead of a plain string:

```python theme={null}
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"]],
}
```

<Info>
  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.
</Info>
