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

---

# Migrate from Arcade

Move an agent from Arcade to AgentKit: map Arcade users, auth providers and tools to AgentKit, move your users, and update your tool calls.
Use this page if your agent uses Arcade today. It covers what's specific to Arcade: how its concepts map to AgentKit, how to move your users, and how your tool calls change. The steps every migration shares, such as setting up Scalekit and creating connections, are in [Migrate to AgentKit](/agentkit/advanced/migrate-to-agentkit/).

## How Arcade maps to AgentKit

| Arcade | AgentKit |
|---|---|
| `user_id` | [Identifier](/agentkit/concepts/): your app's ID for the user, passed on each call |
| Auth provider | [Connection](/agentkit/connections/): one per app, with its auth type, scopes and OAuth app |
| A user's authorization for a provider | [Connected account](/agentkit/connected-accounts/): one per user and connection |
| MCP server (toolkit) | [Connector](/agentkit/connectors/), such as Gmail or GitHub |
| Tool, such as `Gmail.ListEmails` | Tool, such as `gmail_fetch_mails` |
| `client.tools.authorize()` / `client.auth.start()` | [Authorization link](/agentkit/tools/authorize/) |
| `auth_response.context.token` for direct API calls | [`actions.request()`](/agentkit/tools/custom-tools/) through the Scalekit proxy |
| MCP gateway | [Virtual MCP server](/agentkit/mcp/overview/) with a session token per agent run |

## Move your users

Arcade gives your app a user's current access token, but not the refresh token or its expiry; it refreshes tokens itself. An imported access token without a refresh token stops working when it expires, so plan for each user to authorize again: send them an authorization link for each app they use, as in [Option A](/agentkit/advanced/migrate-to-agentkit/#option-a-users-authorize-again).

1. Create a connection in Scalekit for each Arcade auth provider your agent uses. If you configured your own OAuth app in Arcade, you can use the same app in Scalekit, so users see the same consent screen. See [Bring your own OAuth app](/agentkit/advanced/bring-your-own-oauth/).
2. For each user, get an authorization link for each app they authorized in Arcade, and send it to them. Use the same user ID you passed to Arcade as the `identifier`, unless it's an email address: AgentKit identifiers should be your app's opaque user ID.

  **Python**

  ```python
  # Your user IDs and the Scalekit connections each one needs
  users = {"user_123": ["gmail", "github"]}

  for identifier, connection_names in users.items():
      for connection_name in connection_names:
          link = actions.get_authorization_link(
              connection_name=connection_name, identifier=identifier
          ).link
          print(identifier, connection_name, link)  # send this to the user
  ```

  **Node.js**

  ```typescript
  // Your user IDs and the Scalekit connections each one needs
  const users: Record<string, string[]> = { user_123: ['gmail', 'github'] };

  for (const [identifier, connectionNames] of Object.entries(users)) {
    for (const connectionName of connectionNames) {
      const { link } = await actions.getAuthorizationLink({ connectionName, identifier });
      console.log(identifier, connectionName, link); // send this to the user
    }
  }
  ```

These blocks reuse the client from [Set up Scalekit](/agentkit/advanced/migrate-to-agentkit/#1-set-up-scalekit). To find which apps each user authorized, list their connections in Arcade with `client.admin.user_connections.list()`.

## Move your agent code

### Execute tools

  **Python**

  **Before (Arcade):**
  ```python
  response = client.tools.execute(
      tool_name="Gmail.ListEmails",
      user_id="user_123",
  )
  print(response.output.value)
  ```

  **After (Scalekit):**
  ```python
  result = actions.execute_tool(
      tool_name="gmail_fetch_mails",
      identifier="user_123",
      connection_name="gmail",
      tool_input={"max_results": 5},
  )
  print(result.data)
  ```

  **Node.js**

  **Before (Arcade):**
  ```typescript
  const response = await client.tools.execute({
    tool_name: 'Gmail.ListEmails',
    user_id: 'user_123',
  });
  console.log(response.output.value);
  ```

  **After (Scalekit):**
  ```typescript
  const result = await actions.executeTool({
    toolName: 'gmail_fetch_mails',
    identifier: 'user_123',
    connector: 'gmail',
    toolInput: { max_results: 5 },
  });
  console.log(result.data);
  ```

You don't authorize per tool. Once a user's connected account is `ACTIVE`, every tool of that connection works for them. Pass `identifier` and the connection name on every call: `connection_name` in Python, `connector` in Node.js.

Arcade tool names are `Toolkit.ToolName`; AgentKit tool names are lower case, such as `gmail_fetch_mails`, and the inputs can differ. Find each tool's exact name and input in the [connector catalog](/agentkit/connectors/).

### Tool definitions for your LLM

Where you fetched tool definitions with `client.tools.formatted.list(...)`, list the user's tools with `list_scoped_tools`. Each tool comes with its input schema:

  **Python**

  ```python
  tools_response, _ = scalekit_client.actions.tools.list_scoped_tools(
      identifier="user_123",
      # Required: list every connection whose tools the agent should see
      filter={"connection_names": ["gmail"]},
      page_size=100,  # up to 100 tools per page; pass next_page_token back as page_token for more
  )
  ```

  **Node.js**

  ```typescript
  const { tools } = await scalekit.tools.listScopedTools('user_123', {
    // Required: list every connection whose tools the agent should see
    filter: { connectionNames: ['gmail'] },
    pageSize: 100, // up to 100 tools per page; pass nextPageToken back as pageToken for more
  });
  ```

To hand them to a framework such as LangChain or the OpenAI Agents SDK, see [Choose a framework](/agentkit/examples/).

### Direct API calls

Where you called an API yourself with `auth_response.context.token`, call it through the Scalekit proxy with `actions.request()`. It adds the user's credentials, so your code never handles the token:

  **Python**

  ```python
  response = actions.request(
      connection_name="gmail",
      identifier="user_123",
      method="GET",
      path="/gmail/v1/users/me/messages",
  )
  ```

  **Node.js**

  ```typescript
  const response = await actions.request({
    connectionName: 'gmail',
    identifier: 'user_123',
    method: 'GET',
    path: '/gmail/v1/users/me/messages',
  });
  ```

### MCP

If your agent connected to an Arcade MCP gateway, create a [Virtual MCP server](/agentkit/mcp/overview/) with the same connections and tools. It has one static URL for all users; mint a session token for the user before each agent run and pass it as a bearer token.

### Your own tools

Tools you built and deployed to Arcade move into your app as [custom tools](/agentkit/tools/custom-tools/) that call the app's API through the Scalekit proxy. For an app that isn't in the catalog, [add your own connector](/agentkit/bring-your-own-connector/overview/).

## Next

  - [Migrate to AgentKit](/agentkit/advanced/migrate-to-agentkit/): The steps every migration shares.
  - [Authorize a user](/agentkit/tools/authorize/): The full authorization link flow.

## API reference

The endpoints this page's code calls, with every field and the SDK method for each:

- `POST` [Get an authorization link](https://docs.scalekit.com/agentkit/reference/authorization/get-an-authorization-link.md)
- `POST` [Execute a tool](https://docs.scalekit.com/agentkit/reference/tools/execute-a-tool.md)
- `GET` [List a user's scoped tools](https://docs.scalekit.com/agentkit/reference/tools/list-scoped-tools.md)


---

## 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 |
