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

# Secrets

> Store credentials in Identity providers and inject them into sandboxes as environment variables

Keep API keys out of sandbox code. Create an **Identity provider**, add key/value secrets, attach it to a **runtime** (sandbox), and those secrets become environment variables on each `run_code` / `run_cmd`.

```mermaid theme={null}
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#EEF2FF','primaryTextColor':'#1E1B4B','primaryBorderColor':'#5B4CDB','lineColor':'#6366F1','secondaryColor':'#ECFDF5','secondaryBorderColor':'#00AD69','tertiaryColor':'#F5F3FF'}}}%%
flowchart LR
  A[Identity provider] -->|attach| B[Runtime sandbox]
  B -->|run_code / run_cmd| C[Env vars]
```

<Note>
  Manage Identity providers in **Identity → Providers** on the platform, or via `client.identity.providers` / `/v1/identity/providers`. Secret **values are write-only** — list/get return masked placeholders only.
</Note>

## Why Identity providers?

| Without                      | With                                                            |
| ---------------------------- | --------------------------------------------------------------- |
| Keys in prompts or scripts   | Keys encrypted in Identity                                      |
| Copy keys into every sandbox | Attach once; reuse across runtimes                              |
| Painful rotation             | Update the Identity provider; next execution uses the new value |

Secrets are resolved at execution time. They are not stored in the runtime’s persisted env record.

## Behavior

* `provider_type` is the **auth kind** (`api_key` today; `oauth2` / `oidc` later). Vendor names like `openai` are not used here — put that in the provider **name**.
* Secret **keys** become env var names (`OPENAI_API_KEY`).
* Same key on an Identity provider **overwrites** the previous value.
* Attach at create (`providers=[...]`) or later with `client.identity.providers.attach(...)`.
* After **detach**, the next execution no longer receives those keys.
* Interactive terminal/SSH does not auto-inherit Identity provider secrets — use `run_code` or `run_cmd`.

## Create an Identity provider

<CodeGroup>
  ```python Python theme={null}
  from gravixlayer import GravixLayer

  client = GravixLayer()

  provider = client.identity.providers.create(
      name="OpenAI",
      provider_type="api_key",
      secrets=[{"key": "OPENAI_API_KEY", "value": "sk-..."}],
  )
  print(provider.id)
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.gravixlayer.ai/v1/identity/providers" \
    -H "Authorization: Bearer $GRAVIXLAYER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "OpenAI",
      "provider_type": "api_key",
      "secrets": [
        {"key": "OPENAI_API_KEY", "value": "sk-..."}
      ]
    }'
  ```
</CodeGroup>

## Multiple secrets

One Identity provider can hold several keys:

<CodeGroup>
  ```python Python theme={null}
  provider = client.identity.providers.create(
      name="External APIs",
      provider_type="api_key",
      secrets=[
          {"key": "OPENAI_API_KEY", "value": "sk-..."},
          {"key": "ANTHROPIC_API_KEY", "value": "sk-ant-..."},
          {"key": "GITHUB_TOKEN", "value": "ghp_..."},
      ],
  )
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.gravixlayer.ai/v1/identity/providers" \
    -H "Authorization: Bearer $GRAVIXLAYER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "External APIs",
      "provider_type": "api_key",
      "secrets": [
        {"key": "OPENAI_API_KEY", "value": "sk-..."},
        {"key": "ANTHROPIC_API_KEY", "value": "sk-ant-..."},
        {"key": "GITHUB_TOKEN", "value": "ghp_..."}
      ]
    }'
  ```
</CodeGroup>

## Attach at create

<CodeGroup>
  ```python Python theme={null}
  runtime = client.runtime.create(
      template="python-3.14-base-small",
      providers=[provider.id],
  )

  result = runtime.run_code(
      code="import os; print('ok' if os.environ.get('OPENAI_API_KEY') else 'missing')"
  )
  print(result.text)
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.gravixlayer.ai/v1/agents/runtime" \
    -H "Authorization: Bearer $GRAVIXLAYER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "template": "python-3.14-base-small",
      "provider": "azure",
      "region": "eastus2",
      "providers": ["PROVIDER_ID"]
    }'
  ```
</CodeGroup>

## Attach to a running sandbox

<CodeGroup>
  ```python Python theme={null}
  client.identity.providers.attach(provider.id, runtime.runtime_id)

  result = runtime.run_code(
      code="import os; print(os.environ['OPENAI_API_KEY'][:7])"
  )
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.gravixlayer.ai/v1/identity/providers/PROVIDER_ID/attach" \
    -H "Authorization: Bearer $GRAVIXLAYER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"runtime_id": "RUNTIME_ID"}'
  ```
</CodeGroup>

## Use secrets in code

```python theme={null}
result = runtime.run_code(code="""
import os
import urllib.request

req = urllib.request.Request(
    "https://api.openai.com/v1/models",
    headers={"Authorization": f"Bearer {os.environ['OPENAI_API_KEY']}"},
)
print(urllib.request.urlopen(req).status)
""")
print(result.text)
```

## Detach

<CodeGroup>
  ```python Python theme={null}
  client.identity.providers.detach(provider.id, runtime.runtime_id)

  result = runtime.run_code(
      code="import os; print(os.environ.get('OPENAI_API_KEY', 'missing'))"
  )

  runtime.kill()
  client.identity.providers.delete(provider.id)
  ```

  ```bash cURL theme={null}
  curl -X DELETE \
    "https://api.gravixlayer.ai/v1/identity/providers/PROVIDER_ID/attach/RUNTIME_ID" \
    -H "Authorization: Bearer $GRAVIXLAYER_API_KEY"
  ```
</CodeGroup>

## SDK reference

All Identity provider operations live under `client.identity.providers` (maps to `/v1/identity/providers`).

| Method                                       | Purpose                                                |
| -------------------------------------------- | ------------------------------------------------------ |
| `create(...)`                                | Create an Identity provider (optional initial secrets) |
| `list(...)`                                  | List Identity providers (masked)                       |
| `get(provider_id)`                           | Get one Identity provider (masked secrets)             |
| `update(provider_id, ...)`                   | Update name, type, or `is_active`                      |
| `delete(provider_id)`                        | Soft-delete the Identity provider                      |
| `add_secret(provider_id, key, value)`        | Add or upsert a secret pair                            |
| `list_secrets(provider_id)`                  | List secret keys (values masked)                       |
| `update_secret(provider_id, secret_id, ...)` | Rename key and/or replace value                        |
| `delete_secret(provider_id, secret_id)`      | Delete a secret pair                                   |
| `attach(provider_id, runtime_id)`            | Attach to a runtime sandbox                            |
| `detach(provider_id, runtime_id)`            | Detach from a runtime sandbox                          |
| `list_for_runtime(runtime_id)`               | List Identity providers attached to a runtime          |

```python theme={null}
# Provider CRUD
providers = client.identity.providers.list()
provider = client.identity.providers.get(provider.id)
client.identity.providers.update(provider.id, name="OpenAI Prod", is_active=True)
client.identity.providers.delete(provider.id)

# Secret pair CRUD
client.identity.providers.add_secret(provider.id, key="OPENAI_API_KEY", value="sk-...")
secrets = client.identity.providers.list_secrets(provider.id)
client.identity.providers.update_secret(provider.id, secret_id, value="sk-new-...")
client.identity.providers.delete_secret(provider.id, secret_id)

# Attach / detach
client.identity.providers.attach(provider.id, runtime.runtime_id)
client.identity.providers.list_for_runtime(runtime.runtime_id)
client.identity.providers.detach(provider.id, runtime.runtime_id)
```

## CLI

```bash theme={null}
gravixlayer provider create --name OpenAI --type api_key \
  --secret OPENAI_API_KEY=sk-...

gravixlayer runtime create --template python-3.14-base-small \
  --provider PROVIDER_ID

gravixlayer provider list-attached RUNTIME_ID
gravixlayer provider detach PROVIDER_ID RUNTIME_ID
```

## Next

<CardGroup cols={2}>
  <Card title="Create Runtime" icon="play" href="/documentation/agentruntime/sandbox-management/create-sandbox">
    Create a sandbox with Identity providers
  </Card>

  <Card title="Run Python" icon="code" href="/documentation/agentruntime/code-execution/run-python">
    Execute code that reads env vars
  </Card>
</CardGroup>
