OpenSEO Onboarding Flow and AI Agent Skills: A Complete Technical Guide

The OpenSEO onboarding flow guides new users through a credit-limited chat experience backed by a Cloudflare Durable Object named "Sam," which enforces a 7-question free limit while exposing core site tools and credit-metered market research capabilities.

New users entering the every-app/open-seo repository encounter a sophisticated onboarding system designed to demonstrate value while protecting platform resources. This technical guide examines how the platform orchestrates the initial user experience through durable objects, credit enforcement, and a curated set of AI agent skills. Understanding this flow is essential for developers customizing the OpenSEO architecture or integrating similar patterns into their own applications.

Understanding the OpenSEO Onboarding Flow

The onboarding pipeline orchestrates ten discrete steps across the codebase, from initial authentication to message persistence.

Step 1: Authentication and Project Creation

When a user first signs in, src/server.ts authorizes the /agents/* route and ensures an Autumn customer exists for billing purposes. The system automatically creates a default project that will host the onboarding conversation and consume credits.

Step 2: Retrieving Onboarding State

The front-end queries getOnboardingChatState in src/serverFunctions/onboardingChat.ts via GET /onboarding/state to obtain the project's id and current domain. This determines whether the user must complete domain configuration before accessing the chat interface.

Step 3: Domain Configuration

Users submit their site domain and optional location code through saveOnboardingSite, which persists the data via POST /onboarding/site. The locationCode parameter (e.g., 2840 for United States, English) configures regional SEO analysis for subsequent tool calls.

Step 4: Durable Object Instantiation

The client initializes the chat by calling useAgent({ name: projectId }), where the project ID serves as the Durable Object name. The implementation class OnboardingChatAgent in src/server/features/onboarding/OnboardingChatAgent.ts handles WebSocket connections and SQLite persistence through its persistMessages method with built-in retry logic.

Step 5: Credit and Limit Enforcement

Before invoking the LLM, OnboardingChatAgent.onChatMessage validates two constraints defined in src/shared/onboardingChat.ts: the FREE_ONBOARDING_QUESTION_LIMIT (7 questions) and the organization's onboarding credit balance. Exceeding either threshold immediately triggers a subscription prompt rather than processing the query.

Step 6: System Prompt and Tool Construction

The agent calls buildSystemPrompt to assemble an SEO-focused instruction set including fact-sheet markdown. It then invokes buildOnboardingTools from src/server/features/onboarding/onboardingChatTools.ts to construct a ToolSet merging free core utilities with credit-metered market intelligence functions.

Step 7: LLM Streaming and Tool Execution

Using streamText from the ai library, the agent streams responses from the OpenRouter model configured in src/server/lib/openrouter.ts. Tool calls route through DataForSEO via the shared dfsClient, with spend calculated by utilities in src/server/lib/chatAgent.ts and automatically tagged with creditFeature: "onboarding".

Step 8: Conversation Persistence

Each assistant turn appends to this.messages within the Durable Object's SQLite store, ensuring conversation continuity across requests. The generated routing table in src/routeTree.gen.ts exposes /onboarding/ and /onboarding/chat endpoints to wire these server components to the client interface.

AI Agent Skills and Tool Architecture

The OpenSEO agent exposes capabilities through a dynamically constructed ToolSet, explicitly separated into free core utilities and credit-metered market intelligence functions.

Core Site Tools (Free Tier)

Three tools remain available without credit consumption during the onboarding phase:

  • read_website: Fetches plain-text content from user-supplied URLs or the configured domain, enabling Sam to analyze homepage content or competitor pages. Implemented in src/server/features/onboarding/onboardingChatTools.ts (lines 71-90).

  • get_seo_metrics: Retrieves organic traffic estimates, keyword counts, and top-ranking keywords for the user's site within Labs-enabled markets. Available in onboardingChatTools.ts (lines 91-110).

  • research_keywords: Generates keyword opportunities from seed topics, returning search volume, difficulty scores, and intent classification via the KeywordResearchService.research method. Defined in onboardingChatTools.ts (lines 111-152).

Market and Competitor Tools (Credit-Metered)

Advanced capabilities consume onboarding credits when invoked through the onboardingMarketTools.ts module:

  • get_domain_overview: Returns high-level organic footprints including traffic volumes and keyword counts for any domain.

  • get_serp_results: Retrieves live Google SERP data for 1-3 specified keywords, showing top organic results.

  • find_serp_competitors: Identifies top competing domains for a given set of user-provided keywords.

  • get_competitor_keywords: Lists keywords a competitor ranks for, including position, volume, and difficulty metrics.

  • get_backlinks_overview: Summarizes total backlink counts and referring domains (the most expensive operation).

All market tools reside in src/server/features/onboarding/onboardingMarketTools.ts (lines 15-240). Each invocation validates inputs with Zod, calls DataForSEO through the shared dfsClient, and attaches creditFeature: "onboarding" for accurate billing attribution.

Implementation Examples

Fetching the Onboarding Project State

Client applications retrieve the initial configuration to determine if domain setup is required before initializing the chat agent:

// GET /onboarding/state
const { projectId, domain } = await fetch("/onboarding/state")
  .then(r => r.json());
// projectId serves as the durable object name for subsequent chat calls

Configuring Site Domain and Location

Submit the project configuration before initiating the chat to ensure the agent can analyze the correct property:

await fetch("/onboarding/site", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    projectId: "proj_123",
    domain: "example.com",
    locationCode: 2840 // United States, English
  })
});

Initializing the Chat Agent

Connect to the Durable Object using the project ID as the unique identifier:

import { useAgent } from "@cloudflare/ai-chat";

const chat = useAgent({ name: projectId });
const response = await chat.sendMessage("What SEO opportunities do I have?");

Summary

  • The OpenSEO onboarding flow combines automatic project creation, domain configuration, and credit-enforced chat limits to guide new users through a guided SEO consultation.
  • Seven free questions (FREE_ONBOARDING_QUESTION_LIMIT) are permitted before requiring credits, enforced within OnboardingChatAgent.onChatMessage.
  • Core site tools (read_website, get_seo_metrics, research_keywords) execute without credit consumption via src/server/features/onboarding/onboardingChatTools.ts.
  • Market tools require onboarding credits and route through DataForSEO with automatic creditFeature: "onboarding" tagging in src/server/features/onboarding/onboardingMarketTools.ts.
  • All conversation state persists in Cloudflare Durable Objects with SQLite storage, defined in src/server/features/onboarding/OnboardingChatAgent.ts.

Frequently Asked Questions

How many free questions does OpenSEO allow during onboarding?

OpenSEO enforces a strict limit of seven free questions per new user, defined by the constant FREE_ONBOARDING_QUESTION_LIMIT in src/shared/onboardingChat.ts. After this threshold is exceeded, the OnboardingChatAgent checks the organization's onboarding credit balance before processing additional queries.

What happens when a user exhausts their onboarding credits?

When the free question limit is exceeded or the credit balance reaches zero, the OnboardingChatAgent immediately returns a subscription upgrade prompt instead of invoking the LLM or executing tools. This check occurs within the onChatMessage method before any streaming begins.

Which AI agent skills require credits to use?

While read_website, get_seo_metrics, and research_keywords remain free, all market intelligence tools—including get_domain_overview, get_serp_results, find_serp_competitors, get_competitor_keywords, and get_backlinks_overview—consume credits from the onboarding pool when invoked against DataForSEO.

Where is the onboarding chat state persisted?

The conversation history and user metadata persist in a Cloudflare Durable Object named after the project ID, implemented in src/server/features/onboarding/OnboardingChatAgent.ts. The class uses an internal SQLite store (this.messages) with retry logic handled by the persistMessages method, ensuring durability across edge locations.

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 →