How to use Appify and AgentKit by ScaleKit together.

Searching the Web

Appify AgentKit ScaleKit integration how to use together

Searching the Web

ScaleKit AgentKit Appify documentation 2025 2026

Reading Web Page

Apify AgentKit ScaleKit integration tutorial

Searching the Web

scalekit apify actor per-user OAuth agentkit cookbook site:docs.scalekit.com OR site:github.com

Reading Web Page

Apify AgentKit ScaleKit per-user OAuth setup steps code example

I now have enough to give a thorough, accurate answer. Here's the full guide:

Using Apify and AgentKit by ScaleKit Together

What's the idea?

Apify Actors run in isolated, stateless containers - there's no concept of "who is logged in." ScaleKit AgentKit solves exactly this: it provides a connected-accounts OAuth token vault, so each user who runs your Actor can connect their own third-party accounts (Notion, Google, Slack, etc.), and those tokens persist across runs without you managing credentials manually.
The combination lets you build Apify Actors that make authenticated, per-user API calls to external services, all orchestrated through ScaleKit's auth layer.
There's also a native Apify MCP connector in AgentKit's catalog, so you can also go the other direction - let an AgentKit-powered agent invoke Apify Actors (for web scraping, browser automation, etc.) directly from your agent workflows.

Pattern 1: Apify Actor with per-user OAuth via AgentKit

This is the primary integration pattern. The official cookbook and example repo walk through a Notion + YouTube research agent built as an Actor.

Prerequisites

  • A ScaleKit account at app.scalekit.com with API credentials
  • Apify CLI: npm install -g @apify/cli
  • Node.js 18+

Step 1: Set up Connectors in the ScaleKit Dashboard

Go to AgentKit > Connections > Create Connection in your ScaleKit dashboard.
For YouTube (shared account):
  1. Search for YouTube, click Create
  2. Copy the Redirect URI from the panel, paste it into your Google Cloud OAuth client under Authorized redirect URIs
  3. Enable YouTube Data API v3 in Google Cloud Console
  4. Add test users to your OAuth consent screen
  5. Enter your Client ID + Client Secret in ScaleKit, select scopes (youtube.readonly at minimum), click Save
  6. Note the connection name (e.g., youtube)
For Notion (per-user):
  1. Search for Notion, click Create
  2. Enter Client ID and Client Secret from your Notion integration
  3. ScaleKit pre-configures the redirect URI and scopes - click Save
  4. Note the connection name (e.g., notion)

Step 2: Create the Apify Actor Project

apify create notion-youtube-agent -t project_empty
cd notion-youtube-agent
npm install @scalekit-sdk/node openai apify

Step 3: Set Environment Variables

Set these as Actor environment variables in Apify Console > Settings > Environment variables (not as input fields - these are operator-level credentials):
SCALEKIT_ENV_URL=https://your-env.scalekit.cloud
SCALEKIT_CLIENT_ID=skc_...
SCALEKIT_CLIENT_SECRET=your-secret
For local dev, put them in .env and run apify login to set your APIFY_TOKEN.

Step 4: Initialize ScaleKit and Define Identifiers

In src/main.js, initialize the ScaleKit client and decide how to identify each user. Use Apify's built-in userId as the per-user key - this means tokens automatically persist across runs for each Apify account:
import { Actor } from 'apify';
import ScalekitClient from '@scalekit-sdk/node';

await Actor.init();

const { userId } = Actor.getEnv();
const scalekit = new ScalekitClient(
  process.env.SCALEKIT_ENV_URL,
  process.env.SCALEKIT_CLIENT_ID,
  process.env.SCALEKIT_CLIENT_SECRET
);

// Per-user: each Apify account connects their own Notion workspace
const notionIdentifier = userId;

// Shared: one YouTube OAuth session used by all runs
const youtubeIdentifier = 'shared-youtube'; // hardcoded, not an input field

Step 5: Handle the OAuth Flow with a Magic Link

Before calling any API, check whether the account is already connected. If not, generate an auth link and surface it to the user through Apify's OUTPUT:
// src/notionAuth.js
import { Actor } from 'apify';

const ACTIVE = 1;

export async function ensureNotionConnected(scalekitActions, identifier, { connectionName }) {
  const account = await scalekitActions.getConnectedAccount({ identifier, connectionName });

  if (account?.status === ACTIVE) return; // already authorized, proceed

  // Generate the magic link and pause the Actor
  const { link: magicLink } = await scalekitActions.getAuthorizationURL({
    identifier,
    connectionName,
  });

  // Write the auth URL to Actor output so the user can click it
  await Actor.setValue('OUTPUT', {
    status: 'AWAITING__AUTH',
    magicLink,
    message: 'Open the magicLink to authorize Notion, then re-run the Actor.',
  });

  // Poll until the user completes the flow
  await pollUntilAuthorized(scalekitActions, identifier, connectionName);
}
The Actor writes an AWAITING__AUTH payload with a magicLink to OUTPUT. The user opens that link, completes the OAuth flow, and the Actor picks up automatically.
ScaleKit also supports an interactive live view within the Apify Actor run UI, so instead of a raw JSON link you can render a proper auth page inline.

Step 6: Fetch Tokens and Call APIs

Once connected, retrieve the token from ScaleKit and use it to call the external API:
// src/notionTools.js
const token = await scalekitActions.getToken({ identifier, connectionName: 'notion' });

const response = await fetch('https://api.notion.com/v1/search', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${token.accessToken}`,
    'Notion-Version': '2022-06-28',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ query: searchTerm }),
});
ScaleKit handles token refresh automatically in the background.

Step 7: Build the Agentic Loop

With auth handled, wire your tools into an agent loop. The example repo uses an OpenAI-compatible LLM (via Apify's built-in OpenRouter proxy - no API key needed, billed to Apify credits):
// src/agent.js
import { notionTools } from './notionTools.js';
import { youtubeTools } from './youtubeTools.js';

const tools = [...notionTools, ...youtubeTools];

// Standard OpenAI tool-calling loop
while (true) {
  const response = await llm.chat({ messages, tools });
  if (response.finish_reason === 'stop') break;

  const toolResults = await Promise.all(
    response.tool_calls.map(call => executeTool(call, scalekitActions))
  );
  messages.push(...toolResults);
}

Step 8: Deploy to Apify

apify push
Then in Actor Settings > Environment variables, set:
  • SCALEKIT_ENV_URL
  • SCALEKIT_CLIENT_ID
  • SCALEKIT_CLIENT_SECRET
  • Optionally NOTION_DEFAULT_PARENT_PAGE_ID or NOTION_DEFAULT_DATABASE_ID
To monetize: enable Pay-Per-Event under Actor Settings > Monetisation:
EventDefault price
task-completed$0.05 per run
tool-call$0.01 per tool call

Pattern 2: Use the Apify MCP Connector Inside an AgentKit Agent

If you're building an agent outside Apify and want it to be able to invoke Apify Actors (for scraping, automation, data extraction), ScaleKit has a native Apify MCP connector in its catalog.
In the ScaleKit dashboard, create a connection for Apify MCP (uses Bearer Token auth). Your agent then gets Apify Actor invocation as a native tool call, with the same token management and audit trail as any other AgentKit connector.

Project Structure (from the example repo)

.actor/
  actor.json          # Apify actor metadata
  input_schema.json   # Apify Store UI form
  output_schema.json  # Actor output for web view + dataset
  pay_per_event.json  # Monetisation event definitions
src/
  main.js             # Actor entry point - auth + agent
  agent.js            # Agentic loop (tools + LLM)
  llm.js              # LLM abstraction (OpenAI-compatible)
  notionTools.js      # Notion tool definitions + Scalekit executor
  notionAuth.js       # Magic link + polling auth flow
  youtubeTools.js     # YouTube API calls via Scalekit
  youtubeAuth.js      # YouTube magic link + polling auth flow

Key Design Principles

  • Operator credentials vs. user tokens - Your SCALEKIT_CLIENT_ID/SECRET are operator-level (go in env vars, never in input). Individual users' OAuth tokens are stored by ScaleKit keyed by identifier.
  • Apify userId as the identifier - Using Actor.getEnv().userId means tokens persist across runs automatically per Apify account, with no user-managed input fields.
  • Shared vs. per-user connectors - Some services (e.g., a shared YouTube research account) use a hardcoded identifier; others (Notion, Gmail) use the per-user userId. Make this decision per connector.
  • Magic link polling - Because Actors run headlessly, the auth handoff works by writing a link to OUTPUT and polling ScaleKit until the connected account becomes active.
This is a shared conversation. Sign in to Orris to start your own chat.