mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 05:16:23 -06:00
6287056d26
The tool page shipped with the feature but nothing pointed at it: the tools index still listed only ask_user under human input, and neither the secrets CLI page nor ask-user mentioned it. Add those three references. The page also missed the trap the card invites: the allowed-hosts field is editable, and clearing it stores a secret that can never be substituted at egress, so the request looks successful and the credential is unusable. Warn where the operator edits it, say what a skipped or expired prompt means for the agent, and drop wording left over from when requests could ask for an env value.
89 lines
4.2 KiB
Markdown
89 lines
4.2 KiB
Markdown
---
|
|
summary: "How the secrets tool lets the agent request credentials it never sees"
|
|
read_when:
|
|
- You want the agent to obtain an API key without it entering the chat
|
|
- You are answering or debugging a credential request prompt
|
|
- You need the secrets tool schema, storage, or channel behavior
|
|
title: "Secrets"
|
|
---
|
|
|
|
`secrets` lets the agent ask you for a credential without ever seeing it. The
|
|
agent names an entry, you type the value into a trusted prompt, and the Gateway
|
|
writes it straight into the shared secret store. The value never appears in the
|
|
chat, the session transcript, the tool result, or the model's context — the
|
|
agent only learns that the entry now exists.
|
|
|
|
The tool is available only in the main session. Subagents and other
|
|
non-primary runs do not receive it.
|
|
|
|
It is enabled by default and governed by the normal tool policy — there is no
|
|
dedicated config key. To remove it, deny it like any other tool (for example
|
|
`tools.deny: ["secrets"]` in `openclaw.json`); allowlists and tool profiles
|
|
apply to it the same way.
|
|
|
|
## Actions
|
|
|
|
- `request` — ask the human for a credential and store it under a name such as
|
|
`STRIPE_API_KEY`. Requests are protected-secret only: an `env` value is
|
|
readable through `list`, so requesting one would break the promise the masked
|
|
prompt makes. The agent may propose `allowedHosts` and a short `reason` shown
|
|
on the prompt, and the tool blocks until you answer, skip, or it times out
|
|
(15 minutes by default). The request is bound to the requesting agent run; if
|
|
that run ends before you answer, the write is refused.
|
|
- `list` — entry metadata: name, kind, allowed hosts, and last update. Secret
|
|
values are structurally absent from the listing. Operator-set `env` entries
|
|
show their value, since those are injected into exec environments anyway and
|
|
are agent-readable by design.
|
|
- `delete` — soft-delete an entry by name. Deleted entries are purged after 30
|
|
days.
|
|
|
|
There is deliberately no action that writes a value the agent supplies. If a
|
|
value must enter the store, it arrives through the human prompt, the
|
|
`/settings/secrets` page, or the [`openclaw secrets store` CLI](/cli/secrets).
|
|
|
|
## Answering a request
|
|
|
|
The web Control UI docks the prompt above the composer with a masked input.
|
|
The prompt always shows who is asking (agent and session), the entry name, the
|
|
agent's stated reason, and an editable list of allowed hosts, so you have the
|
|
final say on where the credential may be used. If the name already exists, the
|
|
prompt says so and shows when and by whom the entry was last updated;
|
|
submitting replaces the stored value.
|
|
|
|
<Warning>
|
|
Leave at least one allowed host in place. A secret with no allowed hosts is
|
|
stored but can never be substituted at egress, so the request appears to
|
|
succeed and the credential is unusable. Narrow the list rather than clearing
|
|
it.
|
|
</Warning>
|
|
|
|
Skipping the prompt, or letting it expire, tells the agent that no credential
|
|
arrived; it continues with best judgment rather than failing the turn.
|
|
|
|
iOS, macOS, and Android render the same card with a masked secret field.
|
|
|
|
Chat channels never accept the value. On Telegram, Discord, and similar
|
|
surfaces the request is delivered as a link to the Control UI prompt — typing
|
|
a credential into a chat message is exactly what this flow exists to avoid, so
|
|
a plain-text reply is not captured as an answer.
|
|
|
|
Creating a credential request requires an `operator.admin` client (the agent's
|
|
own Gateway client qualifies) and is bound to the requesting agent run.
|
|
Answering needs only the normal question scope, because answering provides a
|
|
value rather than reading one.
|
|
|
|
## Using a stored credential
|
|
|
|
A stored entry is a regular shared-store entry (see
|
|
[Secrets management](/gateway/secrets)):
|
|
|
|
- Reference it from config as `{ "source": "store", "id": "STRIPE_API_KEY" }`
|
|
wherever a SecretRef is accepted (provider API keys, channel tokens). Writes
|
|
refresh affected config references automatically.
|
|
- `env` entries are injected into gateway-host exec environments starting with
|
|
the next agent run.
|
|
- `secret` entries are substituted into subprocess traffic only when the
|
|
egress proxy is enabled (`secrets.egressProxy.enabled`) and the destination
|
|
matches the entry's allowed hosts; the agent and its subprocesses otherwise
|
|
see only an opaque placeholder.
|