hexr.vault gives your agents access to secrets without requiring any credentials to access the secrets themselves. Authentication is handled by your agent’s SPIFFE X.509-SVID — the same identity issued by @hexr_agent. OPA enforces tenant isolation so agent A can only ever read secrets belonging to tenant A. All values are AES-256-GCM encrypted at rest.
Quick start
import hexr.vault
# Get a secret — authenticated by your SPIFFE identity
api_key = hexr.vault.get("openai/api-key")
# Store a secret
hexr.vault.put("my-service/token", "sk-abc123")
# Delete a secret
hexr.vault.delete("my-service/token")
No API keys, no tokens, no configuration. Your agent’s SPIFFE identity is verified automatically.
VaultClient
For explicit configuration or connection lifecycle control, use VaultClient directly:
from hexr.vault import VaultClient
vault = VaultClient(
tenant="acme-corp",
timeout=30.0
)
The Vault endpoint is configured automatically when you deploy with Hexr. On Hexr Cloud or a self-hosted cluster, the SDK discovers the endpoint from the environment set by hexr deploy — you don’t need to specify a URL manually.
Methods
Get a secret value as a string.value = vault.get("openai/api-key")
# Returns: "sk-abc123..."
Get a Secret object with metadata including path, value, and version number.secret = vault.get_secret("openai/api-key")
print(secret.path) # "openai/api-key"
print(secret.value) # "sk-abc123..."
print(secret.version) # 3
put(path, value, metadata=None)
Store a secret. Returns the new version number.version = vault.put("my-service/token", "new-value")
# Returns: 1 (first version)
# With metadata
vault.put("db/password", "p@ssw0rd", metadata={"rotation": "90d"})
Delete a secret permanently.vault.delete("my-service/token")
List secret paths under a given prefix.paths = vault.list("openai/")
# Returns: ["openai/api-key", "openai/org-id"]
Check whether a secret exists before reading it.if vault.exists("openai/api-key"):
key = vault.get("openai/api-key")
get_or_default(path, default)
Get a secret with a fallback value if the path does not exist.key = vault.get_or_default("optional/key", "default-value")
get_json(path) / put_json(path, value)
JSON serialization helpers for structured configuration.vault.put_json("config/settings", {"model": "gpt-4o", "temperature": 0.7})
config = vault.get_json("config/settings")
# Returns: {"model": "gpt-4o", "temperature": 0.7}
Check whether the Vault service is reachable and healthy.status = vault.health()
# Returns: {"status": "ok", "version": "0.1.1"}
Decorators
@secret
Fetch a single secret and inject it as the return value of a function:
from hexr.vault import secret
@secret("openai/api-key")
def get_openai_key():
pass # The return value is the secret
key = get_openai_key() # Returns the secret value
With options:
@secret("optional/key", required=False, default="fallback")
def get_optional():
pass
@secret("config/db", as_json=True)
def get_db_config():
pass # Returns parsed JSON
@secrets_batch
Fetch multiple secrets in a single call and receive them as keyword arguments. Secret path separators (/) are converted to underscores in the argument names:
from hexr.vault import secrets_batch
@secrets_batch("openai/api-key", "anthropic/api-key", "db/password")
def init_services(**secrets):
openai_key = secrets["openai_api_key"] # path / → _
anthropic_key = secrets["anthropic_api_key"]
db_pass = secrets["db_password"]
Context manager
Use VaultClient as a context manager to ensure connections are cleaned up after use:
from hexr.vault import VaultClient
with VaultClient() as vault:
key = vault.get("openai/api-key")
vault.put("results/latest", "processed")
Security model
| Property | Detail |
|---|
| Authentication | SPIFFE X.509-SVID (mutual TLS via Envoy) |
| Authorization | OPA policy at Vault boundary |
| Encryption | AES-256-GCM at rest in PostgreSQL |
| Tenant isolation | OPA enforces: agent A can only see tenant A’s secrets |
| No API keys | Your SPIFFE identity is your Vault credential |
| Audit | Every access logged with SPIFFE ID and timestamp |
Error handling
from hexr.vault import VaultError, SecretNotFoundError, PolicyDeniedError
try:
secret = hexr.vault.get("restricted/secret")
except SecretNotFoundError:
print("Secret doesn't exist")
except PolicyDeniedError:
print("OPA policy denied access for your SPIFFE ID")
except VaultError as e:
print(f"Vault error: {e}")