Skip to main content
Credentials let Keystroke actions safely call external services like Linear, Gmail, HubSpot, Slack, and more. An app is the service you connect. A credential is one connected account or secret for that app. Actions declare the credentials they need, and Keystroke resolves the right organization, project, or user credential when the action runs.

Example requests

Ask your coding agent which service you want to use. It can wire up the app, credential, and actions that need it.
“Connect our HubSpot account so our SDR agent can read and update deals.”
“Set up Slack so the team can message the data analyst agent and schedule regular reports.”
“Read the Pylon documentation, create a custom API integration, and add actions that match the endpoints our support agent needs.”

Apps vs credentials

An app is a service Keystroke can connect to: Granola, Google Workspace, Slack, Salesforce, Snowflake, and the rest of the integration catalog. A credential is one connected account for that app: an API key, OAuth connection, or managed connection instance. A single app can have several credentials, for example one organization-wide Hubspot connection and a project-level Hubspot connection with additional Hubspot permissions.
TermWhat it means
AppA connectable external service shown in the Apps page and integration catalog
CredentialOne connected account or secret for an app
Credential instanceThe stored credential record at an organization, project, or user scope
Gateway appA messaging surface, like Slack, for messaging agents directly in third-party tools
MCP serverA third-party’s MCP server that you attach to an agent with defineMcp()
“Integration” is synonymous with “app”. An app is the user-facing thing you connect, and credential is the runtime binding your code consumes.

Connect apps and credentials

Keystroke supports several connection paths, depending on what you’re building.
Connection typeUse it forHow it works
Built-in OAuth appsApps like Google Workspace, GitHub, Gong, Snowflake, and other catalog integrationsKeystroke creates a managed app credential. In the hosted cloud, most of these run through Keystroke’s platform MCP layer.
Built-in API key appsApps that need a static secret, such as ExaStore an API key credential with the CLI or web app.
Gateway appsExternal channels where people talk to agents, such as SlackConnect the app, then bind a channel to an agent. See external channels.
Custom credentialsYour own API keys or internal servicesDefine a credential and declare it on actions.
Custom MCP serversConnect to any third-party MCP server and enable agents to use its available toolsAttach a defineMcp() tool to an agent, optionally backed by a credential.
You can browse our 1,000+ built-in integrations in the app catalog, or jump to custom apps and MCP to learn more about connecting custom apps and MCP servers.

Credential scopes

Every credential instance is available at one of three scopes:
ScopeUse it when
OrganizationThe whole organization should share one connection or API key
ProjectA specific project(s) gets its own connection or secret
UserThe action should run as the user who connected the app
When building agents and workflows, Keystroke will automatically resolve credentials for each action (agent tools or workflow steps) in this order:
  1. An explicit selection, if one was provided.
  2. A pinned scope from .scope("organization"), .scope("project"), or .scope("user").
  3. The project default.
  4. The organization default.
  5. Throw a missing-credentials error.
User credentials are not part of the unpinned fallback chain. If an action should run as the user, you must specifically pin it with .scope("user"). See using credentials in code.

Cloud and local credentials

Credentials live in the platform: they’re scoped to your organization, project, or user, and materialized on demand when a deployed project runs. Deploying does not upload .env or local secrets, so connect credentials against your cloud project with the web app or CLI.
# Cloud organization credential
keystroke credentials set exa --set apiKey=@env:EXA_API_KEY --scope org
If you run a local server with keystroke dev / keystroke start, it uses a separate local credential store; CLI commands with --local write there.
# Local dev credential
keystroke --local credentials set exa --set apiKey=@env:EXA_API_KEY
See connect and manage apps for the full CLI and web workflow.

How code consumes credentials

Credentials are declared on actions, not on agents or workflows directly. An action lists the credentials it needs:
import { defineAction } from "@keystrokehq/keystroke/action";
import { defineCredential } from "@keystrokehq/keystroke/credentials";
import { z } from "zod";

const exa = defineCredential({
  key: "exa",
  fields: { apiKey: z.string() },
});

export const search = defineAction({
  slug: "search",
  input: z.object({ query: z.string() }),
  output: z.object({ results: z.array(z.string()) }),
  credentials: [exa] as const,
  async run(input, credentials) {
    return callSearchApi(input.query, credentials.exa.apiKey);
  },
});
Agents and workflows consume credentials indirectly when they call that action as a tool or step.

Platform API keys

App credentials are different from Keystroke platform API keys. Platform API keys authenticate your own systems to Keystroke’s platform API and are managed under Settings → API keys or with keystroke api-key. App credentials authenticate Keystroke runs to third-party apps.

Next steps

Connect and manage apps

Use the web app and CLI to connect, scope, rotate, and revoke credentials.

Built-in integrations

Use catalog apps and their generated actions.

Using credentials in code

Declare credentials on actions and control resolution with scopes.

Custom apps and MCP

Add your own credentials, app wrappers, and MCP servers.