#where to add api keys that are required for scripts /programs that will be invoked by skills ?

1 messages · Page 1 of 1 (latest)

glass flint
#

where to add api keys that are required for scripts /programs that will be invoked by skills when skills are asked to run is it safe to keep in openclaw.json ?

rugged hollowBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> ✅ Mark Solution

glass flint
#

i have kept the keys under skills.entries is this recommended approach ?

jolly coyoteBOT
#

Use env vars/secrets, not plaintext in the skill itself.

Best options:

  1. General script env vars: put them in the Gateway environment or ~/.openclaw/.env:
MY_SERVICE_API_KEY=...

OpenClaw loads ~/.openclaw/.env without overriding already-set env vars.

  1. Per-skill config: use skills.entries.<skillKey> in ~/.openclaw/openclaw.json:
{
#
  skills: {
    entries: {
      "my-skill": {
        env: {
          MY_SERVICE_API_KEY: "..."
        }
      }
    }
  }
}

This works, but it’s still plaintext in openclaw.json.

  1. Safer per-skill API key: if the skill declares a primaryEnv, use apiKey with a SecretRef:
#
{
  skills: {
    entries: {
      "my-skill": {
        apiKey: { source: "env", provider: "default", id: "MY_SERVICE_API_KEY" }
      }
    }
  }
}

That keeps openclaw.json pointing at the env var instead of storing the key directly.

So: is it safe to keep keys in openclaw.json? It works, but I’d avoid it unless the file is local-only, not committed, and locked down (chmod 600). Prefer ~/.openclaw/.env, process env, or SecretRefs / 1Password / Vault for real secrets.

Docs:

#

Yes, skills.entries is the right place for per-skill config/env, but for API keys I’d split it like this:

  • Recommended shape: skills.entries.<skill>.apiKey as a SecretRef or env-backed value.
  • ⚠️ Works but less ideal: plaintext keys inside skills.entries.<skill>.env.

Example recommended:

{
  skills: {
    entries: {
      "my-skill": {
        apiKey: { source: "env", provider: "default", id: "MY_SERVICE_API_KEY" }
      }
    }
  }
glass flint
#

is it same for channels as well

jolly coyoteBOT
#

Same principle, different location.

For channel credentials, use the channel’s own config path — not skills.entries.

Example:

{
  channels: {
    discord: {
      enabled: true,
      token: { source: "env", provider: "default", id: "DISCORD_BOT_TOKEN" }
    },
    telegram: {
      enabled: true,
      botToken: { source: "env", provider: "default", id: "TELEGRAM_BOT_TOKEN" }
#
    }
  }
}

Then keep the real secrets in ~/.openclaw/.env or the Gateway process env:

DISCORD_BOT_TOKEN=...
TELEGRAM_BOT_TOKEN=...

Plaintext directly in openclaw.json usually works, but I’d treat it as “okay for quick local testing,” not the recommended long-term setup. Prefer env vars / SecretRefs / token files where supported.

Channel field names vary (token, botToken, appToken, signingSecret, serviceAccountRef, etc.), so check the specific channel doc.

glass flint
#

We're using SecretRefs for channels.slack and gateway.auth — works great. But skills.entries.env only accepts plain strings, not SecretRef objects. Is there a supported way to reference env vars in skills.entries.env instead of storing plaintext API keys there? Or is this on the roadmap?

jolly coyoteBOT
#

Yes — for skills.entries.env, use ${VAR_NAME} env substitution. SecretRef objects are supported on skills.entries.<skill>.apiKey, but not directly inside skills.entries.<skill>.env.

Example:

# ~/.openclaw/.env
MY_TOOL_API_KEY=...
{
  skills: {
    entries: {
      "my-skill": {
        env: {
          MY_TOOL_API_KEY: "${MY_TOOL_API_KEY}"
#
        }
      }
    }
  }
}

If the skill declares that key as its primaryEnv, the cleaner option is:

{
  skills: {
    entries: {
      "my-skill": {
        apiKey: { source: "env", provider: "default", id: "MY_TOOL_API_KEY" }