The real problem
Why this is harder than it looks
The Google Slides API itself is clean. You can create a presentation, read its structure, or inject content with straightforward REST calls. The friction starts before your agent makes a single API call — when you try to get authorized to make them at all.
Google classifies the https://www.googleapis.com/auth/presentations scope as sensitive, which triggers a mandatory app verification process before real users outside your Google Workspace can authorize your app. That verification isn't a rubber stamp: you need a verified domain, a published privacy policy, a working homepage, and a complete OAuth consent screen — then you wait. And if your agent also needs to export presentations to Drive (which most use cases do), you're requesting Drive scopes on top of Slides scopes, potentially pushing into restricted-scope territory that requires an annual security assessment from a third-party auditor.
Then there's the multi-user problem. Google issues short-lived access tokens. For a single-user script, one refresh is trivial. For a product where dozens of employees each connect their own Google account, you need token storage that's isolated per user, proactive refresh logic that runs before expiry rather than after a 401, and detection when a user revokes access from their Google account settings — which makes their token invalid immediately with no webhook to tell you.
None of this is impossible. But you'll spend real time on OAuth app registration, consent screen wording, verification submission, and per-user token plumbing before your agent can do anything useful. Scalekit handles all of it. You register your Google Cloud credentials once; Scalekit manages the token lifecycle for every user from there.
Capabilities
What your agent can do with Google Slides
Once connected, your agent has 2 pre-built tools for reading and creating presentations:
- Create presentations programmatically: spin up new Google Slides presentations with a title, ready for further population via the Slides API
- Read full presentation structure: fetch slides, text, images, shapes, layout metadata, and presentation-level properties in one call
Setup context
What we're building
This guide connects a presentation assistant agent to Google Slides — helping users generate, inspect, and manage slide decks without leaving your product.
🤖
Example agent
Presentation assistant creating and reading slide decks on behalf of each user
🔐
Auth model
B2B SaaS — each user connects their own Google account. identifier = your user ID
Setup
1 Setup: One SDK, One credential
Install the Scalekit SDK. The only credential your application manages is the Scalekit API key — no Google OAuth secrets, no user tokens, nothing belonging to your customers.
pip install scalekit-sdk-python
import scalekit.client
import 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
Connected Accounts
2 Per-User Auth: Creating connected accounts
Each user gets their own Connected Account, giving them a dedicated auth context. The identifier is any unique string from your system — a UUID, email, whatever you use internally.
response = actions.get_or_create_connected_account(
connection_name="google_slides",
identifier="user_slides_456" # your internal user ID
)
connected_account = response.connected_account
print(f"Status: {connected_account.status}")
# Status: PENDING — user hasn't authorized yet
This call is idempotent — safe to call on every session start. Returns the existing account if one already exists.
Authorization Flow
3 The authorization flow
The user authorizes your agent once. Scalekit generates the OAuth URL with correct scopes, PKCE challenge, and redirect handling pre-configured. After approval, you never see the token.
if connected_account.status != "ACTIVE":
link = actions.get_authorization_link(
connection_name="google_slides",
identifier="user_slides_456"
)
# Redirect user → Google OAuth consent screen
# Scalekit captures the token on callback
return redirect(link.link)
Token management is automatic
After the user approves, Scalekit stores encrypted tokens and the connected account moves to ACTIVE. Access
tokens refresh before expiry. If a user revokes access from their Google account settings, the account moves
to REVOKED — no silent failures on subsequent calls. Check account.status before critical operations.
BYOC is required — Google Cloud credentials must be your own
Unlike some connectors, Google Slides requires you to supply your own OAuth client credentials. Register
your OAuth app in Google Cloud Console, enable the Google Slides API, add the Scalekit redirect URI as an
authorized redirect, then paste your Client ID and Secret into the Scalekit dashboard. Token management
stays fully handled.
Already have credentials?
Calling Google Slides
4 Calling Google Slides: What your agent writes
With the connected account active, your agent calls tools using actions.execute_tool(). For operations beyond the pre-built tools, use actions.request() to proxy any Slides REST endpoint directly — Scalekit injects the correct token automatically.
Create a new presentation
Spin up a new Google Slides presentation with a title. The returned presentationId is used for all subsequent read or update operations.
result = actions.execute_tool(
identifier="user_slides_456",
tool_name="googleslides_create_presentation",
tool_input={
"title": "Q3 2026 Business Review"
}
)
# { "presentationId": "1BxiMVs0XRA...", "title": "Q3 2026 Business Review",
# "slides": [...], "pageSize": { "width": {...}, "height": {...} } }
Read a presentation's full structure
Retrieve the complete structure and content of an existing presentation — slides, text boxes, images, shapes, and metadata. Use the fields parameter to limit the response size.
result = actions.execute_tool(
identifier="user_slides_456",
tool_name="googleslides_read_presentation",
tool_input={
"presentation_id": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms",
"fields": "slides,title,pageSize"
}
)
# Returns slides array — each slide contains elements (shapes, images,
# text boxes) with position, size, and content data.
Make raw Slides API calls for advanced operations
For operations beyond the pre-built tools — adding slides, replacing text, inserting images — proxy any Slides REST endpoint directly via actions.request().
# Insert text into a shape on an existing slide
result = actions.request(
connection_name="google_slides",
identifier="user_slides_456",
path="/v1/presentations/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms:batchUpdate",
method="POST",
json={
"requests": [
{
"insertText": {
"objectId": "title_shape_id",
"insertionIndex": 0,
"text": "Q3 Revenue Summary"
}
}
]
}
)
# Returns presentationId + array of replies per request
Framework wiring
5 Wiring into your agent framework
Scalekit integrates directly with LangChain. The agent decides what to create or read; Scalekit handles auth on every invocation. No token plumbing in your agent logic.
from langchain_anthropic import ChatAnthropic
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from scalekit.langchain import get_tools
slides_tools = get_tools(
connection_name="google_slides",
identifier="user_slides_456"
)
prompt = ChatPromptTemplate.from_messages([
("system", "You are a presentation assistant. Use the available tools to help create and manage Google Slides presentations."),
MessagesPlaceholder("chat_history", optional=True),
("human", "{input}"),
MessagesPlaceholder("agent_scratchpad"),
])
agent = create_tool_calling_agent(ChatAnthropic(model="claude-sonnet-4-6"), slides_tools, prompt)
result = AgentExecutor(agent=agent, tools=slides_tools).invoke({
"input": "Create a new presentation called 'Product Roadmap H2 2026' and tell me its ID"
})
Other frameworks supported
Tool reference
Google Slides tools
Your agent calls tools by name — no API wrappers to write. For operations beyond these tools, use actions.request() to proxy any Slides REST endpoint.
googleslides_create_presentation
Create a new Google Slides presentation with an optional title. Returns the full presentation object including presentationId.
googleslides_read_presentation
Read the complete structure and content of a presentation — slides, text, images, shapes, and metadata. Supports a fields mask to limit response size.
Connector notes
Google Slides-specific behavior
BYOC is required — no managed app available
Google Slides does not offer a shared managed OAuth app. You must register your own OAuth client in Google
Cloud Console, enable the Google Slides API in your project, and provide your Client ID and Client Secret
in the Scalekit dashboard. The Scalekit redirect URI must be added as an authorized redirect URI in your
Google Cloud OAuth credentials before the authorization flow will work.
App verification is required for production use
The Slides API uses a sensitive OAuth scope. Until your Google Cloud project completes OAuth app
verification, users outside your organization will see an "unverified app" warning before the consent
prompt. Verification requires a publicly accessible homepage, a privacy policy URL, and domain ownership
confirmation in Google Search Console. Plan for 2–7 business days before launching to external users.
Drive scope required for export operations
The presentations scope covers reading and writing slide content. If your agent needs to export
presentations to PDF or other formats, or access files from Google Drive, you must also request a Drive
scope (drive.file for the narrowest access). Add any additional scopes when configuring the connection
in the Scalekit dashboard.
Infrastructure decision
Why not build this yourself
The Google Slides OAuth flow is documented. Token storage isn't technically hard. But here's what you're actually signing up for:
PROBLEM 01
Google OAuth app verification — the sensitive scope classification means every external user sees an "unverified app" screen until you complete Google's review process
PROBLEM 02
Per-user token isolation across a multi-tenant system — Google's short-lived access tokens must be refreshed proactively and independently for every user
PROBLEM 03
Revocation detection when users disconnect your app from their Google account — tokens become invalid immediately with no push notification
PROBLEM 04
Scope management as your agent's capabilities grow — adding Drive or other Google scopes requires users to re-authorize, a non-trivial re-consent flow to design and handle
That's one connector. Your agent product will eventually need Gmail, Google Drive, Salesforce, Slack, and whatever else your customers ask for. Each has its own OAuth quirks and failure modes.
Scalekit maintains every connector. You maintain none of them.