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

An **account** is one saved set of credentials for one **provider**. You connect
it once. Your profile for 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 dashboard

Every account is connected for an app. Choose **Connect new account** at the end of a provider's list on the app's
**Accounts** tab, then choose **Connect** to start browser sign-in. If the provider
needs credentials, enter them in the same dialog. 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. Open **Advanced** below Connect to review **Required permissions**.
The dialog 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, open **Advanced** below the Connect button,
choose **Change** next to OAuth client, 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.

You name an account after it connects. Executor names each new account
`Default`, then `Default 2`, and so on when that name is already in use for the
provider. Once the account is saved, or browser sign-in returns, a **Name this
account** dialog offers to rename it to something such as “Work” or “Personal.”
Closing it keeps the default. Reconnecting keeps the existing name. You can also
rename an account later from its menu on the app's **Accounts** tab, or with **Edit
details** on the **Accounts** page.

Completing a connection saves the account and selects it in your profile 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.

The Accounts tab lists every compatible saved account under each provider. Choose
one for a single-account requirement, or check the accounts to use for a
multiple-account requirement. Each change is saved immediately. **Connect new
account** at the end of the list adds an account and selects it. Members who can
view an app but not use it see only the profile's current accounts.

Removing an account from a single-account requirement, or unchecking it, changes only
the profile's selection. It keeps the saved account available to other apps. The global
**Accounts** page lists saved accounts and the apps that use them; it does not connect
accounts or change their credentials.

## 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.profiles["<management-profile-id>"].accounts.connect({
  path: { organization: "<organization-id>", app: "<app-id>" },
  body: { profile: "<profile-id>", requirement: "vercel" },
});
```

```js Local
return await tools.executor.profiles["<management-profile-id>"].accountConnect.issue({
  body: { owner: "alice", target: { app: "<app-id>", profile: "<profile-id>", requirement: "vercel" } },
});
```

</CodeGroup>

Create a profile first, or use the ID of your existing profile. Hosted uses
`profiles.create`; local uses `appProfiles.create`. Read their discovered schemas
for the required fields.

Every request names the profile requirement it fills. To replace the credentials of an
account the app already uses, add its ID as `account` in the same body. The account keeps its ID, name and every app's selection.

Add `note` to tell the person connecting why the account is needed or which one
to pick, such as "Connect the **billing** workspace." The form shows it first.
It is Markdown of at most 1,000 characters with only `https:` links, and no HTML
or images. When the saved account has no description, the note becomes it.

The app's requirements carry its setup help, so the agent can explain in chat
where to get the credentials before it sends the link.

Check whether you finished:

```js
const connection = await tools.executor.profiles["<management-profile-id>"].accountConnections.get({
  path: { connection: "<connection-id>" },
});
return connection.state;
```

`Completed` means the account is saved and 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. Replace credentials
from an app that uses the account: open its menu on the app's **Accounts** tab and choose
**Reconnect** or **Update credentials**. A **Needs sign-in** account also has a
**Reconnect** button there. Replacing credentials keeps the same account, so every profile
that selected it keeps working.

What removing an account does to the profiles that selected it depends on where
Executor runs:

- **Cloud and self-host** remove the account from every profile's selections.
  A `.many()` requirement that still holds other accounts keeps working with
  them. A single-account requirement, or a `.many()` requirement that held only
  this account, is left empty, and the profile's tool calls fail until someone
  selects another account.
- **Local** keeps the reference. A profile that selected the account fails
  every tool call, even when a `.many()` requirement still holds other
  accounts, until you remove or replace the account in its selection. This makes
  a broken app visible instead of quietly changing which credentials an agent
  uses.
