What Are Gatekeepers in Cloudflare OS? A Technical Guide to Capability-Based Adapters
Gatekeepers in Cloudflare OS are capability-based adapters that expose external services to AI-driven gadgets through a three-layer architecture of Durable Objects, enforcing fine-grained permissions and audit trails via an ApprovalQueue.
Cloudflare OS—internally codenamed the "Gadgets Workshop"—uses Gatekeepers to safely bridge AI agents with third-party APIs like Google Workspace, GitHub, and Home Assistant. As implemented in the cloudflare/cloudflare-os repository, these components act as secure, auditable intermediaries that translate natural language requests into authenticated API calls while maintaining strict user consent boundaries.
Core Architecture: The Three Layers of Cloudflare OS Gatekeepers
The Gatekeeper system organizes access control into three distinct Durable Object layers, each defined in packages/workshop-shared/src/gatekeeper.ts.
GatekeeperVendor: The Entry Point
The GatekeeperVendor serves as the durable-object entry point for service integration. It handles OAuth initialization, lists available resource types, and can auto-provision accounts. When the Workshop UI needs to display available connectors, it calls GatekeeperVendor.describe() to retrieve metadata including the vendor name, logo, and supported authentication flows.
GatekeeperUser: Account Management
Once a user completes OAuth, the system instantiates a GatekeeperUser durable object representing that specific connected account. This layer surfaces account information, enumerates grantable resources via getGatekeeperClassFor(url), and manages the credential lifecycle. Each connected Google or GitHub account maintains its own GatekeeperUser instance that persists the access tokens and refresh logic.
Gatekeeper: Resource-Specific Access
The Resource Gatekeeper implements the Gatekeeper<Session> interface as a Durable Object facet bound to a specific resource URL—such as https://docs.google.com/document/d/XYZ. This layer exposes the concrete API methods (e.g., listDocuments, sendEmail) through a session RPC that gadgets invoke. Crucially, it routes all read operations through ObservationAuthorizer.authorizeObservation() and queues write operations in the ApprovalQueue for explicit user approval.
Key Types and Interfaces Defined in gatekeeper.ts
The shared API contract in packages/workshop-shared/src/gatekeeper.ts defines the metadata structures that enable type-safe integration:
- VendorDescription: UI metadata including the vendor name, logo URL, tagline, and a boolean flag indicating if the vendor supports sign-in capabilities.
- AccountDescription: Data structure representing a connected account in the UI, potentially declaring a singleton agent or management interface.
- SupportedResource: Declares resource types the vendor can bind, including URL patterns like
https://docs.google.com/*for Google Docs. - ResourceDescription: Metadata returned by resource-specific Gatekeepers containing the URL, title, suggested binding name, and TypeScript type definitions.
- AgentCatalog: A bounded discovery index that exposes reachable objects to the AI agent without requiring full session data retrieval.
Runtime Lifecycle: How Gatekeepers Work in Practice
The execution flow follows a strict six-phase pattern enforced by the Overseer:
- Vendor discovery: The Workshop UI calls
GatekeeperVendor.describe()to enumerate available connectors. - Account connection: The UI invokes
GatekeeperVendor.connectAccount(callback, options), returning an OAuth URL. The callback'scomplete(user, expiresAt)method persists theGatekeeperUserafter authorization. - Resource selection: The system may spawn a configurator iframe via
startResourceConfiguratorto capture the specific resource URL. - Class resolution: The Overseer calls
GatekeeperUser.getGatekeeperClassFor(url)to retrieve the Durable Object class implementingGatekeeper<Session>for that resource type. - Session start: The gadget invokes
Gatekeeper.startSession(approvalQueue)to obtain a session stub providing the concrete API. - Observations and actions: Read operations pass through
ObservationAuthorizer.authorizeObservation(), while writes are submitted viaapprovalQueue.submitAction()and only executed after user approval triggersapplyAction().
// 1. List available vendors (UI side)
const vendors = await gatekeeperVendor.describe();
// 2. Connect a Google account (user clicks “Connect”)
const {url} = await gatekeeperVendor.connectAccount(callback, {scopes: "full"});
window.open(url, "_blank");
// 3. After OAuth completes, callback.complete(user) stores the account.
// The Workshop now has a GatekeeperUser fetcher.
// 4. Resolve a specific resource (e.g. a Google Doc)
const {class: GatekeeperClass, resource} = await gatekeeperUser.getGatekeeperClassFor(
"https://docs.google.com/document/d/XYZ");
// 5. Instantiate the resource Gatekeeper within the Overseer
const gatekeeper = ctx.facets.add(GatekeeperClass, { /* props with credentials */ });
// 6. Start a session for the gadget
const session = await gatekeeper.startSession(approvalQueue);
// 7. Read data (observation)
await observationAuthorizer.authorizeObservation({
description: "Read document title",
resourceId: resource.id,
});
const title = await session.getTitle();
// 8. Request a write (action)
const actionId = await session.createComment({text: "Hello"});
await approvalQueue.submitAction(actionId, {
// ActionDescription describing the write
});
Implementation Examples in the Cloudflare OS Repository
The cloudflare/cloudflare-os monorepo contains several reference implementations demonstrating the Gatekeeper pattern:
packages/gatekeeper-context/README.md: Implements a singleton agent providing a collections library and management UI.packages/gatekeeper-mcp/README.md: Exposes a minimal "MCP" connector demonstrating the simplest possible Gatekeeper implementation.packages/gatekeeper-google/README.md: Production-caliber OAuth integration for Google Workspace, showing real-world token management.packages/gatekeeper-email/README.md: Demonstrates stateless email sending without persistent UI components.
Summary
- Gatekeepers provide capability-based security for AI gadget integration with external APIs.
- The architecture separates concerns into three Durable Object layers: Vendor (service definition), User (account management), and Resource (concrete API access).
- All interactions are audited and permissioned through the
ObservationAuthorizerfor reads and theApprovalQueuefor writes. - The core RPC contracts reside in
packages/workshop-shared/src/gatekeeper.ts. - Concrete implementations follow a six-phase lifecycle from vendor discovery to action execution.
Frequently Asked Questions
What is the primary purpose of Gatekeepers in Cloudflare OS?
Gatekeepers serve as secure intermediaries that expose external services to AI-driven gadgets while enforcing user consent and maintaining audit trails. They prevent unauthorized access by requiring explicit approval for all write operations through the ApprovalQueue.
How does the ApprovalQueue enforce security in Gatekeeper sessions?
When a gadget requests a write operation, the Resource Gatekeeper generates an action identifier and submits it to the ApprovalQueue rather than executing immediately. The Overseer only invokes applyAction() on the Gatekeeper after the user explicitly approves the operation in the Workshop UI, creating a mandatory authorization checkpoint for all state-changing operations.
What distinguishes GatekeeperVendor from GatekeeperUser?
GatekeeperVendor is a singleton Durable Object that handles service-level concerns like OAuth flow initialization and resource type enumeration, while GatekeeperUser represents a specific authenticated instance of that service for one user, managing account-specific tokens and resolving resource URLs to concrete Gatekeeper classes.
Where are the Gatekeeper interfaces defined in the source code?
The central RPC contracts defining GatekeeperVendor, GatekeeperUser, and Gatekeeper<Session> reside in packages/workshop-shared/src/gatekeeper.ts, which also exports the shared type definitions including VendorDescription, AccountDescription, and SupportedResource.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →