> **Building with AI coding agents?** Install the authstack plugin with one command. This equips your agent with accurate Scalekit implementation patterns.
>
> **Recommended**:
> ```bash
> npx @scalekit-inc/cli setup
> ```
>
> Global:
> ```bash
> npm install -g @scalekit-inc/cli
> scalekit setup
> ```
>
> Supports Claude Code, Cursor, GitHub Copilot, Codex + skills for other Agent Skills-compatible agents.
> Skills: integrate-agentkit, implement-saaskit, add-mcp-oauth, implement-sso, implement-scim.
> [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# How AgentKit works

Connections, connected accounts, identifiers and tools: the AgentKit model, every connected-account status, and the user verification modes.
You configure a **connection** once per app. Each user approves access once, which activates their **connected account**. After that, your agent calls **tools** with the user's **identifier**, and Scalekit makes the API call with that user's token.

1. **You set up a connection** (once per app): in the dashboard.
2. **Your user approves access** (once per user): authorization link.
3. **Scalekit stores tokens**: connected account is ACTIVE once any user verification passes.
4. **Your agent calls a tool** (every tool call): identifier + tool name.

On every call: Scalekit adds the token, calls the API and returns JSON to your agent. The app (Gmail, Slack, GitHub…) sees an API call with the user's token.

Steps 1 and 2 happen once. Step 4 happens on every call. Your code never handles an OAuth token.

## Key terms

| Term | What it is | Who creates it | In code |
| --- | --- | --- | --- |
| Connector | A supported app, such as Gmail, and its library of tools. | Scalekit, or you for a [custom connector](/agentkit/bring-your-own-connector/overview/) | `gmail` |
| Connection | Your environment's settings for one connector: an OAuth client and scopes, or the fields for API-key sign-in. All your users share it. | You, once, in the dashboard | `connection_name` |
| Connected account | One user's link to a connection. It holds their tokens and a status. | Your code creates it. The user activates it by approving access. | `connected_account_id` |
| Identifier | Your app's ID for the user. Always pass it with the connection name. | You | `identifier` |
| Authorization link | A one-time URL where the user approves access. | Scalekit, when your code asks for one | `get_authorization_link` |
| User verification | The check that the person who approved access is the user you meant. | Your server, or Scalekit | `verify_connected_account_user` |
| Tool | One action on a connector, with an input schema. | Scalekit for built-in tools, or you for custom tools | `tool_name` |
| Virtual MCP server | A URL that exposes chosen tools for one user to any MCP client. | You, per agent | `actions.mcp` |
| Session token | A short-lived bearer token that lets an MCP client call a Virtual MCP server's tools as one user. [Mint one](/agentkit/mcp/session-tokens/) before each run. | Your server, per run | `actions.mcp.create_session_token` |
| API proxy | A call to the app's own API through Scalekit, which adds the user's credentials. Use it when no [built-in tool](/agentkit/tools/scalekit-optimized-tools/) fits. See [Call any API](/agentkit/tools/custom-tools/). | Your code | `actions.request` |

The **In code** column shows Python names. The Node.js SDK uses the camelCase form, such as `connectionName` and `connectedAccountId`. One exception: Node.js `executeTool` takes the connection name as `connector` and the tool's inputs as `toolInput`. The REST API also names the connection `connector`.

## Connected account statuses

| Status | Means | What to do |
| --- | --- | --- |
| `ACTIVE` | Tokens are valid. | Call tools. |
| `PENDING_AUTH` | The user hasn't finished approving access. | Send a new authorization link. |
| `PENDING_VERIFICATION` | The user approved, but user verification hasn't confirmed them. | Finish your verify step, or check the verification mode. |
| `EXPIRED` | Tokens expired or were revoked and couldn't be refreshed. | Send a new authorization link. |
| `DISCONNECTED` | The account was disconnected. | Reconnect with a new authorization link. |

In Python, `status` is a string such as `"ACTIVE"`. In Node.js, it is the numeric `ConnectorStatus` enum: import it from `@scalekit-sdk/node` (2.18.0 or later) and compare with `ConnectorStatus.ACTIVE`. The REST API returns the name as a string.

## Choose an identifier

Use your app's internal user ID. It must be stable (it never changes), unique per user and hard to guess. Don't use an email address: a user can change their email, and an old address can be reassigned to someone else, so the identifier would no longer point to the same person. An email is also easy to guess, which makes misuse easier.

Pass the identifier together with the connection name. When you pass `connected_account_id` instead, Scalekit ignores the identifier.

## User verification modes

Set the mode in **AgentKit** > **Settings** > **User Verification**. New environments start with **None**.

| Mode | What happens | Use it for |
| --- | --- | --- |
| Custom user verifier | Scalekit redirects the user to your verify URL. Your server confirms the user and calls the verify API. | Production (recommended) |
| Scalekit users only | The person approving access must be signed in to your Scalekit dashboard. | Internal testing |
| None | Anyone with the link activates the account. | Development only |

[Verify users](/agentkit/user-verification/) shows how to set up the custom user verifier.

## Next

  - [Set up a connection](/agentkit/connections/): Configure the app your agent needs.
  - [Authorize a user](/agentkit/tools/authorize/): Send the authorization link and wait until the account is ACTIVE.
  - [Verify users](/agentkit/user-verification/): Set up the custom user verifier before real users connect.


---

## More Scalekit documentation

| Resource | What it contains | When to use it |
|----------|-----------------|----------------|
| [/llms.txt](/llms.txt) | Structured index with routing hints per product area | Start here — find which documentation set covers your topic before loading full content |
| [/llms-full.txt](/llms-full.txt) | Complete documentation for all Scalekit products in one file | Use when you need exhaustive context across multiple products or when the topic spans several areas |
| [sitemap-0.xml](https://docs.scalekit.com/sitemap-0.xml) | Full URL list of every documentation page | Use to discover specific page URLs you can fetch for targeted, page-level answers |
