---
title: Connect an account
description: "Save a credential once as an account, from the dashboard, the app you are configuring, or an agent, then select it for any app that needs that provider."
---

An **account** is one saved set of credentials for one **provider**. You connect
it once. Every app that needs that provider can select it, and none of them
holds a second copy.

There are two kinds of credential, and the provider decides which it accepts:

- **Secrets**: fields you paste, such as an API token, or an email and a key.
- **OAuth**: browser sign-in or a client ID and secret for machine-to-machine access.
  Executor stores and renews the resulting tokens.

## From the hosted dashboard

Choose **Connect** on the app's Overview card or **Accounts** tab for a provider
without an account. Set **Account name** in the compact dialog, then choose **Connect** to
start browser sign-in. If the provider needs credentials, enter them in the same
dialog. Use **Change account** for a connected
provider; its picker also offers **Connect another account**. The connection dialog
contains the sign-in methods supported by the provider.

The dialog uses the provider fields already loaded with the app. Opening it does
not create a connection or fetch the fields again. A connection is created when
you submit; retries in that dialog reuse the same request.

OAuth setup is checked in the background and reused across forms. If Executor can
use a saved client or register one automatically, the dialog can connect without
asking for client details.
If your own client is required, its fields appear immediately. A failed check offers
**Retry** without guessing which setup to show. Client IDs and secrets stay on the
server during these checks.

The provider's code declares the grant, endpoints, scopes, and authentication
method. The dialog shows the required permissions and asks only for a client ID
and, when required, a client secret. For browser sign-in, copy the fixed redirect
URL into the OAuth app's settings. Machine-to-machine connections complete in the
dialog and need no browser redirect.

If saved OAuth client details are wrong, choose **Change OAuth client** in the
connection form and enter the replacement. Executor saves manual client details
only after a successful sign-in. A failed replacement keeps the previous client
and account. If browser sign-in rejects the client, **Update client details**
opens the form again with the account name retained.

The account name is optional during setup. New accounts use `Default`, then
`Default 2`, and so on when that name is already in use for the provider. Use
**Account name** in the form to choose a name such as “Work” or “Personal.” You can also rename
an account later from its detail page.

Completing a connection saves the account and selects it for this app. There is
no separate selection to save. Browser sign-in returns to the app's Accounts tab;
cancelling or failing sign-in offers a direct way back to the app.

To reuse an account, choose **Use saved account** or **Change account**. The picker
also offers **Connect another account**. For a
single-account requirement, clicking a saved account applies it immediately. For
multiple accounts, check the accounts you want and choose **Use selected accounts**.
An empty selection can be saved with **Use without accounts** when the app allows
multiple accounts.

**Stop using this account** removes the app's selection. It keeps the saved account
available to other apps. The global **Accounts** page lists saved accounts and the
apps that use them.

## From an agent

An agent can start the same flow. It must never ask you for a secret in chat,
and must never read a token out of your files. It asks Executor for a connection
link and gives you the link; you finish in your browser.

<CodeGroup>

```js Hosted
return await tools.executor.mutations.accounts_connect({
  path: { organization: "<organization-id>", app: "<app-id>" },
  body: { requirement: "vercel" },
});
```

```js Local
return await tools.executor.mutations.accountConnect_issue({
  body: { owner: "alice", target: { app: "<app-id>", requirement: "vercel" } },
});
```

</CodeGroup>

Supply either `target`, to fill a specific requirement, or `provider`, to save
an account without selecting it anywhere. Not both.

Check whether you finished:

```js
const connection = await tools.executor.queries.accountConnections_get({
  path: { connection: "<connection-id>" },
});
return connection.state;
```

`Completed` means the account is saved. If the request named a target, the
account is also selected for that requirement.

A pending request expires after thirty minutes. Issue a new one if it does.

## How a targeted request fills a slot

- A single-account requirement is **replaced** by the new account.
- A `.many()` requirement **appends** the new account, and does not duplicate
  one that is already selected.
- If the app's requirement changed while the request was open, the request fails
  rather than filling the wrong slot.

## Changing and removing an account

You can rename an account, replace its credentials, and remove it. Replacing
credentials keeps the same account, so every app that selected it keeps working.

Removing an account does not silently unselect it. Apps that selected it keep
the reference and report it as unavailable, and they cannot run until you choose
a different account. That is deliberate: it makes a broken app visible instead
of quietly changing which credentials an agent uses.

## What is coming later

- Per-person account selection. Today one app holds one selection for the whole
  organization, so a tool call uses the saved account rather than the caller's
  own.
