An AI agent built as an Apify actor that accepts a single natural language task and handles both Notion operations and YouTube research — or both together in one run.
Authentication is handled by Scalekit, so the actor never manages OAuth tokens directly:
- Per-user Notion accounts identified by
notionUserEmail - A shared YouTube connected account identified by
youtubeIdentifier
The agent interprets a free-form task and calls the appropriate tools:
Notion-only examples:
"List the 5 most recently edited pages in my Notion workspace""Create a new page titled Meeting Notes under the workspace root""Read the content of the page titled Product Roadmap"
YouTube → Notion example:
"Search YouTube for Python tutorial channels and append the top 10 to my Research page"
For YouTube research, the agent:
- Resolves the target Notion page by name, creating it when a default parent/database is configured
- Expands the keyword into semantic search variations using an LLM
- Searches YouTube for each variation and deduplicates channels
- Fetches subscriber count and channel metadata
- Scores each channel for relevance (0–10) using an LLM
- Appends a ranked results section to the Notion page
Output in Notion (per channel):
- Relevance score and reasoning
- Subscriber and video count
- Channel URL
- Sample video link
- Node.js v18+
- Apify CLI:
npm install -g @apify/cli - A Scalekit environment with:
- A Notion connection named
notion - A YouTube connection named
youtube
- A Notion connection named
- An OpenAI-compatible LLM endpoint and API key (default:
https://llm.scalekit.cloudwithclaude-sonnet-4-6)
git clone https://github.com/scalekit-inc/notion-youtube-agent.git
cd notion-youtube-agent
npm installcp .env.example .envEdit .env with your Scalekit credentials:
SCALEKIT_ENV_URL=https://your-env.scalekit.com
SCALEKIT_CLIENT_ID=prd_skc_xxxxx
SCALEKIT_CLIENT_SECRET=your_secretThese are operator-level credentials — they authorize the actor to use Scalekit, not individual users.
The actor handles Notion authorization automatically:
- On first run for a given
notionUserEmail, the actor generates a magic link and writes it toOUTPUT - Open the link to authorize Notion for that user
- The actor polls until authorization completes, then proceeds
The actor now handles YouTube authorization the same way:
- If the YouTube connected account (
youtubeIdentifier, defaultshared-youtube) is not yet authorized, the actor generates a magic link and writes it toOUTPUT - Open the link to authorize the shared YouTube account (done once by the operator)
- The actor polls until authorization completes, then proceeds
Copy INPUT.example.json and fill in your values:
mkdir -p storage/key_value_stores/default
cp INPUT.example.json storage/key_value_stores/default/INPUT.json
# edit INPUT.json with your valuesRun the actor:
npm start
# or
apify runIf Notion or YouTube authorization is needed, the actor writes an AWAITING_*_AUTH payload to OUTPUT with a magicLink. Open that link and the actor continues automatically.
Scalekit credentials (SCALEKIT_ENV_URL, SCALEKIT_CLIENT_ID, SCALEKIT_CLIENT_SECRET) are set as actor environment variables, not input fields. The LLM API key can be supplied per run as llmApiKey; if omitted, the actor uses the LLM_API_KEY environment variable. To let the actor create a missing Notion page, set either notionDefaultParentPageId / NOTION_DEFAULT_PARENT_PAGE_ID or notionDefaultDatabaseId / NOTION_DEFAULT_DATABASE_ID.
| Field | Required | Default | Description |
|---|---|---|---|
task |
Yes | — | Natural language task, e.g. "Search YouTube for Python tutorial channels and append the top 10 to my Research page" |
notionUserEmail |
Yes | — | Email used as the Scalekit identifier for the user's Notion connected account |
llmApiKey |
No | LLM_API_KEY env var |
API key for the LLM endpoint. Use this when the end user should provide their own key. |
llmBaseUrl |
No | https://llm.scalekit.cloud |
OpenAI-compatible endpoint base URL |
llmModel |
No | claude-sonnet-4-6 |
Model name passed to the LLM endpoint |
notionDefaultParentPageId |
No | NOTION_DEFAULT_PARENT_PAGE_ID env var |
Parent page where a missing target page should be created. |
notionDefaultDatabaseId |
No | NOTION_DEFAULT_DATABASE_ID env var |
Database where a missing target page should be created. Use this instead of a parent page when desired. |
youtubeIdentifier |
No | shared-youtube |
Scalekit identifier for the shared YouTube connected account |
authTimeoutSeconds |
No | 300 |
How long to wait for Notion or YouTube authorization (seconds) |
maxIterations |
No | 10 |
Max agent loop iterations |
.actor/
actor.json # Apify actor metadata
input_schema.json # Apify Store UI form definition
output_schema.json # Actor output links for web view + dataset results
pay_per_event.json # Monetisation event definitions
src/
main.js # Actor entry point — auth + agent
agent.js # Agentic loop (Notion + YouTube tools)
llm.js # LLM abstraction (OpenAI-compatible)
notionTools.js # Notion tool definitions + Scalekit executor
notionAuth.js # Notion magic link + polling auth flow
youtubeTools.js # YouTube API calls via Scalekit
youtubeAgentTools.js # youtube_search_channels agent tool definition
youtubeResearch.js # YouTube research pipeline (expand → search → score)
youtubeAuth.js # YouTube magic link + polling auth flow
apify login
apify pushAfter pushing, set SCALEKIT_ENV_URL, SCALEKIT_CLIENT_ID, SCALEKIT_CLIENT_SECRET, and optionally LLM_API_KEY, NOTION_DEFAULT_PARENT_PAGE_ID, or NOTION_DEFAULT_DATABASE_ID in Actor Settings → Environment variables in the Apify console.
To enable Pay-Per-Event pricing, go to Actor Settings → Monetisation:
| Event | Default price |
|---|---|
task-completed |
$0.05 per run |
tool-call |
$0.01 per tool call |
This actor uses Scalekit Agent Auth to connect to Notion and YouTube. Scalekit stores OAuth tokens, handles refresh, and proxies API calls.
Auth flow on each run:
- Notion: looks up or creates a connected account for
notionUserEmail. If not ACTIVE, generates a magic link, outputs it, and polls until authorized. - YouTube: looks up or creates a connected account for
youtubeIdentifier. If not ACTIVE, generates a magic link, outputs it, and polls until authorized. - Once both accounts are ACTIVE, the agent runs and all API calls are proxied through Scalekit.