Core Entry Points for OpenSEO Cloudflare Workers: A Complete Technical Guide

OpenSEO Cloudflare Workers expose three primary entry points—the fetch handler, scheduled handler, and Workflow classes—plus three Durable Object bindings that enable stateful chat agents and audit scratchpads.

The OpenSEO codebase (every-app/open-seo) is architected as a modern Cloudflare Workers application that handles real-time SEO audits, rank tracking, and AI-powered chat agents. Understanding its entry points is essential for contributors, operators, and anyone extending the platform. This guide maps every invocation path with precise file references from the source code.

The Three Primary Entry Points

Cloudflare Workers runtime invokes OpenSEO through handlers exported from src/server.ts. These form the backbone of the application's execution model.

fetch Handler: HTTP Request Routing

The fetch handler (src/server.ts#L29-L78) processes every HTTP request hitting the worker. It multiplexes traffic across:

  • API calls – REST endpoints for project management
  • Web UI requests – Dashboard and application frontend
  • /agents/* endpoints – Durable Object chat routing (WebSocket upgrade)
  • OAuth flow – Authentication callbacks
  • Specialized handlers – GDPR erasure, Autumn webhook, and MCP route forwarding
// src/server.ts — simplified fetch handler structure
export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const url = new URL(request.url);
    
    // Route to Durable Object chat agents
    if (url.pathname.startsWith('/agents/')) {
      // WebSocket upgrade to OnboardingChatAgent or SamChatAgent
    }
    
    // API and UI routing
    // ...
    
    return new Response('Not Found', { status: 404 });
  }
} satisfies ExportedHandler<Env>;

scheduled Handler: Cron-Triggered Background Jobs

The scheduled handler (src/server.ts#L93-L132) executes on Cloudflare Cron triggers defined in wrangler.jsonc. Two schedules drive operations:

Cron Pattern Purpose
*/5 * * * * Every 5 minutes: stale-audit reconciliation, rank-check scheduling
17 3 * * * Daily at 03:17 UTC: OAuth KV garbage collection
// Simulated local invocation of the scheduled handler
import server from './src/server';

await server.scheduled(
  { cron: "*/5 * * * *", scheduledTime: Date.now() } as ScheduledController,
  env,
  {} as ExecutionContext
);

Workflow Classes: Long-Running Multi-Step Operations

OpenSEO exports two Workflow classes from src/server.ts (src/server.ts#L80-L88) that Cloudflare Workflows orchestrates:

  • SiteAuditWorkflow – Encapsulates multi-stage site crawling and analysis
  • RankCheckWorkflow – Manages distributed rank checking across search engines

Workflows run in isolated execution contexts, surviving individual worker invocations to handle operations that exceed request timeouts.

// Internal invocation from the RankCheckWorkflow scheduler
import { RankCheckWorkflow } from './server/workflows/RankCheckWorkflow';

const workflow = new RankCheckWorkflow();
await workflow.run({
  projectId: 'proj_123',
  keywords: ['seo tools', 'rank tracker'],
  engines: ['google', 'bing']
});

Durable Object Entry Points

Beyond handlers and workflows, OpenSEO registers three Durable Object classes that act as entry points for stateful, long-lived computing.

ONBOARDING_CHAT → OnboardingChatAgent

OnboardingChatAgent (src/server/features/onboarding/OnboardingChatAgent.ts) provides per-project AI strategy chat using the Agents SDK. Each projectId maps to a unique Durable Object instance.

// Client-side WebSocket connection
const ws = new WebSocket(
  'wss://open-seo.example.com/agents/onboarding/proj_123'
);

SAM_CHAT → SamChatAgent

SamChatAgent (src/server/features/sam/SamChatAgent.ts) handles in-app SAM (Search Action Model) chat sessions. Unlike onboarding chat, this creates one instance per chat session rather than per project.

AUDIT_SCRATCHPAD → AuditScratchpad

AuditScratchpad (src/server/features/audit/AuditScratchpad.ts) maintains crawl state for active audits:

  • Frontier – URLs queued for crawling
  • Link edges – Discovered internal/external links
  • Page mirror – Cached page content for analysis

Configuration: How Entry Points Are Wired Together

The wrangler.jsonc configuration binds all entry points declaratively:

Section Purpose Lines
main Points to src/server.ts as the entry module Line 22
workflows Declares SiteAuditWorkflow and RankCheckWorkflow bindings ~22-40
durable_objects Registers the three DO classes with their binding names ~40-58
// wrangler.jsonc — entry point configuration excerpt
{
  "main": "src/server.ts",
  "workflows": [
    {
      "name": "site-audit-workflow",
      "class_name": "SiteAuditWorkflow"
    },
    {
      "name": "rank-check-workflow", 
      "class_name": "RankCheckWorkflow"
    }
  ],
  "durable_objects": {
    "bindings": [
      { "name": "ONBOARDING_CHAT", "class_name": "OnboardingChatAgent" },
      { "name": "SAM_CHAT", "class_name": "SamChatAgent" },
      { "name": "AUDIT_SCRATCHPAD", "class_name": "AuditScratchpad" }
    ]
  }
}

See the complete configuration at wrangler.jsonc.

Entry Point Execution Flow


┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  HTTP Request   │────→│  fetch handler  │────→│  API / UI / DO  │
│  (any client)   │     │  src/server.ts  │     │  agents routing │
└─────────────────┘     └─────────────────┘     └─────────────────┘

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  Cron Trigger   │────→│scheduled handler│────→│ Background jobs │
│  (Cloudflare)   │     │  src/server.ts  │     │  audit/rank/KV  │
└─────────────────┘     └─────────────────┘     └─────────────────┘

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  Internal call  │────→│   Workflow.init │────→│ Multi-step exec │
│  (worker code)  │     │ Site/Rank Check │     │  (survives DO)  │
└─────────────────┘     └─────────────────┘     └─────────────────┘

Summary

  • fetch handler in src/server.ts routes all HTTP traffic including WebSocket upgrades to Durable Objects
  • scheduled handler runs cron jobs for reconciliation, scheduling, and cleanup every 5 minutes and daily
  • Workflow classes (SiteAuditWorkflow, RankCheckWorkflow) enable fault-tolerant, long-running operations
  • Durable Objects provide stateful entry points for chat agents (OnboardingChatAgent, SamChatAgent) and audit state (AuditScratchpad)
  • wrangler.jsonc declaratively binds all entry points for Cloudflare deployment

Frequently Asked Questions

What triggers the OpenSEO scheduled handler to run?

The scheduled handler triggers automatically based on cron patterns in wrangler.jsonc. OpenSEO configures two schedules: every 5 minutes for operational tasks and daily at 03:17 UTC for garbage collection. Cloudflare invokes the handler—no external HTTP request required.

How do OpenSEO Durable Objects maintain state across requests?

Each Durable Object class (OnboardingChatAgent, SamChatAgent, AuditScratchpad) runs in its own isolated V8 isolate with persistent in-memory state. Cloudflare routes requests to the same physical instance based on the object ID (derived from projectId or session ID), enabling WebSocket chat histories and crawl scratchpads to persist beyond single requests.

Can I invoke OpenSEO Workflows from outside the Worker?

No. According to the OpenSEO source code, Workflows are internal entry points invoked only from server-side Worker code. They are not exposed as HTTP endpoints. To trigger a workflow, make an API call that the fetch handler routes to internal workflow-initialization logic.

What's the difference between the two chat Durable Objects?

OnboardingChatAgent creates one instance per projectId for strategy discussions during project setup. SamChatAgent creates one instance per chat session for ongoing in-app assistance. The distinction affects routing logic in the fetch handler and how clients construct WebSocket URLs.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →