# Secrets

> Org- and environment-scoped key/value secrets for prompts and custom tools

Secrets are key/value pairs scoped to your organization **and** a single [environment](/platform/environment-isolation) (`development`, `production`, `eval`). Use them to keep API keys, tokens, and other configuration out of your resource files and inject them into agent system prompts and custom tools at runtime.

A secret is identified by its **key**, which must match `^[A-Za-z_][A-Za-z0-9_]*$` — a letter or underscore followed by letters, digits, or underscores (e.g. `STRIPE_API_KEY`, `WELCOME_TEMPLATE`). Setting a key that already exists in that environment overwrites it.

## Environment scoping and the dev → eval mirror

Secrets are isolated per environment, exactly like entities, configs, and API keys. A secret set in `development` is not visible in `production`.

The one exception is the **dev → eval mirror**: whenever development secrets are written, they are automatically mirrored into the `eval` environment. This keeps evals running against the same configuration as development without a separate sync. Production secrets are never mirrored.

## Setting secrets

There are two ways to set secrets.

### Dashboard

Go to **Settings → Secrets**. The list is scoped by the dev/prod environment switcher, so switch environments to manage each set independently. Values are masked in the list; an org admin can reveal a value with the eye toggle. Admins can add, replace (set an existing key to overwrite it), and delete secrets here. Deletion is dashboard-only.

### `.env` files (CLI)

The CLI reads `.env.development` and `.env.production` from your project root (next to `struere.json`) and syncs them as secrets. `struere dev` / `struere sync` sync `.env.development` (and mirror to eval); `struere deploy` syncs `.env.production`. Sync is additive — keys in the file are upserted, keys not in the file are left untouched. See [Syncing secrets with the CLI](/cli/secrets).

## Using secrets in system prompts

Reference a secret in an agent's system prompt with `{{secrets.KEY}}`. It resolves to the secret's value for the agent's environment at prompt-compile time.

```typescript
import { defineAgent } from 'struere'

export default defineAgent({
  name: "Support Agent",
  slug: "support",
  version: "0.1.0",
  systemPrompt: `You are an assistant for {{organizationName}}.
The support portal is at {{secrets.SUPPORT_PORTAL_URL}}.`,
  model: { model: "openai/gpt-5-mini" },
  tools: ["entity.query"],
})
```

If the key is not set in that environment, it resolves to the literal string `[MISSING_SECRET:KEY]` (e.g. `[MISSING_SECRET:SUPPORT_PORTAL_URL]`) — the prompt still compiles, so test with [`struere compile-prompt`](/cli/compile-prompt) to confirm every referenced key is set.

## Using secrets in custom tools

In a [custom tool](/tools/custom-tools) handler, read a secret from `context.secrets.KEY`. A key that is not set in the tool's environment is `undefined`.

```typescript
import { defineTools } from 'struere'

export default defineTools([
  {
    name: "create_charge",
    description: "Create a charge via the payments API",
    parameters: {
      type: "object",
      properties: { amount: { type: "number" } },
      required: ["amount"],
    },
    handler: async (args, context, struere, fetch) => {
      const apiKey = context.secrets.STRIPE_API_KEY
      const response = await fetch("https://api.stripe.com/v1/charges", {
        method: "POST",
        headers: { "Authorization": `Bearer ${apiKey}` },
        body: `amount=${args.amount}`,
      })
      return await response.json()
    },
  },
])
```

`context.secrets` is scoped to the same environment and organization as the running tool, so dev tools read dev secrets and production tools read production secrets.

## Security note

Secrets are stored as-is and **masked when listed** in the dashboard; org admins can reveal a value with the eye toggle. They are **not redacted** elsewhere — a secret referenced in a prompt appears in the compiled prompt, and any value used in a tool call appears in execution telemetry. Treat secret values as sensitive: keep your `.env.development` and `.env.production` files out of version control (add them to `.gitignore`) and do not paste secret values into shared logs or screenshots.
