Skip to content
Scalekit Docs
Talk to an Engineer Dashboard

Migrate to AgentKit

Move to AgentKit from your in-house solution, Composio, Nango, Pipedream Connect or another agent integration platform.

Use this guide to move an agent from another integration platform, such as your current in-house solution, Composio, Nango, Pipedream Connect or Arcade, to AgentKit. You set up Scalekit, create a connection for each app, move your users’ access, and then move your agent’s tool calls.

There are two ways to move your users. Choose per connection:

Users authorize againImport existing credentials
What users doConnect each app once more, through an authorization linkNothing
What you needNothing from the old platformEach user’s credential, exported from the old platform
OAuth appsAny connectionYour own OAuth app, with the same client ID that issued the tokens
Best forTokens you can’t exportCredentials you can export

A refresh token works only with the OAuth app that issued it. If the old platform signed users in with its own OAuth app, those users authorize again.

Coming from one of these platforms? Its guide maps the platform’s concepts to AgentKit, says which credentials you can export, and shows your agent code before and after:

  1. Create a Scalekit account

    Sign up at app.scalekit.com and copy your API credentials from Developers > Settings > API Credentials.

  2. Set environment variables

    Add them to a .env file that you don’t commit:

    .env
    SCALEKIT_CLIENT_ID=your_client_id
    SCALEKIT_CLIENT_SECRET=your_client_secret
    SCALEKIT_ENVIRONMENT_URL=https://your-env.scalekit.com
  3. Install the SDK and create the client

    There’s no session object: you pass the user’s identifier on each call. Later blocks reuse this setup.

    Terminal window
    pip install scalekit-sdk-python python-dotenv
    import os
    from datetime import datetime
    from dotenv import load_dotenv
    from scalekit import ScalekitClient
    load_dotenv()
    scalekit_client = ScalekitClient(
    os.environ["SCALEKIT_ENVIRONMENT_URL"],
    os.environ["SCALEKIT_CLIENT_ID"],
    os.environ["SCALEKIT_CLIENT_SECRET"],
    )
    actions = scalekit_client.actions

For each app your agent uses, create a connection in AgentKit > Connections > Add connection. See Configure a connection. The examples on this page use connections named gmail, openai, twilio and exa.

Old platform’s authConnection in Scalekit
OAuth with the platform’s own OAuth appOAuth. Use Scalekit credentials to start, or bring your own OAuth app. Users authorize again
OAuth with your own OAuth appOAuth with the same OAuth app (client ID and secret). You can import the tokens
API key, bearer token or basic authThe same type. You can import the credential

Send each user an authorization link. It creates the user’s connected account if there isn’t one. Once they approve, the account is ACTIVE and your agent can call tools.

link = actions.get_authorization_link(connection_name="gmail", identifier="user_123").link
print(link) # send this to the user

user_123 is your app’s ID for the user. See Authorize a user for the full flow.

Create each user’s connected account with the credential they already have. Scalekit imports it when your server calls the API with your environment’s client credentials, and the account is ACTIVE straight away.

Send the credential in authorization_details:

  • OAuth tokens go in oauth_token.
  • API keys, bearer tokens and basic auth go in static_auth. In Python, the fields go directly under static_auth; in Node.js and the REST API, they go one level down, in details.
FieldRequiredDescription
access_tokenYesThe user’s current access token.
refresh_tokenNo, recommendedLets Scalekit get a new access token when the current one expires.
expires_atNo, recommendedWhen the access token expires, in UTC. Needs Python SDK 2.25.0 or Node.js SDK 2.22.0 or later.
response = actions.create_connected_account(
connection_name="gmail",
identifier="user_123",
authorization_details={
"oauth_token": {
"access_token": "ya29.a0...",
"refresh_token": "1//0g...",
"expires_at": datetime.fromisoformat("2026-12-01T12:00:00+00:00"),
}
},
)
print(response.connected_account.status)

Each connector names the fields it needs. Most use these:

TypeFieldsExample connector
Bearer tokentokenOpenAI: the API key
Basic authusername and passwordTwilio: the Account SID and Auth Token
API keyapi_keyExa: the API key
credentials = {
"openai": {"token": "sk-proj-..."}, # bearer
"twilio": {"username": "AC...", "password": "..."}, # basic auth
"exa": {"api_key": "..."}, # API key
}
for connection_name, fields in credentials.items():
response = actions.create_connected_account(
connection_name=connection_name,
identifier="user_123",
authorization_details={"static_auth": fields},
)
print(connection_name, response.connected_account.status)

Each account comes back ACTIVE. Some connectors use other field names, such as domain or one field per header. To see a connector’s fields, list its auth patterns:

Terminal window
curl -sS -G "$SCALEKIT_ENVIRONMENT_URL/api/v1/providers" \
-H "Authorization: Bearer $TOKEN" \
--data-urlencode identifier=TWILIO \
| jq '.providers[].auth_patterns[] | {type, fields: [.fields[] | {field_name, required}]}'

A request that leaves out a required field, or sends one the connector doesn’t define, fails with 400, such as unknown field 'api_key' for provider ALGOLIAMONITORING. An update replaces the whole credential, so send every required field when you rotate a key; that also makes an EXPIRED account ACTIVE again.

Your agent lists the user’s tools, then executes them. Each call names the user with identifier and the connection by its name. For the old platform’s code side by side with this, see the guide for Composio, Nango or Arcade.

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
)
result = actions.execute_tool(
tool_name="gmail_fetch_mails",
identifier="user_123",
connection_name="gmail",
tool_input={"query": "is:unread", "max_results": 5},
)
print(result.data)

Pass identifier and the connection name on every executeTool call: connection_name in Python, connector in Node.js.

Tool names and inputs can differ from the old platform’s. Find each tool’s exact name and input in the connector catalog.

Scalekit serves MCP through Virtual MCP servers: one static server URL for all users, with a short-lived session token per agent run.

  1. Create a Virtual MCP server that exposes the connections and tools you choose. This gives you its mcp_server_url.
  2. Mint a session token for the user before each agent run, and pass it as a bearer token.
{
"mcpServers": {
"scalekit": {
"url": "<MCP_SERVER_URL>",
"headers": {
"Authorization": "Bearer <SESSION_TOKEN>"
}
}
}
}

See Virtual MCP servers for the full setup.

Define custom tools in your app code and call the app’s API through the Scalekit proxy with actions.request(), which adds the user’s credentials. If a call returns proxy not enabled for provider, see Call any API.

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

For an app that isn’t in the catalog, add your own connector. It works like a built-in one.

API reference

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