Valta Docs
Key Safety and Proxy Data
This guide describes the financial-action proxy currently present in this repository at POST /api/v1/proxy. The connected database also contains tables for an LLM proxy (agent_provider_keys, agent_virtual_keys, and llm_proxy_requests), but the matching LLM proxy request handler and its runbook are not present in the checked default-branch source. The schema alone is not enough to verify its runtime behavior, so this guide does not make operational promises about that feature.
The two kinds of credentials
Valta API keys
- Valta API keys are generated by the API and returned in full once when created. Save the value in a secret manager immediately.
- The server stores a SHA-256 hash for authentication, rather than the raw key. The key list returns a prefix, not the full secret.
- Revoke an exposed or unused key with
DELETE /api/v1/keys/:id. Get the key ID fromGET /api/v1/keys.
Provider credentials stored in Valta
- Sensitive provider credential fields configured for supported services are encrypted with AES-256-GCM before they are stored. Non-sensitive configuration fields may be stored as supplied.
- Encryption uses the
API_KEY_ENCRYPTION_SECRETserver environment variable. The code requires a 64-character hex string representing 32 bytes. - Sensitive credential hints are masked; the UI-facing hint contains only the final four characters (or a masked value for shorter secrets).
- Valta decrypts the stored credential server-side when it needs to call the configured provider. The financial-action proxy uses the account's stored credential for the selected service.
These are different credentials with different purposes: your Valta API key authenticates requests to Valta; a provider credential authorizes Valta to call that provider.
LLM proxy: what the database schema shows
The connected database schema contains these LLM-proxy-related tables:
agent_provider_keys: includesencrypted_key,last4,is_active, andrevoked_atcolumns.agent_virtual_keys: includessecret_hash,secret_prefix,status, andrevoked_atcolumns.llm_proxy_requests: includes virtual-key, user, agent, run, and allow IDs; model; outcome; deny reason; estimated and actual cost; upstream status; latency; and creation time.
The llm_proxy_requests table has no request-body or response-body columns. That only describes this table's schema; it does not prove what every application log or external service stores.
These are database-schema facts, not proof of the LLM proxy's live request path. The matching handler is absent from the checked default-branch source, so the following details remain unverified from code: encryption algorithm and key management for agent_provider_keys.encrypted_key, whether a virtual key is displayed only once, the virtual-key hash algorithm, the LLM proxy's exact fail-closed behavior, its revocation endpoint, and any cleanup or retention process. No LLM-proxy retention period is defined by these table columns.
How the financial-action proxy works
A caller sends a request to POST /api/v1/proxy with an agent ID, registered service, relative path, method, declared amount, description, and optional body. Valta:
- Validates the request and confirms that the service has a registered proxy origin.
- Checks the agent's wallet and applicable spending controls through the wallet spend function.
- Forwards the request to the service's configured origin using the account's stored credential only after the spend is approved.
- Returns the provider response to the caller.
The proxy is not a general-purpose URL forwarder. It joins the requested relative path to a service origin defined in Valta's service schema.
Important limit: the amount is declared by the caller. The gate enforces the amount supplied to it; it does not independently calculate the provider's eventual charge from the request or response body. A caller that understates the amount can make the recorded spend inaccurate.
What the proxy records
The proxy_requests receipt table stores metadata for each recorded decision, including:
- Receipt ID, user ID, and agent ID
- Service, HTTP method, and relative path
- Caller-declared amount and decision (allowed, blocked, refunded, or pending approval)
- Reason, provider response status when available, description, and creation time
The proxy receipt table does not define request-body or response-body columns. The proxy forwards the supplied body to the provider and returns the provider response to its caller; those bodies are not written by this receipt-recording code.
Receipt persistence is best-effort in the current implementation: a database error while inserting a proxy receipt is swallowed. Do not treat the receipt list as proof that every attempted call has a persisted row.
Valta does not publish a defined retention period for these proxy receipts.
What happens when a spend check cannot be completed
The wallet spend path denies a request when it cannot verify daily or monthly spend totals. A failed wallet lookup or an unexpected error also prevents the proxy route from reaching its outbound fetch and results in an error response.
This describes the current financial-action proxy path. It is not a blanket guarantee that every Valta feature or every provider call is protected by the proxy. If an agent or application has a provider's own credential and calls that provider directly, that call does not pass through this gate.
Keep provider keys safe
- For OpenAI or another provider you call directly, create a separate provider project and API key for each environment where the provider supports it.
- Configure a provider-side usage budget or alert as a second line of defence, where available.
- Prefer storing provider credentials in Valta's credential settings and routing supported financial-action requests through Valta.
- Keep raw provider credentials out of agent prompts, logs, source control, browser bundles, and agent runtime environment variables when Valta is intended to hold and use them.
- If an agent has a provider credential itself, it may be able to call that provider directly and bypass Valta's financial-action gate.
- Use the narrowest provider permissions available. Rotate a credential promptly if it may have been exposed.
Freeze an agent
Use the agent freeze control in the Valta dashboard, or call the SDK freeze method from your server:
await valta.agents.freeze(agentId)
A freeze blocks the agent's subsequent governed financial activity. For operational steps, see the Kill Switch guide.
What this guide does not claim
- The LLM proxy's runtime behavior cannot be verified from the current default-branch source, even though related database tables exist.
- The current source branch does not contain a verified cooperative
allow()cap implementation or LLM-proxy revocation endpoint. - No retention period is defined in the LLM proxy table schema or published for financial-action proxy receipts.
- The financial-action proxy relies on the amount declared by its caller; it does not independently verify provider billing.