Skip to content

Agent-initiated intake

Here, kovra inverts the usual creation path: instead of you creating a secret and an agent consuming it, the agent asks for a secret it needs but doesn’t have, and you fulfil it. The agent names only the coordinate — never a value — so nothing sensitive ever passes through the model’s context (I11/I14).

  1. The agent requests. Over MCP it calls request_secret(coordinate, sensitivity, description). No value is supplied; the agent gets back a request id. (At the terminal, kovra intake request does the same.)
  2. kovra queues it. The request lands in the intake broker as metadata only — a coordinate, a requested sensitivity, and the requester’s note (shown fenced as untrusted text).
  3. It surfaces to you. The pending request shows up wherever you look: a badge on the macOS menu-bar app, the Dashboard, or kovra intake list.
  4. You fulfil it out-of-band. You type the value into a surface only a human can summon. kovra seals it under the coordinate and clears the request. prod is born high (the request can’t lower it), and fulfilling a high secret is an attended action gated by an bioProve (I16). What the request says about who asked comes from a file an agent can write, so that dialog shows it only as untrusted text. Fulfilling into a project vault over a critical global secret takes the same approval as overwriting it.
  5. The agent moves on. It learns the secret now exists — it never sees the value.

Why it’s safe — anti-phishing by construction

Section titled “Why it’s safe — anti-phishing by construction”

The agent can only ever create a request (which bumps the badge); it can never open the fulfilment surface or read the value back. Only a human summons the entry window — the agent has no shell to open it, and a prompt-injected agent can’t fabricate the request you see, because kovra builds it from the stored fields, not from the caller. The value goes straight from your keystrokes into the vault.

The kovra-menulet menu-bar app is the quickest path. It shows a badge with the count of pending requests, and its menu lists them — selecting one opens a native window to verify the coordinate and enter the value. The same menu has an “Open Dashboard…” item that brings up the full Dashboard.

The kovra menulet menu: pending secret requests, each with Fulfil, plus an Open Dashboard… item.

It does no vault work itself — it reads the broker and spawns kovra intake fulfill <id> --window, so the same code path (and the same Touch ID gate) runs whether you fulfil from the menu or the terminal.

A “Start at Login” item in the same menu keeps the menulet running across reboots, so the badge is always there to catch a request — toggle it on once and macOS relaunches it at every login. On macOS 13 and later it shows up as kovra under System Settings → General → Login Items → Open at Login, where you can also turn it off.

Sound for Approvals, also in that menu, turns off (or back on) the quiet sound kovra plays when it asks for your approval — see Attended confirmation.

You can also fulfil pending requests from the Dashboard or with kovra intake at the terminal (below).

The Dashboard lists pending requests in its overview. You fulfil one right there — type the value into the loopback page (only you can, over 127.0.0.1) and kovra seals it — or dismiss it. See Fulfil agent requests.

zsh
~ % kovra intake list
1782229003-92888-0 secret:dev/openai/api-key [Medium/dev] — Agent needs OpenAI key…
~ % kovra intake fulfill 1782229003-92888-0
Value: ••••••••••••
Sealed dev/openai/api-key (Medium).

fulfill takes the value from a hidden prompt, or --stdin / --clipboard / --window (the native entry window the menulet uses). kovra intake cancel <id> drops a request without fulfilling it. See the CLI reference.

If you’re wiring up an agent, request_secret is the tool to reach for when a value is missing — never ask the user to paste a secret into the chat. See kovra over MCP and the MCP tool reference.