Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.zavu.dev/llms.txt

Use this file to discover all available pages before exploring further.

Secrets

Function secrets are encrypted at rest and injected as environment variables at runtime. The function reads them via process.env.<KEY> just like in any Node program.
zavu fn secrets set SENDER_ID jn76vnxet8g5nq661by3v06y1581bmmn
zavu fn secrets set DATABASE_URL postgresql://...
zavu fn secrets set OPENAI_API_KEY sk-...
defineAgent({
  senderId: process.env.SENDER_ID!,
  ...
})

defineTool({
  ...,
  handler: async () => {
    const db = postgres(process.env.DATABASE_URL!)
    // ...
  }
})

Setting secrets

Inline

zavu fn secrets set OPENAI_API_KEY sk-abc123
The value is in your shell history — fine for non-secret config, not great for real keys.

From a file

zavu fn secrets set GOOGLE_SERVICE_ACCOUNT --from-file ./sa.json
Reads the file as UTF-8. Trailing whitespace is stripped. Useful for multi-line values (PEM keys, JSON service accounts).

From stdin (safest)

pbpaste | zavu fn secrets set OPENAI_API_KEY -
# or
echo "$SECRET_FROM_VAULT" | zavu fn secrets set KEY -
Nothing touches disk or shell history. The - placeholder tells the CLI to read from stdin until EOF.

Listing

zavu fn secrets list
key              value    synced
─────────────  ────────  ──────
SENDER_ID       …1bmmn    yes
DATABASE_URL    …5432     yes
OPENAI_API_KEY  …sk-x     no
  1 secret not yet pushed to Lambda — run `zavu deploy` to sync.
Only the last 4 characters of each value are shown. Plaintext is never returned by the API — even from the dashboard, only the same last-4 is visible.

Removing

zavu fn secrets unset OLD_KEY
# alias
zavu fn secrets rm OLD_KEY

When changes take effect

Setting / unsetting a secret marks the function as out of sync. The next zavu deploy rebuilds the Lambda with the new env vars. Until then, the running function still has the old environment.
$ zavu fn secrets set NEW_KEY value
✓ Created NEW_KEY (…alue)
  Lambda env var updates on the next `zavu deploy`. Run it now to apply.

$ zavu deploy
... function now sees process.env.NEW_KEY
You can batch secret changes before a single deploy. Setting 5 secrets in a row results in 1 sync (the next deploy), not 5.

Constraints

ConstraintLimit
Key format[A-Z_][A-Z0-9_]* (uppercase env-var style)
Key length≤ 64 chars
Reserved prefixesAWS_, LAMBDA_, _HANDLER, _X_AMZN (Lambda reserves these)
Value size≤ 4096 chars
Total secrets per function50
Total env size4 KB (AWS Lambda hard limit)
For values larger than 4 KB (large JSON blobs, certificates), upload to S3 / Convex storage and store a URL + auth header pair instead.

Auto-provisioned secrets

Every function created by zavu fn init gets these injected automatically — you don’t set them yourself:
KeyValuePurpose
ZAVU_API_KEYA unique live API key scoped to this function’s projectLets the function call Zavu’s REST API.
ZAVU_API_BASE_URLThe dashboard’s Convex .site URLSo local-dev functions hit the right backend.
ZAVU_PROJECT_IDThe function’s project IDFor logging / multi-tenant code.
ZAVU_FUNCTION_IDThis function’s IDFor logging.
ZAVU_FUNCTION_SLUGThis function’s slugFor logging / URL construction.
Use them directly:
import Zavudev from "@zavudev/sdk"

const zavu = new Zavudev({
  apiKey: process.env.ZAVU_API_KEY!,
  baseURL: process.env.ZAVU_API_BASE_URL,
})
ZAVU_API_KEY is revoked automatically when you zavu fn delete the function. If you reset it manually from the dashboard’s API Keys page, the function will start failing — redeploy to provision a new one.The auto-key has messages:send, messages:read, contacts:read scopes. For other operations create a separate scoped key and inject it as a secret.

Encryption

Values are encrypted with AES-256-GCM, key derived via PBKDF2 (100,000 iterations, SHA-256) from the platform encryption key. Encryption happens server-side before the value is persisted, so plaintext never lives in our database. The Lambda receives plaintext at deploy time as a standard environment variable, encrypted at rest by AWS (KMS-managed CMK). Inside the function, process.env.X returns the decrypted value.

Common patterns

zavu fn secrets set OPENAI_API_KEY sk-new-value
zavu deploy
# The old key is now overwritten in storage; revoke it in OpenAI's dashboard.
Functions are project-scoped — if you have separate Zavu projects for staging vs prod, each has its own secrets.
zavu login                # pick staging project
zavu fn secrets set DB_URL postgres://staging…
zavu deploy

zavu login                # pick prod project
zavu fn secrets set DB_URL postgres://prod…
zavu deploy
zavu whoami shows the current project before each operation.
Never commit secret values. Commit a .zavu/secrets.example.yml style file with key names + descriptions, and have a teammate’s setup script prompt for actual values:
# setup.sh
while read line; do
  [[ -z "$line" ]] && continue
  key=$(echo "$line" | cut -d= -f1)
  desc=$(echo "$line" | cut -d= -f2-)
  read -s -p "Enter $key ($desc): " val
  echo
  zavu fn secrets set "$key" "$val"
done < secrets.spec
Use ZAVUDEV_API_KEY env var so the CLI uses your CI’s key:
# .github/workflows/deploy.yml
env:
  ZAVUDEV_API_KEY: ${{ secrets.ZAVU_CI_KEY }}
steps:
  - run: |
      zavu fn secrets set DB_URL "${{ secrets.DB_URL }}"
      zavu fn secrets set API_KEY "${{ secrets.API_KEY }}"
      zavu deploy

API equivalence

For automation, the secret endpoints are part of the public API:
# Set
curl -X PUT https://api.zavu.dev/v1/functions/$FN_ID/secrets/SENDER_ID \
  -H "Authorization: Bearer $KEY" \
  -d '{"value":"jn76…"}'

# List (values never returned)
curl https://api.zavu.dev/v1/functions/$FN_ID/secrets \
  -H "Authorization: Bearer $KEY"

# Unset
curl -X DELETE https://api.zavu.dev/v1/functions/$FN_ID/secrets/OLD_KEY \
  -H "Authorization: Bearer $KEY"
See the API reference for full schemas.