Secrets
Secrets let you store sensitive values - API keys, tokens, connection strings - outside your tool’s code. Instead of hardcoding a secret in your handler, you store it once at the workspace level as a Secret and Rival injects it at runtime. Your code reads it by name, and the value is never embedded in the tool source or visible to anyone running the tool from the marketplace.
Where secrets live
Secrets are managed at /user/secrets - open the settings sidebar and select Secrets. Each secret is a name/value pair scoped to your workspace.
If you embed credentials directly in tool code, they become part of the published version snapshot and are visible to anyone with code-level access. Storing them as Secrets keeps them in a separate, access-controlled store and makes rotation easy - update the value once and every tool that reads it picks up the new value on the next run.
Creating a secret
- Open Settings → Secrets (or go to
/user/secrets). - Click New secret.
- Give it a descriptive name in uppercase with underscores, for example
OPENAI_API_KEYorDATABASE_URL. - Paste the value and save.
Values are encrypted at rest and not displayed again after saving. The naming convention is just a convention - it isn’t enforced - but it keeps things consistent across your team.
Attaching secrets to a tool
Creating a secret at the workspace level does not automatically make it available to every tool. You attach the secrets a specific tool needs from Studio’s Secrets tab. This is intentional: a tool that processes user-facing text has no reason to read your payment-processor credentials.
Open the tool in Studio, go to Secrets, and select the secrets this tool should be able to read. Once attached, the secret is injected into the tool’s runtime environment on every run. The same rows are also available as a strip under the file tree on the Code tab, if you’d rather not leave the editor.
Attachments are per version. The Secrets tab shows what the version you’re looking at reads, so an older published version keeps the secrets it was published with even after you attach or remove one on the version you’re working on.
Asking the runner for a key instead
Everything above ships your credential: every run of the tool, including runs by marketplace users, spends your key. If the tool wraps a paid third-party API, that’s usually not what you want.
A secret can instead be declared an external key - the version publishes the key’s name and a description, and whoever runs the tool picks which of their own secrets fills it. Turn on the External toggle on the secret’s row in the Secrets tab to declare one. See External Keys for the whole flow, including how the mapping travels in the X-Env-Keys header on API calls.
Reading secrets in your tool code
How you access secrets depends on the language your tool uses.
Python
import os
def cortexone_handler(event, context): api_key = os.environ.get("MY_API_KEY") if not api_key: return {"statusCode": 400, "body": {"error": "API key not configured"}} # use api_key ... return {"statusCode": 200, "body": {"ok": True}}Use os.environ.get("KEY_NAME") rather than os.environ["KEY_NAME"] so missing variables return None instead of raising a KeyError.
Python 3.13 — Fast
import json
def cortexone_handler(event, context): api_key = process["env"].get("MY_API_KEY") if not api_key: return {"statusCode": 400, "body": {"error": "API key not configured"}} # use api_key ... return {"statusCode": 200, "body": {"ok": True}}process["env"] is always available without any import. os.environ does not work in this runtime.
JavaScript
function cortexone_handler(event, context) { const apiKey = process.env.MY_API_KEY; if (!apiKey) { return { statusCode: 400, body: { error: "API key not configured" } }; } // use apiKey ... return { statusCode: 200, body: { ok: true } };}Lua
function cortexone_handler(event, context) local api_key = process.env.MY_API_KEY if not api_key then return {statusCode = 400, body = {error = "API key not configured"}} end -- use api_key ... return {statusCode = 200, body = {ok = true}}endSecurity
Secret values are encrypted at rest and never returned in API responses or shown in the dashboard after the initial save. Marketplace users who run your tool cannot see the secrets or their values - they only interact with the inputs and outputs you define.
Secrets are scoped to your workspace. Members of your organization can see secret names (so they can attach them to tools), but values are not exposed to non-owner roles.
Related
- Accounts & Authentication - API keys and workspace access
- Roles & Permissions - who can read and edit secrets
- Creating a Tool - where Secrets attach in the editor
- External Keys - asking whoever runs the tool for their own key