Connections

Secrets

Declare secret names in the file (including vendor API keys), set values in the encrypted project vault, or use type: managed for Enterprise platform keys.

A secret block declares a named group of sensitive values, such as API keys and tokens. Set the values in the encrypted project vault. Enterprise projects can use type: managed for platform-supplied vendor keys.

Credential profiles and agents reference a secret block by name. Nodes declare the variables they need in a secrets: map and read them through context.secrets.

Vendor integrations resolve their API keys internally from declared secret blocks. Those keys appear in context.secrets only if the node also lists them in its secrets: map.

secret

Group related secret variable names (not values) in a top-level block. Values are set out-of-band in the project vault; no value ever appears in a .swirls file or a deployment.

FieldTypeRequiredDescription
labelstringNoDisplay label.
descriptionstringNoDescription.
typeidentifierNoOnly managed — platform supplies values (Enterprise). Omit for user vault values.
varsidentifier arrayYesSecret key identifiers (e.g. API_KEY, OPENROUTER_API_KEY).
secret api_k {
  label: "Third-party API"
  vars: [API_KEY, API_SECRET]
}

secret llm_keys {
  type: managed
  vars: [OPENROUTER_API_KEY]
}

Block names and var names match ^[a-zA-Z0-9_]+$. Repeating a var within one block is an error. Managed blocks may only list known platform vendor keys.

The project vault

Each project has its own vault. Values are encrypted at rest with per-project keys, and the vault is write-only: no CLI command, API route, or dashboard page ever returns a stored value. Listings show whether a value is set, never what it is.

Set values with the swirls secret commands or on the project's Secrets page in the dashboard:

CommandBehavior
swirls secret set KEY=VALUEStores the value as block::VAR for each matching non-managed secret block var. Rejects managed vars.
swirls secret listLists the vault's keys and whether a value is set. Alias: ls.
swirls secret remove KEYDeletes the stored value. Alias: rm.

All three take --project to target a project explicitly. If the same var name is declared in more than one block, swirls secret set writes every matching non-managed target and reports each.

Managed blocks show as "Managed by Swirls" on the Secrets page — no value input is offered.

Node-level secrets:

On root { } or node name { }, list which vars from which blocks this node may access. This example uses the api_k block declared above:

workflow example {
  label: "Example"
  root {
    type: code
    label: "Entry"
    secrets: {
      api_k: [API_KEY]
    }
    code: @ts {
      const key = context.secrets.api_k.API_KEY
      return { hasKey: Boolean(key) }
    }
  }
}

Access pattern: context.secrets.<blockName>.<VAR>. See Context. The secrets: value is always an object literal, never a bare block name, a string, or a flat array. There is no process.env in @ts code; it is an empty object in the sandbox.

A node receives only the secret variables listed in its declaration, delivered at runtime.

Who references a secret block

ConsumerSyntaxMeaning
Any nodesecrets: { <block>: [VAR, ...] }Allowlist of vars the node may read via context.secrets.
auth / postgres blocksecrets: <block> (bare identifier)The single block whose vars back the credential fields.
agent blocksecrets: <block> (bare identifier, required)Block holding the model API key and any agent credentials.
decision blocksecrets: <block> (bare identifier, required)Exact customer-owned or managed block declaring TYPESAFE_API_KEY.
webhook blocksecret: <block>.<VAR> (dotted reference)Shared-secret value compared against the inbound header:.

The validator checks that every referenced block exists and every listed var is declared in it.

Required vendor keys

Node types that call third-party APIs need the corresponding key declared in some secret block (user or type: managed):

Node typeRequired secret
ai, agentOPENROUTER_API_KEY, or OPENAI_API_KEY / ANTHROPIC_API_KEY / GOOGLE_GENERATIVE_AI_API_KEY per provider:
emailRESEND_API_KEY
scrape, search (default or provider: firecrawl)FIRECRAWL_API_KEY
search with provider: telemTELEM_API_KEY
parallelPARALLEL_API_KEY
decisionTYPESAFE_API_KEY in the exact block referenced by the decision declaration
diskARCHIL_API_KEY (platform-only; never declared in DSL)

Until a required key is declared and satisfiable (vault value set, or managed + Enterprise), executions for the nodes that need it are held with secrets_hold. They pick up the fix on the next run after you update the DSL / vault / plan.

Further reading

  • Context — context.secrets shape
  • Auth — credential profiles built on secret blocks

TypeSafe decision credentials

A decision declaration requires secrets: <block> referencing a block with vars: [TYPESAFE_API_KEY]. By default, set the value on that exact project secret slot. Swirls resolves <block>::TYPESAFE_API_KEY without scanning other blocks or falling back to operator credentials.

For managed access, add type: managed to the referenced secret block. The existing Enterprise platform_keys entitlement applies. Swirls supplies the platform's TypeSafe key to native decision execution and records it as platform usage; no vault value is needed or accepted. Both modes use the same explicit block reference. A decision node cannot override the binding, and state/model expressions receive no vendor credentials. Managed TypeSafe keys are not readable through ordinary code or HTTP/auth nodes. See the managed example.

On this page