Google Photos

Live

OAUTH 2.0

PHOTO LIBRARY

Media

Google Photos gives your agent the photo library your app manages: create albums, add and organize media items, search by date or category, and let users pick photos from their full library through the Picker.

  • Per-user credentials: each call uses the actual user's token, never a shared bot.
  • Encrypted per-tenant vault: AES-256, resolved at request time, never in LLM context.
  • Scoped before every call: pre-call scope check, 90-day SIEM-exportable audit chain.
Google Photos
agent · Acme Q3
Run
Find the photos uploaded through this app last weekend.
S
googlephotos_search_media_items
97ms
Photo agent
18 photos and 2 videos were uploaded between Saturday and Sunday. 14 of them are already in the Offsite 2026 album.
Sources: Google Photos, 20 media items
googlephotos
20 media items
18:29
Message Claude...

Tools your photo agent reaches for on Google Photos, scoped per user.

CALL ANY TOOL
17 tools for the Google Photos photo library your app creates: albums, media items, search, and Picker sessions that let users choose from their full library.
googlephotos_add_album_enrichment
Add album enrichment
Add a text caption, location, or map enrichment item to an album this app created, Google removed access to a user's pre-existing Photos library in March 2025, so enrichments can only be added to app-owned albums. Provide exactly one enrichment type (text, location, or map) with the fields it needs, and optionally where in the album to place it relative to an existing media item or enrichment. Returns the id of the newly created enrichment item. Use add_album_enrichment after create_album to annotate an album with narrative text, a place, or a route between two places.
Parameters
Name
Type
Required
Description
album_id
string
Required
Identifier of the album to add the enrichment item to. Must be an album created by this app. Obtain the id from a prior create_album or list_albums call.
enrichment_type
string
Required
Which kind of enrichment item to create. "text" adds a caption, "location" pins a single place, and "map" draws a route between two places. Exactly one type is created per call, and only the fields for the chosen type are used. One of: `text`, `location`, `map`.
destination_latitude
number
Optional
Latitude of the destination place, in decimal degrees. Only used when enrichment_type is "map". Provide both destination latitude and longitude together, or omit both.
destination_location_name
string
Optional
Display name of the destination place for a route. Required when enrichment_type is "map" (location_name/latitude/longitude describe the origin, this describes the destination). Ignored otherwise.
destination_longitude
number
Optional
Longitude of the destination place, in decimal degrees. Only used when enrichment_type is "map". Provide both destination latitude and longitude together, or omit both.
latitude
number
Optional
Latitude of the place named in location_name, in decimal degrees. Optional even for "location"/"map", provide both latitude and longitude together, or omit both.
location_name
string
Optional
Display name of the place to pin. Required when enrichment_type is "location" (the place itself); used as the origin's name when enrichment_type is "map". Ignored for "text".
longitude
number
Optional
Longitude of the place named in location_name, in decimal degrees. Optional even for "location"/"map", provide both latitude and longitude together, or omit both.
position
string
Optional
Where in the album to place the new enrichment item. FIRST_IN_ALBUM and LAST_IN_ALBUM place it at either end; AFTER_MEDIA_ITEM requires relative_media_item_id; AFTER_ENRICHMENT_ITEM requires relative_enrichment_item_id. Defaults to LAST_IN_ALBUM. One of: `POSITION_TYPE_UNSPECIFIED`, `FIRST_IN_ALBUM`, `LAST_IN_ALBUM`, `AFTER_MEDIA_ITEM`, `AFTER_ENRICHMENT_ITEM`. Default: `LAST_IN_ALBUM`.
relative_enrichment_item_id
string
Optional
Enrichment item id the new enrichment item should be placed after. Required when position is AFTER_ENRICHMENT_ITEM; ignored otherwise.
relative_media_item_id
string
Optional
Media item id the new enrichment item should be placed after. Required when position is AFTER_MEDIA_ITEM; ignored otherwise.
text
string
Optional
The caption text to display. Required when enrichment_type is "text"; ignored otherwise. Also accepts `schema_version` and `tool_version` to pin a version.
googlephotos_batch_add_media_items_to_album
Batch add media items to album
googlephotos_batch_create_media_items
Batch create media items
googlephotos_batch_get_media_items
Batch get media items
googlephotos_batch_remove_media_items_from_album
Batch remove media items from album
googlephotos_create_album
Create album
googlephotos_create_picker_session
Create picker session
googlephotos_delete_picker_session
Delete picker session
googlephotos_get_album
Get album
googlephotos_get_media_item
Get media item
googlephotos_get_picker_session
Get picker session
googlephotos_list_albums
List albums
googlephotos_list_media_items
List media items
googlephotos_list_picker_media_items
List picker media items
googlephotos_search_media_items
Search media items
googlephotos_update_album
Update album
googlephotos_update_media_item
Update media item
Build your Agent
Same auth pattern across LangChain, OpenAI, Anthropic, and Google ADK.
Python · LlamaIndex
import { ScalekitClient } from "@scalekit-sdk/node";
import { createReactAgent } from "@langchain/langgraph/prebuilt";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);

// Google Photos tools scoped to this user
const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["googlephotos"], toolNames: [
    "googlephotos_create_picker_session",
    "googlephotos_search_media_items",
    "googlephotos_create_album"] },
  pageSize: 100,
});

const agent = createReactAgent({ llm, tools });
await agent.invoke({ messages: [{ role: "user", content: "Find the photos uploaded through this app last weekend" }] });
import OpenAI from "openai";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);
const openai = new OpenAI();

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["googlephotos"] }, pageSize: 100,
});

const res = await openai.chat.completions.create({
  model: "gpt-5",
  messages: [{ role: "user", content: "Find the photos uploaded through this app last weekend" }],
  tools,
});

// Execute the tool call with the user's vaulted Google Photos token
await sk.tools.executeTool(res.choices[0].message.tool_calls[0], "user_123");
import Anthropic from "@anthropic-ai/sdk";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);
const anthropic = new Anthropic();

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["googlephotos"] }, pageSize: 100,
});

const msg = await anthropic.messages.create({
  model: "claude-sonnet-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Find the photos uploaded through this app last weekend" }],
  tools,
});

// Tool call runs with the user's vaulted Google Photos token
await sk.tools.executeTool(msg.content, "user_123");
import { Agent } from "@google/adk/agents";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["googlephotos"] }, pageSize: 100,
});

const agent = new Agent({
  name: "photo_agent",
  model: "gemini-2.5-pro",
  instruction: "Google Photos tools scoped to this user",
  tools,
});

await agent.run("Find the photos uploaded through this app last weekend");
Try these prompts
Copy any prompt into your agent. Each maps directly to a Google Photos tool. Click to copy, paste into your agent, done.
Albums
Copy the prompt
Copied
Create an album called Offsite 2026.
Copy the prompt
Copied
Add these 12 media items to the Offsite 2026 album.
Copy the prompt
Copied
Add a caption and a location to the Offsite 2026 album.
Media items
Copy the prompt
Copied
List the photos this app uploaded this month.
Copy the prompt
Copied
Search this app's favorite photos from June 2026.
Copy the prompt
Copied
Update the description on this photo.
Picker
Copy the prompt
Copied
Start a Picker session so I can choose photos from my library.
Copy the prompt
Copied
Check whether I finished picking photos.
Copy the prompt
Copied
List the photos I picked in this session.
SEE HOW AUTH WORKS
Each user signs in to Google Photos once; Scalekit stores and refreshes their tokens. Credentials stay vaulted, every call is scope checked, and every action is logged.
1
Authorize
Your user connects
Google Photos
once. We tie it to their identity and the meetings they approved — no shared bot account, no org-wide access
Who:
user ‘A’
when:
Once per user
access:
Limited to user
2
Store
Their
Google Photos
token lives in a vault scoped to them. User A's meetings are never reachable by an agent acting for user B, even on the same connection
vault:
encrypted
scope:
per-user
tokens:
auto-refreshed
3
Resolve
When your agent calls a
Google Photos
tool, we fetch the right token server-side. It never touches your agent, never appears in the LLM context, never shows up in your logs
speed:
~40ms
check:
before every call
seen by:
nobody
4
Audit
Every
Google Photos
tool call is logged — who triggered it, which meeting was fetched, what came back. 90 days of history, tied to the user who authorized it
history:
90 days
export:
SIEM-ready
logged:
every call
Test other agents
See the same per-user auth pattern across other media and file connectors.
Support and Ops Teams
Email-to-calendar agent
Reads scheduling intent out of Gmail threads, resolves the times everyone actually has free, and creates the event on the user's own Google Calendar. No shared service account.
Support and Ops Teams
Meeting prep
Pulls agenda, participant context, and open action items before every meeting.
Engineering Teams
Slack triage
Polls Slack for new messages, classifies bugs and support requests with a LangGraph router, files GitHub issues or Zendesk tickets, and confirms in the thread.
GTM and RevOps Teams
Competitive intelligence briefing agent
Scans Gong calls for competitor mentions, matches each one to its Notion battlecard, and DMs every affected rep a single Slack digest per cycle. Every call runs as the PMM who owns the briefing, never a shared bot.
Test other agents
See the same per-user auth pattern across other media and file connectors.
OPS
Email-to-calendar scheduling agent
Read scheduling intent out of Gmail threads, resolve mutual free time, and create the Google Calendar event.
OPS
Meeting prep agent
Assemble the agenda, HubSpot attendee history, and open action items from Gmail before every meeting on the calendar.
ENGINEERING
Slack triage agent
Classify new Slack messages as bugs or support requests, file the GitHub issue or Zendesk ticket, and reply in the thread.
GTM
Competitive intelligence briefing agent
Scan Gong calls for competitor mentions, match each one to its Notion battlecard, and DM every affected rep a single Slack digest.
Why Scalekit
Secure your agent's access. Connectors ship in minutes
01.
Shared tokens break per-user analytics
A shared Google Photos token looks fine in a demo. In production every album and upload looks like one service account, and you cannot tell which user triggered it. Scalekit resolves the credential of the actual user who triggered the agent, never a shared bot.
// shared token
audit → bot_service_account

// scalekit
audit → user_abc ✓
02.
Authentication is not authorization
03.
Multi-tenancy is architectural
04.
Google Photos today. Ten connectors tomorrow.
“Our agents act across Salesforce, Gong, Google Drive, and more, on behalf of every customer. Scalekit behind the scenes meant we can keep adding tools without ever rebuilding how credentials or tool calling work.”
Venu Madhav Kattagoni
Head of Engineering / Von
FAQs
Frequently Asked Questions
Does the agent access Google Photos as the user or through a shared service account?
As the user. Each user signs in to Google Photos once, and Scalekit stores and refreshes their tokens. Albums and media the agent creates are attributed to that user in your audit trail, not a shared service account.
Where is the Google Photos OAuth token stored?
In Scalekit's managed AES-256 token vault, namespaced per tenant. Refresh is automatic. Revocation is a single dashboard action. Credentials never appear in prompts, logs, or LLM context.
Can I limit what the agent does in Google Photos?
Yes. Filter by tool name in listScopedTools to expose only what you want, for example the read and Picker tools without the album write tools. Scalekit also enforces scope checks before every API call.
What happens when a user revokes Google Photos access?
The connection is invalidated on the next tool call. Subsequent requests for that user fail closed with a clear error. Other users in the tenant remain unaffected. The event is logged for audit.
Can the agent see a user's whole Google Photos library?
No. Since March 2025, Google limits the Photos API to albums and media your app created or uploaded. To work with other photos, googlephotos_create_picker_session lets the user pick items from their full library, and googlephotos_list_picker_media_items returns what they picked.
Start in your coding agent
Up and running in one command
Install the Scalekit skill in your editor of choice. Connector, auth, tools, prompt, all wired up
Claude Code REPL
/plugin marketplace add scalekit-inc/claude-code-authstack
/plugin install agentkit@scalekit-auth-stack
Cursor Code REPL
# ~/.cursor/mcp.json
{
""mcpServers"": {
""googlephotos"": {
""url"": ""https://mcp.scalekit.com/googlephotos"",
""headers"": { ""Authorization"": ""Bearer $SCALEKIT_TOKEN"" }
}
}
}
Codex Code REPL
# ~/.codex/config.toml
[mcp_servers.googlephotos]
url = ""https://mcp.scalekit.com/googlephotos""
auth_env = ""SCALEKIT_TOKEN""
Copilot Code REPL
# .vscode/mcp.json
{
""servers"": {
""googlephotos"": {
""url"": ""https://mcp.scalekit.com/googlephotos"",
""type"": ""http""
}
}
}