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

# Secrets and Secret Variables

> Store and use sensitive values in Narada without hardcoding them into prompts or workflow state

## Overview

Use secrets for credentials and other sensitive values that an agent needs to use but should not treat as ordinary prompt or workflow data. This includes API keys, passwords, bearer tokens, webhook signing keys, and private account identifiers.

Secrets are different from [input variables](/documentation/input-variables). Input variables are visible to the agent and should be used for normal run data. Narada does not pass secret plaintext to the LLM. Secrets are stored or passed through a protected path, represented in prompts and traces as placeholders or masked handles, and resolved only by the execution step that needs the plaintext value.

<CardGroup cols={3}>
  <Card title="One-off secret variables" icon="key">
    Pass sensitive values at run time with SDK `secret_variables` or REST `secretVariables`. Use `${name}` in the prompt.
  </Card>

  <Card title="Organization secrets" icon="building">
    Store reusable secrets for your organization and attach them to Agent Studio variables of type `secretString`.
  </Card>

  <Card title="Custom-agent secrets" icon="lock">
    Store a secret on a single custom agent when the credential should travel with that agent instead of the organization vault.
  </Card>
</CardGroup>

<Warning>
  Do not put credentials in `input_variables`, `inputVariables`, normal prompt text, or workflow variables of type `string`. Use secrets whenever the value is not meant to be read, reasoned about, or returned by the agent.
</Warning>

## Choose the Right Option

| Need                                                                | Use                                              | Syntax                      |
| ------------------------------------------------------------------- | ------------------------------------------------ | --------------------------- |
| Pass normal data the agent can read                                 | `input_variables` or `inputVariables`            | `{{$customerName}}`         |
| Pass a sensitive value for one SDK or REST run                      | `secret_variables` or `secretVariables`          | `${password}`               |
| Reuse a credential across Agent Studio workflows in an organization | Organization secret plus `secretString` variable | `{{$apiToken}}`             |
| Keep a credential scoped to one custom agent                        | Custom-agent secret                              | `secrets.API_KEY` in Python |

The two syntaxes are intentional:

* `${name}` is for one-off SDK and REST secret variables.
* `{{$name}}` is for Agent Studio workflow variables, including variables of type `secretString`.

## Organization Secrets

Organization secrets are reusable values stored for your Narada organization. They are useful for API keys and service credentials that multiple custom agents need.

Create and manage them from **Organization secrets** in the Narada app, or create one while selecting a secret for a `secretString` variable in Agent Studio.

When you save an organization secret:

* Narada stores the value encrypted.
* The plaintext value is not displayed again after creation.
* Secret lists and selectors show only the name and a masked preview.
* Secret names must start with a letter and contain only letters, numbers, and underscores.
* Secret values can be up to 4096 bytes of UTF-8 text.

Organization secrets are referenced by a stable secret ID, not only by name. Updating or renaming a secret keeps the same ID, so existing agents continue to resolve it. Deleting a secret and creating a new secret with the same name creates a new ID; agents that referenced the deleted secret need to be reattached to the new one.

## Agent Studio Secret Variables

In Agent Studio, create a workflow variable with type `secretString`, then choose an organization secret. The workflow variable stores the secret ID and display metadata, not the plaintext value.

Use the secret variable in workflow fields with the same variable syntax as other Agent Studio variables:

```text theme={null}
Authorization: Bearer {{$apiToken}}
```

During a run, Narada injects an opaque secret handle. The handle displays as `********` in traces, JSON serialization, and accidental string conversion. For model-facing prompt text, Narada keeps the `{{$apiToken}}` placeholder instead of inserting the secret value. For supported execution payloads, Narada resolves the secret immediately before the action is sent.

<Note>
  A `secretString` variable is a secret handle, not a normal string. It does not support indexed access like `{{$apiToken[0]}}`.
</Note>

Secret variables are intentionally read-only:

* They cannot be selected as workflow output variables.
* They cannot be used in conditions.
* They cannot be mapped into child custom-agent runs.
* Python and workflow exports do not include their secret values.

## Python Agents and Code Steps

Python code receives `secretString` variables as `SecretVariable` handles inside the `variables` dictionary. Call `await .get()` only at the point where your code needs the plaintext.

```python theme={null}
api_token_handle = variables["apiToken"]

print(api_token_handle)  # ********

api_token = await api_token_handle.get()
headers = {"Authorization": f"Bearer {api_token}"}
```

The value returned by `.get()` is a normal Python string. Avoid printing it, returning it, or writing it into another workflow variable.

Custom-agent scoped secrets are available through the `secrets` namespace:

```python theme={null}
api_key = await secrets.API_KEY.get()
```

Use attribute access when the secret name is a valid Python attribute. Use item access for dynamic lookups:

```python theme={null}
secret_name = "API_KEY"
api_key = await secrets[secret_name].get()
```

## SDK and REST Secret Variables

For one-off SDK and REST runs, pass sensitive values through `secret_variables` or `secretVariables`. Reference those values in the prompt with `${name}` placeholders.

<Tabs>
  <Tab title="Python SDK">
    ```python theme={null}
    import os

    from narada import Agent, BrowserEnvironment

    env = BrowserEnvironment()
    agent = Agent(environment=env)

    response = await agent.run(
        prompt="Log in with username ${username} and password ${password}.",
        secret_variables={
            "username": os.environ["APP_USERNAME"],
            "password": os.environ["APP_PASSWORD"],
        },
    )
    ```
  </Tab>

  <Tab title="REST API">
    ```json theme={null}
    {
      "prompt": "/$USER/login-agent Log in with username ${username} and password ${password}.",
      "browserWindowId": "your-browser-window-id",
      "secretVariables": {
        "username": "<username>",
        "password": "<password>"
      }
    }
    ```
  </Tab>
</Tabs>

With one-off secret variables, the model sees placeholders such as `${password}` while planning. The plaintext values are substituted later for the action that needs them.

One-off secret variables are not Agent Studio organization secrets. Use organization secrets when you want to save and reuse a credential across custom agents.

## Redaction and Limits

Narada masks secret handles as `********` and redacts exact secret substrings from visible model output and structured output when a resolved secret appears there. This is a safety guardrail, not a reason to ask an agent to repeat or transform secrets.

Once plaintext is intentionally sent to a browser page, connector, API, Python library, or other external system, that system receives the value. Redaction may not catch transformed values, partial values, screenshots, hashes, or third-party logs.

Use these habits for sensitive workflows:

* Keep credentials in secrets from the start.
* Resolve a secret as late as possible.
* Do not print or return plaintext secrets from Python.
* Do not ask agents to summarize, compare, or reveal secret values.
* Attach secrets separately to each custom agent that needs them.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Secret is not part of this workflow">
    The workflow can only resolve secrets that are attached to that workflow. Reattach the organization secret or add the custom-agent secret again.
  </Accordion>

  <Accordion title="A secret stopped resolving after I recreated it">
    Organization secrets are referenced by secret ID. If you delete a secret and create a new one with the same name, existing agents still point at the deleted ID and need to be reattached.
  </Accordion>

  <Accordion title="A secret with this name already exists">
    Secret names are unique within the organization. Rename the existing secret, update its value, or choose a different name.
  </Accordion>

  <Accordion title="My Python export does not include the secret value">
    Exports intentionally omit secret values. Recreate the needed secret in Agent Studio and attach it before running the workflow there.
  </Accordion>

  <Accordion title="A secret appears as ********">
    That is expected for display, traces, logs, and accidental string conversion. In Python, call `await variables["name"].get()` or `await secrets.NAME.get()` only when plaintext is required.
  </Accordion>
</AccordionGroup>
