#Re Openclaw's secret management

1 messages · Page 1 of 1 (latest)

timid cove
#

I ran openclaw secrets configure , followed the instructions for Tavily api key. Then now I can't find where they actual key is saved. I have checked, it is not in .openclaw/.env or .openclaw/gateway.systemd.env

here's my openclaw.json

        "enabled": true,
        "config": {
          "webSearch": {
            "apiKey": {
              "source": "env",
              "provider": "default",
              "id": "TAVILY_API_KEY"
            }
          }
        }
      }```

version is OpenClaw 2026.4.15 (041266a) .

But Tavily is still working, so where is the actual key saved at?
modern houndBOT
#

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

winged rivetBOT
bronze reefBOT
#

Let me verify against the local docs and source so I don’t guess.

#

Short version: with that config, the actual Tavily key is probably not stored by secrets configure at all.

What you have here:

{ source: "env", provider: "default", id: "TAVILY_API_KEY" }

means OpenClaw only stores the reference in openclaw.json. At runtime it reads TAVILY_API_KEY from the gateway process environment.

So if Tavily still works, the real key is likely coming from one of these:

  1. the gateway process environment
  2. .env in the working directory used to start the gateway
  3. ~/.openclaw/.env
  4. the env / env.vars block in openclaw.json
  5. env.shellEnv.enabled: true importing your login shell
#
  1. Ubuntu compat fallback: ~/.config/openclaw/gateway.env

Also, ~/.openclaw/gateway.systemd.env is not where secrets configure writes env-backed secrets. That file is only generated for systemd from state-dir .env, and it may be empty or absent.

I checked the docs/source for this on 2026.4.15, and env refs resolve from process.env[...], not from a separate secret store.

Docs:

If you want, I can help you narrow down which of those 6 is supplying TAVILY_API_KEY on your box.

timid cove
#

yes please

bronze reefBOT
#

Yep. I’d check it in this order, and don’t paste the actual key back here.

# 1) Is shell env import enabled?
grep -n 'shellEnv' ~/.openclaw/openclaw.json

# 2) Is TAVILY_API_KEY set inline in the config env block?
grep -n 'TAVILY_API_KEY\|vars' ~/.openclaw/openclaw.json

# 3) Ubuntu compatibility fallback
grep -n 'TAVILY_API_KEY' ~/.config/openclaw/gateway.env 2>/dev/null

# 4) Common shell startup files
grep -n 'TAVILY_API_KEY' ~/.bashrc ~/.bash_profile ~/.profile ~/.zshrc ~/.zprofile 2>/dev/null

# 5) If you use the systemd user service, check whether systemd has it
#
systemctl --user show-environment | grep '^TAVILY_API_KEY='

# 6) Linux only: confirm the running gateway process has it, without printing the secret
tr '\0' '\n' < /proc/$(pgrep -u "$USER" -f 'openclaw.*gateway' | head -1)/environ \
  | sed -n '/^TAVILY_API_KEY=/s/=.*/=<set>/p'

How to read the results:

  • found in ~/.config/openclaw/gateway.env → that’s the source
  • found in shell files + shellEnv.enabled: true → OpenClaw is importing it from your login shell
  • found only in systemctl --user show-environment → systemd manager env has it
  • only step 6 shows <set> → the running gateway process has it, but it’s coming from inherited process/service env rather than OpenClaw config files

Most likely from what you described: either env.shellEnv.enabled or ~/.config/openclaw/gateway.env.

#

If you want, send back which of the 6 steps matched, and I’ll help interpret it.

timid cove
#

found it in grep -n 'TAVILY_API_KEY' ~/.config/openclaw/gateway.env 2>/dev/null 192: "id": "TAVILY_API_KEY"

#

but i can't navigate to the folder. It says doesn't exist

bronze reefBOT
#

That’s actually useful, it means it’s probably not coming from ~/.config/openclaw/gateway.env.

A couple of gotchas:

  • ~ is shell shorthand for your home directory
  • it usually works in a terminal, but not in Finder / Explorer / some file pickers
  • if that folder truly doesn’t exist, that’s fine, it’s only a compatibility fallback on some installs

Try this in a terminal:

echo $HOME
ls -la ~/.openclaw
grep -n 'shellEnv\|TAVILY_API_KEY\|vars' ~/.openclaw/openclaw.json
grep -n 'TAVILY_API_KEY' ~/.bashrc ~/.bash_profile ~/.profile ~/.zshrc ~/.zprofile 2>/dev/null
#

What I’d expect:

  • if shellEnv.enabled is on, the key is probably coming from your shell files
  • if env.vars contains it, it’s coming from openclaw.json
  • if neither matches, then it’s likely inherited from the service/process environment

Real folder examples:

  • Linux: /home/yourname/.openclaw
  • macOS: /Users/yourname/.openclaw

If you want, paste the output of just:

grep -n 'shellEnv\|vars' ~/.openclaw/openclaw.json
#

and I’ll help read it. Don’t paste the actual key.

timid cove
#

it returned nothing

bronze reefBOT
#

Good, that narrows it down.

If that grep returned nothing, then the key is not coming from:

  • env.shellEnv.enabled
  • inline env.vars in openclaw.json

So the next likely places are:

  1. the running gateway process environment
  2. a .env in the directory the gateway was started from
  3. the systemd user environment (if you run it as a service)

Try these, still read-only, and they won’t print the secret value:

#
# 1) See how the gateway is running
openclaw gateway status

# 2) Check the running gateway process env without showing the key
tr '\0' '\n' < /proc/$(pgrep -u "$USER" -f 'openclaw.*gateway' | head -1)/environ \
  | sed -n '/^TAVILY_API_KEY=/s/=.*/=<set>/p'

# 3) If using systemd user service, check its env
systemctl --user show-environment | sed -n '/^TAVILY_API_KEY=/s/=.*/=<set>/p'

If step 2 shows <set>, then the key is definitely in the gateway process env, and secrets configure only stored the ref.

One more sneaky possibility: if you’re only testing generic web_search, OpenClaw might be using some other web provider, not Tavily. So if step 2 and 3 both show nothing, that’s the next thing I’d check.

If you paste the output of just:

#
openclaw gateway status

I can tell you the most likely source right away.

timid cove
#
OpenClaw 2026.4.15 (041266a) — Welcome to the command line: where dreams compile and confidence segfaults.

│
◇
Service: systemd (enabled)
File logs: /tmp/openclaw/openclaw-2026-04-23.log
Command: /usr/bin/node /usr/lib/node_modules/openclaw/dist/index.js gateway --port 18789
Service file: ~/.config/systemd/user/openclaw-gateway.service
Service env: OPENCLAW_GATEWAY_PORT=18789

Config (cli): ~/.openclaw/openclaw.json
Config (service): ~/.openclaw/openclaw.json

Gateway: bind=loopback (127.0.0.1), port=18789 (service args)
Probe target: ws://127.0.0.1:18789
Dashboard: http://127.0.0.1:18789/
Probe note: Loopback-only gateway; only local clients can connect.

Runtime: running (pid 201157, state active, sub running, last exit 0, reason 0)
RPC probe: ok

Listening: 127.0.0.1:18789
Troubles: run openclaw status
Troubleshooting: https://docs.openclaw.ai/troubleshooting
bronze reefBOT
#

Perfect, that narrows it down a lot.

From that status output:

  • the systemd unit is active
  • the unit summary only shows OPENCLAW_GATEWAY_PORT
  • so secrets configure did not write TAVILY_API_KEY into the service file/env summary

At this point, the remaining likely places are:

  1. the systemd user manager environment
  2. an EnvironmentFile= referenced by the unit
  3. the running gateway process env

Try these:

#
# 1) Does systemd itself hold the variable?
systemctl --user show-environment | sed -n '/^TAVILY_API_KEY=/s/=.*/=<set>/p'

# 2) Does the unit reference any env file?
systemctl --user cat openclaw-gateway.service | grep -E 'Environment=|EnvironmentFile='

# 3) Does the running gateway process have it?
tr '\0' '\n' < /proc/201157/environ | sed -n '/^TAVILY_API_KEY=/s/=.*/=<set>/p'

How to read that:

  • 1 = <set> → systemd user env has it
  • 2 shows EnvironmentFile=... → check that file
  • 3 = <set> → the running gateway definitely has it in env
#

If 1 and 3 both show nothing, then I’d start suspecting you’re not actually using Tavily at runtime, unless tools.web.search.provider is explicitly set to "tavily".

If you paste the output of #2 only, I can probably tell you exactly where to look next.

timid cove
#

EnvironmentFile=-/root/.openclaw/gateway.systemd.env
Environment=HOME=/root
Environment=TMPDIR=/tmp
Environment=PATH=/usr/bin:/root/.bun/bin:/root/.local/bin:/root/.npm-global/bin:/root/bin:/root/.volta/bin:/root/.asdf/shims:/root/.nvm/current/bin:/root/.fnm/current/bin:/root/.local/share/pnpm:/usr/local/bin:/bin
Environment=OPENCLAW_GATEWAY_PORT=18789
Environment=OPENCLAW_SYSTEMD_UNIT=openclaw-gateway.service
Environment="OPENCLAW_WINDOWS_TASK_NAME=OpenClaw Gateway"
Environment=OPENCLAW_SERVICE_MARKER=openclaw
Environment=OPENCLAW_SERVICE_KIND=gateway
Environment=OPENCLAW_SERVICE_VERSION=2026.4.15
Environment=OPENCLAW_SERVICE_MANAGED_ENV_KEYS=BRAVE_API_KEY,DISCORD_BOT_TOKEN,GOOGLE_API_KEY,OPENCLAW_GATEWAY_TOKEN,OPENROUTER_API_KEY
Environment=OPENCLAW_NO_RESPAWN=1
Environment=NODE_COMPILE_CACHE=/var/tmp/openclaw-compile-cache

bronze reefBOT
#

Ah, this is the clue.

That output strongly suggests OpenClaw did not save a Tavily key anywhere.

Why:

  • EnvironmentFile=-/root/.openclaw/gateway.systemd.env means that file is optional
  • OPENCLAW_SERVICE_MANAGED_ENV_KEYS=... shows which env keys the service is actively managing
  • TAVILY_API_KEY is not in that list
  • but BRAVE_API_KEY and GOOGLE_API_KEY are

So my best read now is:

  1. secrets configure only saved the ref in openclaw.json
  2. the actual Tavily key was not written into systemd env
  3. your “Tavily is still working” test is probably generic web_search using Brave or Google instead
#

That fits the docs too, because in auto web search mode, Tavily is checked after Brave and Google.

Two quick checks:

# Does the running gateway actually have TAVILY_API_KEY?
tr '\0' '\n' < /proc/201157/environ | sed -n '/^TAVILY_API_KEY=/s/=.*/=<set>/p'

# Is web search explicitly pinned to Tavily?
grep -n 'provider' ~/.openclaw/openclaw.json

If:

  • the /proc/.../environ check shows nothing
  • and your config does not explicitly set tools.web.search.provider to "tavily"
#

then the answer is basically:

the Tavily key is not saved anywhere, because Tavily is not the active search provider right now.

Docs: https://docs.openclaw.ai/tools/web

If you want, I can give you the exact openclaw.json snippet to force Tavily so you can test it cleanly.

timid cove
#

yes

bronze reefBOT
#

Yep, set it like this so web_search is explicitly pinned to Tavily:

{
  plugins: {
    entries: {
      tavily: {
        enabled: true,
        config: {
          webSearch: {
            apiKey: {
              source: "env",
              provider: "default",
              id: "TAVILY_API_KEY",
            },
          },
#
        },
      },
    },
  },
  tools: {
    web: {
      search: {
        provider: "tavily",
      },
    },
  },
}

Then restart the gateway:

#
openclaw gateway restart

What this does:

  • keeps your Tavily key as an env ref
  • forces generic web_search to use Tavily
  • avoids silently falling back to Brave/Google/other providers

If Tavily still works after that, then TAVILY_API_KEY really is present in the runtime env somewhere.
If it breaks, then your earlier tests were almost certainly hitting another provider.

Docs: https://docs.openclaw.ai/tools/tavily and https://docs.openclaw.ai/tools/web

Glad we found the weird part 😅

timid cove
#

web_search is already pinned to Tavily before this.

and do note that TAVILY_API_KEY still resolves to my actualy tavily api key correctly

bronze reefBOT
#

Yep, then we’ve basically got the answer:

openclaw secrets configure did not save the Tavily key itself.
It only saved the env ref:

{ source: "env", provider: "default", id: "TAVILY_API_KEY" }

Since:

  • web_search is pinned to Tavily
  • TAVILY_API_KEY resolves correctly
  • the systemd unit/env file does not contain the key

the actual key is coming from your existing environment, not from OpenClaw storage.

#

Because your service is running as root (HOME=/root), the likely places are:

  • /root/.bashrc
  • /root/.profile
  • /root/.zshrc
  • /etc/environment
  • /etc/profile
  • /etc/profile.d/*
  • or the systemd user manager environment

You can search those safely with:

grep -Rsn 'TAVILY_API_KEY' /root/.bashrc /root/.profile /root/.zshrc /etc/environment /etc/profile /etc/profile.d 2>/dev/null
systemctl --user show-environment | sed -n '/^TAVILY_API_KEY=/s/=.*/=<set>/p'
#

If those both show nothing, then the key may not be saved on disk at all. It may only exist in the live process/session environment.

So the direct answer to your original question is:

It is not saved by OpenClaw.
OpenClaw is just reading TAVILY_API_KEY from the environment you already have.

Glad we pinned that down. If this solved it, please right-click the solution message → Apps → ✅ Mark Solution so Answer Overflow can index it.

timid cove
#
tvly-...0pYxIVOlJO```
bronze reefBOT
#

Yep, that’s the smoking gun.

printenv TAVILY_API_KEY returning the real value means:

  • the key already exists in your current environment
  • OpenClaw is just reading it via the env ref
  • openclaw secrets configure did not store the secret itself

So the answer is:

the actual key is not saved by OpenClaw
it’s coming from your shell / system environment

printenv tells us the var exists, but not where it was originally set. The most likely sources are still:

  • /root/.bashrc
  • /root/.profile
#
  • /etc/environment
  • /etc/profile.d/*
  • or systemd user environment

If you want the exact file that set it, this is the most direct search:

grep -Rsn 'TAVILY_API_KEY' /root/.bashrc /root/.profile /root/.zshrc /etc/environment /etc/profile /etc/profile.d 2>/dev/null

Also, nice job redacting it 👍
If this solved it, please right-click the solution message → Apps → ✅ Mark Solution so it gets indexed on Answer Overflow.

timid cove
#

that grep returned nothing

bronze reefBOT
#

Then yeah, that pretty much settles it.

If:

  • printenv TAVILY_API_KEY shows the real key
  • the grep found nothing in /root/... or /etc/...
  • and OpenClaw config only has the env ref

then the key is most likely not saved on disk anywhere obvious. It’s just present in the live environment right now, either from:

  • a one-off export TAVILY_API_KEY=...
  • the current root shell/session
  • or the systemd user manager environment

So the direct answer is still:

OpenClaw did not save the Tavily key.

#

It is reading it from an environment variable that already exists in memory.

One last optional check:

systemctl --user show-environment | sed -n '/^TAVILY_API_KEY=/s/=.*/=<set>/p'
  • if that prints <set>, systemd is holding it
  • if that prints nothing too, then it’s probably only in your current shell/session environment

Also, if it’s only in memory, it may disappear on logout/reboot.

If you want it somewhere explicit and easy to find later, the clean persistent place is:

  • /root/.openclaw/.env
timid cove
#

why did openclaw secrets set it up that way??

bronze reefBOT
#

Because openclaw secrets is really a SecretRef mapper, not a secret vault.

When it set:

{ source: "env", provider: "default", id: "TAVILY_API_KEY" }

you effectively told OpenClaw:

“Don’t store this secret yourself. Read it from my environment.”

So by design it:

  • writes the reference
  • checks the env var is resolvable during setup
  • does not copy the actual key into ~/.openclaw/.env or gateway.systemd.env
#

That’s intentional, because auto-writing the plaintext key back to disk would kind of defeat the point of moving to SecretRefs in the first place.

So the mental model is:

  • source: "env" → OpenClaw reads from env, you own where that env var comes from
  • OpenClaw config stores the pointer, not the secret

Honestly, I think the UX is a bit confusing here. The command could be much clearer that it is not storing the value, only the ref.

Docs: https://docs.openclaw.ai/gateway/secrets and https://docs.openclaw.ai/cli/secrets

If you want, I can help you pick the least-confusing way to manage Tavily going forward:

  1. keep env refs,
  2. move it explicitly into ~/.openclaw/.env,
  3. or use a dedicated secret provider.
timid cove
#

2

bronze reefBOT
#

Nice, I’d do that.

Since your gateway is running as root, use:

  • /root/.openclaw/.env

Put this in it:

TAVILY_API_KEY=your-real-tavily-key

Then:

  1. leave your openclaw.json ref exactly as-is
#
   { source: "env", provider: "default", id: "TAVILY_API_KEY" }
  1. restart the gateway
    openclaw gateway restart
    
  2. test Tavily again

A couple of useful notes:

  • you do not need to touch gateway.systemd.env
  • OpenClaw will load ~/.openclaw/.env itself on startup
  • after you confirm it still works, you can remove the old hidden/in-memory export later if you want one clear source of truth

So the clean end state is:

#
  • secret lives in /root/.openclaw/.env
  • config keeps only the env ref
  • no mystery shell-only value floating around anymore

Docs: https://docs.openclaw.ai/help/environment

If you want, I can also give you a quick sanity check after the restart so you can confirm it’s definitely reading from /root/.openclaw/.env.

timid cove
#

i have added it into /root/.openclaw/.env

bronze reefBOT
#

Nice, perfect.

Now do:

openclaw gateway restart

After that, /root/.openclaw/.env is your clean persistent source of truth.

One small gotcha: if the old in-memory TAVILY_API_KEY is still hanging around in your current session, it can mask whether .env is the thing being used right now.

So the clean sanity check is:

  1. restart the gateway
  2. open a fresh shell/session
  3. test Tavily again
#

If it still works after that, you’re good, it’s being picked up from /root/.openclaw/.env.

So from here the intended setup is:

  • secret stored in /root/.openclaw/.env
  • config keeps only the env ref
  • no more mystery value you can’t track down

Glad we untangled that 😌
If this fixed it, please right-click the solution message → Apps → ✅ Mark Solution so it gets indexed on Answer Overflow.

timid cove
#

how do i test tavily from a fresh shell/session?

bronze reefBOT
#

Easiest way:

  1. close the current terminal
  2. open a brand new terminal (or SSH in again)
  3. in that new shell, check whether the shell itself still has the var:
printenv TAVILY_API_KEY

What you want for a clean test:

  • if it prints nothing, great, your shell is clean
  • if it still prints the key, then something else is exporting it globally

Then from that fresh shell:

#
openclaw gateway restart

After the restart, test OpenClaw with something that clearly needs web search, for example in chat:

“Search the web for today’s top Tavily-related news”
or
“Search the web for the latest OpenClaw release notes”

How to interpret it

  • fresh shell printenv is empty, but web search still works after restart
    → OpenClaw is reading TAVILY_API_KEY from /root/.openclaw/.env

  • fresh shell printenv still shows the key
    → your shell/session is still exporting it from somewhere else too

#

Important nuance:

  • /root/.openclaw/.env is for OpenClaw
  • it does not automatically populate your shell environment

So for this test, it’s actually good if printenv TAVILY_API_KEY is empty in the new shell.

timid cove
#

printenv TAVILY_API_KEY is empty.
my agent has reported that tavily_extract is still working

bronze reefBOT
#

Perfect, that confirms it. 🎉

If:

  • printenv TAVILY_API_KEY is empty in a fresh shell
  • and tavily_extract still works

then OpenClaw is now reading the key from:

  • /root/.openclaw/.env

That’s the clean setup you wanted:

  • your shell env does not have the key
  • OpenClaw does have the key
  • the config only stores the env ref