Credentials
Most useful tools need a secret. The awkward part is not storing it — it is that everything between you and the component is a place the secret should not end up: the agent’s context window, a committed config file, a process listing, a log.
ACT’s answer has two halves. Sessions decide when a credential crosses the boundary — once, at open, rather than on every call. The credential store decides where it lives until then — on the host, never in the component’s manifest and never in the agent’s view.
The operator’s side
Section titled “The operator’s side”Provision once; every later run finds it.
act login actpkg.dev/library/some-apiact login reads what the component declares it needs and prompts for each field. If the
component declares exactly one credential you can omit --key; if it declares several, name one.
An existing credential is reported and left alone unless you pass --force.
For anything non-interactive, act secret set is the same store without the prompting:
act secret set actpkg.dev/library/some-api --field acme:tokenact secret set actpkg.dev/library/some-api --field acme:token --fields-stdin < token.jsonact secret set actpkg.dev/library/some-api --field acme:token --from-command 'vault read -field=json secret/acme'act secret list # key, kind, description, expiry — never a valueact secret rm <component> --key <key>The component reference is the namespace: a credential stored for
actpkg.dev/library/some-api is not visible to any other component. The backing store defaults to
the platform’s credential location; --credentials-backend file:<path> points both act secret
and act run at the same alternative, so the writer and the reader cannot drift apart.
A credential is a set of named fields
Section titled “A credential is a set of named fields”There is no fixed schema. A credential is whatever fields you say it is:
act secret set <component> --field acme:username --field acme:password # a passwordact secret set <component> --field acme:token # an API tokenNo field name is well-known — whoever stores the credential names it, in their own namespace. The
std: namespace belongs to the spec and is refused here. A few std: names are reserved for
components to ask for, when a component wants to accept a conventional shape:
| Key | Use |
|---|---|
std:bearer-token | OAuth/OIDC bearer, or a generic bearer-style token |
std:api-key | API key — the component decides which header it becomes upstream |
std:username / std:password | Basic auth |
Anything component-specific takes a vendor prefix: pg:sslcert, anthropic:org-id. When a value
is not a plain string, state its type: --field acme:token=std:oauth2.
The component’s side
Section titled “The component’s side”A component declares what it expects, which is what makes act login able to prompt for it:
# The class carries no constraints, but an undeclared class is denied outright —# without this line the component cannot reach the store however it is run.[std.capabilities."act:credentials"]
[[std.credentials]]key = "default" # what a session uses when its args name no keydescription = "Acme API user"
[[std.credentials.fields]]key = "acme:token"label = "Acme API token"act-build pack refuses a manifest that declares [[std.credentials]] without the
act:credentials capability — the two always travel together.
At run time the component imports act:credentials/store and asks for what it needs, scoped to
its session:
list-secrets: async func(session: option<string>) -> result<list<secret-info>, secret-error>;get-secret: async func(session: string, want: secret-request) -> result<secret, secret-error>;Note the direction: this is a host import. The host implements the store; the component asks. A component never sees a filesystem path, a keyring, or another component’s secrets — only the answer to its own request.
Why not the obvious alternatives
Section titled “Why not the obvious alternatives”Not per-call metadata. A credential repeated on every invocation is a credential in the agent’s context on every invocation. The spec discourages it; use session args.
Not env in .mcp.json. That file is committed — that is the whole point of it — so a secret
in it is a secret in the repository. See
wiring a component into your agent.
Not the config file. ~/.config/act/config.toml is for grants and paths. Credentials rotate
and should not live where policy lives.
Related
Section titled “Related”- Sessions — the boundary a credential crosses
act secret/act login— full CLI surface- ACT-AUTH — the normative design, including OAuth discovery and token refresh