Secrets

Secret requests let the agent ask for credentials without putting plaintext secrets in chat or model context.

Config

createHeypi({
  state: { root: "./state" },
  // ...adapters, agent, runtime
  secrets: true,
});

Options

Option Required Default Description
enabled No false Enables the secret_request managed tool.
url No https://heypi.dev/secret Public page URL sent to users.
serve No false Serves the static secret page from this heypi app.
expiresInMs No 600_000 Pending request lifetime.
maxFields No 8 Maximum fields per request.

When enabled, heypi exposes secret_request. The agent passes a reason and one or more fields:

{
  reason: "Need a GitHub token to inspect private workflow logs.",
  fields: [
    { name: "GITHUB_TOKEN", label: "GitHub token" },
    { name: "GITHUB_OWNER" },
  ],
}

heypi returns a browser link. The user opens it, enters the values, encrypts them locally, and pastes the heypi-secret:... blob back into the same chat scope. heypi decrypts locally and writes the values into the active runtime workspace:

.secrets/GITHUB_TOKEN
.secrets/GITHUB_OWNER

The encrypted blob is intercepted before the normal model turn, so it is not stored as chat history and is not sent to the model.

Pending requests are process-local. If the heypi process restarts before the user replies, the link is invalid and the agent must request a fresh secret link.

Saved values are runtime files, not database rows, memory entries, or workspace records. Their durability follows the configured runtime workspace and deployment backup strategy.

Self-hosting

The default page URL is:

https://heypi.dev/secret

That page is static client-side code. It receives the public key and request metadata in the URL fragment, encrypts locally with WebCrypto, and does not need server-side access to your heypi instance. It uses generated Basecoat CSS and no JavaScript UI widgets.

To self-host the page from your own heypi app:

createHeypi({
  state: { root: "./state" },
  // ...adapters, agent, runtime
  http: { host: "0.0.0.0", port: 3000 },
  secrets: {
    url: "https://203-0-113-10.sslip.io/secret",
    serve: true,
  },
});

secrets.url is the public URL placed in chat. With serve: true, heypi serves the static page at that URL's path. It also serves the stylesheet at <path>.css. Use HTTPS for real secrets.

Self-hosted secret pages need a stable URL. Avoid http.port: 0 for self-hosted secrets unless another layer provides a stable public URL and forwards to the selected local port. For local development, either use a fixed local port that matches secrets.url, or omit serve and use the hosted page.

Security model

  • The private key stays in the heypi process memory and expires with the request.
  • Secret values are stored as scoped runtime files, not memory.
  • Anyone who can read the scoped runtime workspace can read saved secrets.
  • Pending secret requests are lost on process restart.
  • Field name is the stable file/env-style key; label is optional display text.

Use narrow runtime scope and runtime isolation for sensitive credentials.