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

# Secure Secrets Management

> Store and retrieve secrets with per-agent isolation using SPIFFE identity-scoped access.

## The Problem

```python theme={null}
# ❌ Don't do this
import os
OPENAI_KEY = os.environ["OPENAI_API_KEY"]  # Leaked in logs, shared across agents
```

## The Hexr Way

```python theme={null}
from hexr import hexr_agent
from hexr.vault import VaultClient

@hexr_agent(name="my-agent", tenant="acme-corp")
def main():
    vault = VaultClient()
    
    # Store a secret (encrypted at rest, scoped to this agent)
    vault.put("OPENAI_API_KEY", "sk-...")
    
    # Retrieve it
    key = vault.get("OPENAI_API_KEY")
```

***

## Why It's Different

| Feature               | Env Variables | Hexr Vault            |
| --------------------- | ------------- | --------------------- |
| Encryption at rest    | ❌ Plaintext   | ✅ AES-256-GCM         |
| Per-agent isolation   | ❌ Shared      | ✅ SPIFFE-scoped       |
| Per-process isolation | ❌ No          | ✅ Role-level scoping  |
| Audit trail           | ❌ No          | ✅ Every access logged |
| Rotation              | Manual        | SDK-managed           |
| Visible in logs       | Yes           | Never                 |

***

## Decorator Approach

Inject secrets automatically:

```python theme={null}
from hexr import hexr_agent
from hexr.vault import secret, secrets_batch

@hexr_agent(name="my-agent", tenant="acme-corp")
@secrets_batch(["OPENAI_API_KEY", "ANTHROPIC_API_KEY"])
def main(OPENAI_API_KEY: str, ANTHROPIC_API_KEY: str):
    # Secrets injected as function parameters
    print(f"OpenAI key starts with: {OPENAI_API_KEY[:8]}...")
```

***

## Scoping

Secrets are scoped to SPIFFE ID prefixes:

```python theme={null}
# Agent-level: all processes in this agent can access
vault.put("SHARED_KEY", "value")
# Stored with scope: spiffe://hexr.cloud/agent/acme/my-agent/*

# Process-level: only the researcher process can access
vault.put("RESEARCH_DB_KEY", "value", scope="researcher")
# Stored with scope: spiffe://hexr.cloud/agent/acme/my-agent/researcher
```

A writer process trying to read `RESEARCH_DB_KEY` will get an access denied error.

***

## Full Example

```python theme={null}
from hexr import hexr_agent, hexr_llm
from hexr.vault import VaultClient

@hexr_agent(name="smart-agent", tenant="acme-corp")
def main():
    vault = VaultClient()
    
    # Store secrets during setup
    vault.put("OPENAI_API_KEY", "sk-proj-...")
    vault.put("SLACK_WEBHOOK", "https://hooks.slack.com/...")
    
    # Use them
    response = hexr_llm(
        provider="openai",
        model="gpt-4o",
        prompt="Generate a status report",
    )
    
    # List all secrets (keys only, not values)
    keys = vault.list()
    print(f"Stored secrets: {keys}")
    # → ["OPENAI_API_KEY", "SLACK_WEBHOOK"]
```
