Secrets
Blocks often need credentials — a database connection string, an AI API key — that must not appear in the pipeline file, logs, or on disk. Spade delivers these through secrets: named values a block reads at run time with get_secret, resolved from a secure store and injected into the sandbox by the runtime.
How it works🔗
The block author reads a secret by a logical name:
from spade import run, get_secret def handler(): dsn = get_secret("db") # logical name — the credential the block needs # ... connect and query ...The pipeline binds that logical name to one of your stored secrets. Only the secret's name appears in the pipeline — never its value:
- id: 019cf4bc-2222-7000-0000-000000000000 name: db.query args: query: "SELECT * FROM parcels" secrets: db: prod-postgres-dsnAt run time the runtime resolves the value — from the OS keychain for a local
spade run, or from the cloud KMS for a cloud run — and injects it into the block.get_secret("db")returns the value.
The value only ever exists in the block process's memory; it is never written to disk.
get_secret in each language🔗
The function is the same across every runtime library — it takes the logical name and returns the value, and raises/returns an error if the secret was not provided.
| Language | Call | Reference |
|---|---|---|
| Python | get_secret("db") | Python handlers |
| R | get_secret("db") | R handlers |
| TypeScript | getSecret("db") | TypeScript handlers |
| Go | GetSecret("db") | Go handlers |
| Rust | get_secret("db")? | Rust handlers |
Setting secrets🔗
For local runs, store secrets in the OS keychain with the CLI:
spade secret set prod-postgres-dsnSee spade secret for the full command reference.
Local vs. cloud🔗
Local secrets (keychain) and cloud secrets (KMS) are independent namespaces, so the same pipeline can resolve a name to a development credential locally and a production credential in the cloud. A block that references a secret must find it in the store for wherever it runs.
Network access is separate🔗
Reading a secret does not require network access. If a block also needs the network — for example to reach the database whose connection string it just read — its block.yaml must additionally declare network: true. The two are independent: get_secret works without network, and network access is surfaced separately so users can see which blocks reach out.