skills/integrating-agent-auth/SKILL.md
Integrates Scalekit Agent Auth into a project to handle OAuth flows, token storage, and automatic refresh for third-party services (Gmail, Slack, Notion, Calendar). Use when a user needs to connect to an external service, authorize OAuth access, fetch access or refresh tokens, or execute API calls on behalf of a user.
npx skillsauth add scalekit-inc/skills integrating-agent-authInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Scalekit handles the full OAuth lifecycle — authorization, token storage, and refresh — so agents can act on behalf of users in Gmail, Slack, Notion, Calendar, and other connectors.
Required env vars: SCALEKIT_CLIENT_ID, SCALEKIT_CLIENT_SECRET, SCALEKIT_ENV_URL
→ Get from app.scalekit.com: Developers → Settings → API Credentials
Install the SDK and initialize the client:
<tabs>Important: Except for Gmail, all connectors must be configured in the Scalekit Dashboard first before creating authorization URLs.
To set up a connector: Scalekit Dashboard → Agent Auth → Connections → + Create Connection → Select connector → Set Connection Name → Save
Python
pip install scalekit-sdk-python
import scalekit.client, os
from dotenv import load_dotenv
load_dotenv()
scalekit = scalekit.client.ScalekitClient(
client_id=os.getenv("SCALEKIT_CLIENT_ID"),
client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"),
env_url=os.getenv("SCALEKIT_ENV_URL"),
)
actions = scalekit.actions
Node.js
npm install @scalekit-sdk/node
import { ScalekitClient } from '@scalekit-sdk/node';
import 'dotenv/config';
const scalekitClient = new ScalekitClient(
process.env.SCALEKIT_ENV_URL!,
process.env.SCALEKIT_CLIENT_ID!,
process.env.SCALEKIT_CLIENT_SECRET!
);
const { connectedAccounts } = scalekitClient;
</tabs>
Before integrating with a connector, follow these steps in the Scalekit Dashboard:
Gmail is the only connector that does not require dashboard setup. Skip this section for Gmail.
For all other connectors (Slack, Notion, Google Calendar, etc.):
MY_SLACK, MY_NOTION)Important: The Connection Name you set in the dashboard is exactly what you use as the
connection_nameparameter in your code. They must match exactly.
First, ask the user:
Are you starting fresh and want a quick test with Gmail, or are you integrating directly into your project?
Copy this checklist and check off steps as you complete them:
Agent Auth Integration Progress:
- [ ] Step 1: SDK installed and client initialized
- [ ] Step 2: Connected account created for the user
- [ ] Step 3: User has authorized the connection (status = ACTIVE)
- [ ] Step 4: Access token fetched successfully
- [ ] Step 5: Downstream API call succeeds with fetched token
Replace "user_123" with the project's actual user ID. Replace "gmail" with the target connector.
Python
response = actions.get_or_create_connected_account(
connection_name="gmail",
identifier="user_123"
)
connected_account = response.connected_account
Node.js
const response = await connectedAccounts.getOrCreateConnectedAccount({
connector: 'gmail',
identifier: 'user_123',
});
const connectedAccount = response.connectedAccount;
If status is not ACTIVE, the user must complete OAuth. In a web app, redirect to link. In CLI/dev, print and wait.
Python
if connected_account.status != "ACTIVE":
link_response = actions.get_authorization_link(
connection_name="gmail",
identifier="user_123"
)
print("Authorize here:", link_response.link)
input("Press Enter after authorizing...")
Node.js
if (connectedAccount?.status !== 'ACTIVE') {
const linkResponse = await connectedAccounts.getMagicLinkForConnectedAccount({
connector: 'gmail',
identifier: 'user_123',
});
console.log('Authorize here:', linkResponse.link);
// Web app: redirect user to linkResponse.link
}
ALWAYS call get_connected_account immediately before any API call — Scalekit auto-refreshes tokens and this guarantees the latest valid token.
Python
response = actions.get_connected_account(
connection_name="gmail",
identifier="user_123"
)
tokens = response.connected_account.authorization_details["oauth_token"]
access_token = tokens["access_token"]
refresh_token = tokens["refresh_token"]
Node.js
const accountResponse = await connectedAccounts.getConnectedAccountByIdentifier({
connector: 'gmail',
identifier: '[email protected]',
});
const authDetails = accountResponse?.connectedAccount?.authorizationDetails;
const accessToken = authDetails?.details?.case === 'oauthToken'
? authDetails.details.value?.accessToken : undefined;
const refreshToken = authDetails?.details?.case === 'oauthToken'
? authDetails.details.value?.refreshToken : undefined;
Use access_token from Step 3 as a Bearer token. Example: fetch 5 unread Gmail messages.
Python
import requests
headers = {"Authorization": f"Bearer {access_token}"}
list_url = "https://gmail.googleapis.com/gmail/v1/users/me/messages"
messages = requests.get(
list_url, headers=headers, params={"q": "is:unread", "maxResults": 5}
).json().get("messages", [])
for msg in messages:
data = requests.get(
f"{list_url}/{msg['id']}", headers=headers,
params={"format": "metadata", "metadataHeaders": ["From", "Subject", "Date"]}
).json()
hdrs = data.get("payload", {}).get("headers", [])
print(next((h["value"] for h in hdrs if h["name"] == "Subject"), "No Subject"))
print(next((h["value"] for h in hdrs if h["name"] == "From"), "Unknown"))
print(data.get("snippet", ""))
print("-" * 50)
Node.js
const listUrl = 'https://gmail.googleapis.com/gmail/v1/users/me/messages';
const params = new URLSearchParams({ q: 'is:unread', maxResults: '5' });
const { messages = [] } = await fetch(`${listUrl}?${params}`, {
headers: { Authorization: `Bearer ${accessToken}` },
}).then(r => r.json());
for (const msg of messages) {
const msgData = await fetch(
`${listUrl}/${msg.id}?format=metadata&metadataHeaders=From&metadataHeaders=Subject&metadataHeaders=Date`,
{ headers: { Authorization: `Bearer ${accessToken}` } }
).then(r => r.json());
const h = msgData.payload?.headers ?? [];
console.log('Subject:', h.find(x => x.name === 'Subject')?.value ?? 'No Subject');
console.log('From:', h.find(x => x.name === 'From')?.value ?? 'Unknown');
console.log('Snippet:', msgData.snippet ?? '');
console.log('-'.repeat(50));
}
Replace "gmail" with any supported connector name: slack, notion, calendar, etc.
The SDK workflow (Steps 1–3) is identical for all connectors. Only the downstream API call (Step 4) changes.
For connector-specific API details, see CONNECTORS.md.
Use Scalekit tools with AI frameworks to build agents that can execute actions on behalf of users.
Create conversational agents with LangChain that can autonomously call Scalekit tools based on user intent.
Python
from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain_core.prompts import ChatPromptTemplate
# Fetch tools from Scalekit in LangChain format
tools = actions.langchain.get_tools(
identifier="user_123",
providers=["GMAIL"],
page_size=100
)
# Define the agent prompt
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant with access to external tools."),
("placeholder", "{chat_history}"),
("human", "{input}"),
("placeholder", "{agent_scratchpad}"),
])
# Create and run the agent
llm = ChatOpenAI(model="gpt-4o")
agent = create_openai_tools_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
result = executor.invoke({"input": "fetch my last 5 unread emails and summarize them"})
Build agents using Google's Agent Development Kit with native Gemini integration.
Python
from google.adk.agents import Agent
# Fetch tools from Scalekit in Google ADK format
gmail_tools = actions.google.get_tools(
providers=["GMAIL"],
identifier="user_123",
page_size=100
)
# Create the agent
agent = Agent(
name="gmail_assistant",
model="gemini-2.5-flash",
description="Gmail assistant that can read and manage emails",
instruction="You are a helpful Gmail assistant that can read, send, and organize emails.",
tools=gmail_tools
)
# Run the agent
response = agent.process_request("fetch my last 5 unread emails and summarize them")
For more examples and framework-specific patterns, see code-samples.md.
For comprehensive documentation on connected accounts lifecycle, states, and API usage, see connected-accounts.md.
For code samples and implementation examples by framework, see code-samples.md.
For an overview of supported providers and their capabilities, see providers.md.
For comprehensive token management including refresh, security, and monitoring, see token-management.md.
For configuring your own OAuth credentials per connector (whitelabeling, dedicated quotas), see byoc.md.
tools
Create or review Scalekit custom providers/connectors for proxy-only usage, including MCP providers. Use this skill when the task is to gather API docs, infer whether a connector is OAuth, Basic, Bearer, or API Key, determine if it is an MCP provider, determine required tracked fields like domain or version, generate provider JSON, check for existing custom providers, show update diffs, run approved create or update curls, and print resolved delete curls.
tools
Use when a developer is new to Scalekit and needs guidance on where to start, doesn't know which auth plugin or skill to choose, wants to connect an AI agent or agentic workflow to third-party services (Gmail, Slack, Notion, Google Calendar), needs OAuth or tool-calling auth for agents, wants to add authentication to a project but hasn't chosen an approach yet, or needs to install the Scalekit plugin for their AI coding tool (Claude Code, Codex, Copilot CLI, Cursor, or other agents).
tools
Use when a user asks to generate, review, validate, or fix any code snippet that uses Scalekit APIs or SDKs. This skill is the single source of truth for Scalekit code correctness — it can generate illustration-quality snippets from scratch (for docs, websites, or integration guides) and review existing code to catch wrong method names, missing parameters, security anti-patterns, and broken auth flows. Covers all four SDKs (Node, Python, Go, Java), raw REST API calls, and both Scalekit product suites — SaaSKit (SSO, login, sessions, RBAC, SCIM) and AgentKit (connections, tool calling, MCP auth). Use when the user says review my Scalekit code, generate a Scalekit example, validate this auth flow, check my SDK usage, fix my Scalekit integration, write a code sample for docs, or anything involving Scalekit code quality.
development
Walks through a structured production readiness checklist for Scalekit SSO implementations. Use when the user says they are going live, launching to production, doing a pre-launch review, hardening their SSO setup, or wants to verify their Scalekit implementation is production-ready.