Providers and accounts
A provider describes how to authenticate with a service. An account is one saved, reusable instance of it, and an app requirement is the slot it fills.
Provider
A provider is a service and its authentication, declared in app code. It has an ID, one or more named authentication methods and an optional name.
import { defineProvider, object, secrets, string } from "apps";
const vercel = defineProvider({
id: "vercel.com/api",
auth: {
api_key: secrets({
label: "API token",
fields: object({ token: string({ minLength: 1 }) }),
}),
},
});
api_key is the method name. secrets means fields you paste; oauth2 means a
browser sign-in.
The ID names one kind of credential at one vendor. By convention it is the
vendor’s domain, an optional product, and api or mcp, such as
vercel.com/api, vercel.com/mcp or google.com/gmail/api. An MCP server
uses <domain>/api only when every method’s credential works on both the API
and the MCP server. When the MCP server has its own OAuth that the API does not
accept, <domain>/api holds the shared methods and <domain>/mcp holds that
OAuth: a Linear API key works on both and is linear.app/api, while Linear’s
MCP OAuth is linear.app/mcp. A protocol no
vendor owns uses its bare name, such as imap; a private service uses your own
domain, such as acme.com/billing/api; a server that only runs on your machine
uses local/<name>. Any lowercase ID of letters, digits, ., - and /
deploys; the deploy warns when one does not follow the convention and names the
catalog’s ID for the vendor when it knows one. Two apps that declare the same ID share accounts, so
an account saved for one can be selected by the other. They must define each
method of the same name the same way, apart from OAuth scopes; a deploy that
redefines a method fails.
Omit name unless you want a specific one. An app’s own name appears only in
that app’s connect and requirement prompts. Elsewhere, and when the app gives
none, Executor uses the integrations.sh catalog’s name for the ID, then a name
another app gave it, then a name derived from the ID: vercel.com/api shows as
“Vercel” and vercel.com/mcp as “Vercel MCP”.
A provider ID is also not permission. Knowing it does not let an app read an account. Access is authorized separately.
Account
An account is one saved instance of one provider method: a label plus the field values. It is owned, and it is reusable.
Two accounts of the same provider are normal. “Work Vercel” and “Personal Vercel” hold different tokens, and an app selects one of them. Several apps can select the same account without copying the credential.
An account can also have a description: free text for agents, such as “reads only; use the sandbox account for writes”. Agents read it with the label when they choose between accounts. Set it when you create the account or edit it later; neither changes the credential.
Fields are an object that matches the method’s schema — { token }, or
{ email, key } — not one normalized secret string.
Requirements
An app declares a requirement for each provider it needs. The requirement is a named slot on the app.
const requirements = { accounts: { vercel } };
vercel is the slot name. A plain provider needs exactly one account.
provider.many() accepts zero or more, and the app receives a list.
Configuring an app means choosing which account fills each slot. Those account IDs are saved on the app, not copied into it. Replace the credentials on the account and every app that selected it follows.
An app cannot run a tool that needs a slot you have not filled.
Not a login
Signing in to Executor with Google or GitHub is not an account in this sense. A login proves who you are. An account is a credential an app uses. A login never creates an account, and a tool never receives your login token.
What is coming later
- Per-person account selection on a shared app.
- Providers backed by a signed-in browser session.
See Connect an account for the steps.