Declare credentials on an action
UsedefineCredential() to describe the credential an action needs, then list it in the action’s credentials array.
src/actions/search.ts
exa) is the app/credential slug Keystroke looks up in the vault. The schema validates the resolved secret before your action runs.
Credentials belong on actions, not on
defineAgent() or defineWorkflow(). Agents and workflows get credentials by running actions that declare them.Credential kinds
There are three runtime credential kinds:| Kind | Authoring shape | Use it for |
|---|---|---|
api_key | defineCredential({ key, fields }) or credential.static() | Static API keys and secret fields |
oauth_managed | defineCredential({ key, kind: "oauth" }) or credential.oauth() | Native OAuth connections, such as Slack gateway credentials |
keystroke | defineCredential({ key, kind: "keystroke" }) or generated app credentials | Hosted catalog apps routed through Keystroke’s platform MCP layer |
Use actions in workflows and agents
Once an action declares credentials, use it like any other action.Resolution order
When an action runs, Keystroke resolves each credential requirement using the run context. Resolution order:- Explicit selection: if the platform supplied a credential instance id for this run, that exact instance wins.
- Pinned scope: if the action or credential is scoped with
.scope(...), only that scope is tried. - Project default: for unpinned credentials, try the default project credential.
- Organization default: if no project credential resolves, try the default organization credential.
- Error: if nothing resolves, the run fails with a missing-credentials error.
Pin a scope
Use.scope() when the action must use a specific credential scope.
| Scope | When to pin |
|---|---|
organization | A shared org credential should always be used |
project | The workflow should use a project-specific secret |
user | The action should run as the user who connected the app |
Defaults and multiple credentials
Within a scope, Keystroke can resolve a credential automatically when:- There is exactly one credential instance for that app and scope.
- Or there are multiple instances, but exactly one is marked as default.
Troubleshooting
When a credential can’t be resolved, the action fails beforerun executes, with a message that points at the fix:
| Message | Cause | Fix |
|---|---|---|
”This agent needs the <key> credential…” | Nothing resolved for that key at any tried scope | Connect the credential (keystroke connect <key> or the Apps page), or check the action’s pinned scope |
”Multiple <key> credentials are available. Pick one…” | More than one instance and no default | Mark one default, or pass an explicit selection |
.scope("user") credential only resolves when the run carries a user actor, such as an agent prompt tied to a signed-in user. Background runs with no user (most cron and webhook triggers) cannot resolve user-scoped credentials. The Slack gateway runs as the workspace’s connected account, not the individual who sent the message, so scope its actions to organization or project rather than user.
Cloud and local behavior
Cloud execution and local runs use the same resolution rules, but different stores.| Target | Where credentials come from |
|---|---|
| Cloud | The hosted platform credential store, materialized to workers on demand |
Local (keystroke dev, --local) | The local server credential store |
.env. If a deployed workflow uses an action with credentials, connect those credentials in the cloud first.
Next steps
Connect and manage apps
Create credential instances and choose their scopes.
Actions
Learn how actions define typed inputs, outputs, and credentials.
Workflow steps
Run credentialed actions as durable workflow steps.
Agent tools
Attach credentialed actions as tools an agent can call.