# How the SAM AI Agent Assists Users in OpenSEO: Architecture and Capabilities

> Discover how the SAM AI agent enhances OpenSEO with its conversational SEO assistance architecture. Learn its capabilities and credit-aware research features.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: architecture
- Published: 2026-08-15

---

**The SAM (Search-Assistant Machine) AI agent is a conversational SEO assistant built on Cloudflare Durable Objects that helps users perform credit-aware research inside OpenSEO by leveraging a system prompt "soul," persistent memory blocks, and a full MCP toolset.**

The SAM (Search-Assistant Machine) AI agent serves as the intelligent core of the OpenSEO application, transforming complex SEO research into natural conversations. Built on Cloudflare's Durable Objects architecture and the Think framework according to the every-app/open-seo source code, this in-app chatbot bridges raw data APIs and actionable insights. This article examines exactly how SAM assists users through its persistent memory, MCP tool integration, and credit-aware billing system.

## Core Architecture: Durable Objects and Session Isolation

### The SamChatAgent Durable Object

SAM is implemented as a **Cloudflare Durable Object** (`DO`) named `SamChatAgent` that extends the **Think** framework. Each chat session instantiates one DO, identified by a unique session ID passed by the client via `useAgent({ name: sessionId })`.

Before any WebSocket or HTTP connection reaches the agent, the Worker authorizes the request on the `/agents/*` route defined in [`src/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server.ts).

Source: [[`src/server/features/sam/SamChatAgent.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/sam/SamChatAgent.ts)](https://github.com/every-app/open-seo/blob/main/src/server/features/sam/SamChatAgent.ts)

### Session Lifecycle Management

The `SamSessionRepository` class in [`src/server/features/sam/SamSessionRepository.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/sam/SamSessionRepository.ts) persists session metadata to the `sam_sessions` table. When a new conversation starts, the system auto-derives a session title from the first user message using `deriveTitle`.

To maintain session hygiene, SAM "touches" the session on every successful response. Users can also rewind conversations via a `POST …/rewind` endpoint, which safely cancels any in-flight turn before removing messages from history.

## The System Prompt: Configuring SAM's "Soul"

### Building the Identity Block

On every turn, SAM constructs a read-only identity block through `buildSoulPrompt` located in [`src/server/features/sam/samSystemPrompt.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/sam/samSystemPrompt.ts). This "soul" prompt defines:

- **Role and tone:** Professional SEO researcher persona
- **Project context:** Active project details including name, domain, target market, and language
- **Policy constraints:** No emojis, no unsupported metric claims, and no product-pitching

This approach ensures consistent personality while dynamically injecting current project state into the conversation context.

## Persistent Context: Memory and Research Logs

SAM maintains state across turns using **writable context blocks** backed by the `sam_project_memory` table (schema defined in [`src/db/sam.schema.ts`](https://github.com/every-app/open-seo/blob/main/src/db/sam.schema.ts)).

### The Memory Block

The **memory** block stores durable facts about the project—business positioning, confirmed competitors, and strategic notes. This data persists across all sessions belonging to the same project, allowing SAM to recognize users and recall previous discussions regardless of which chat window they open.

### The Research Log Block

The **research_log** block maintains a dated, one-line summary of completed research arcs. SAM uses this log primarily for **credit-gating**, preventing duplicate expensive API calls by checking whether specific research has already been performed for the current project.

These blocks are accessed through context-block providers defined within `SamChatAgent` (lines 40-50).

## Tool Integration: MCP and Free Scraping Utilities

SAM exposes two categories of tools through the handlers in [`src/server/features/sam/samChatTools.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/sam/samChatTools.ts): free site-scraping utilities and adapted MCP tools.

### Free Site Scraping

Every SAM session can discover and read content without spending credits:

- **`map_links`**: Discovers URLs on the project's domain
- **`read_pages`**: Extracts content from up to 10 pages simultaneously

These are defined in the `scrapeTools` function and require no billing authorization.

### Adapted MCP Toolset

All external SEO tools (e.g., `get_domain_overview`, `get_backlinks_profile`, `get_serp_results`) are wrapped via `adaptMcpTool`. This wrapper automatically injects the correct `projectId`, billing context, and authentication headers before calling `instrumentMcpToolHandler` for telemetry and cost tracking.

## Credit-Aware Billing and Turn Management

SAM operates on a **metered turn-based** billing model. In hosted mode, every interaction incurs a `turnCostUsd` charged against the organization's credit balance.

### The beforeTurn Hook

Lines 41-61 of [`SamChatAgent.ts`](https://github.com/every-app/open-seo/blob/main/SamChatAgent.ts) implement the `beforeTurn` lifecycle hook:

1. Calls `checkUsageCreditsDepleted` to verify sufficient balance
2. If credits are depleted, refuses the turn with a friendly error message
3. On successful completion, records expenditure via `trackUsageCreditSpend`

This ensures users cannot accidentally exhaust their budget on expensive keyword or backlink research operations.

## How SAM Assists Users: Practical Workflows

Beyond architecture, SAM delivers specific user assistance through four key workflows:

### 1. Automated Onboarding

When detecting a new project with empty memory, SAM automatically invokes `map_links` and `read_pages` to ingest the site, synthesize an initial understanding, and present findings to the user for confirmation or correction.

### 2. Real-Time SEO Research

Using adapted MCP tools like `get_domain_keyword_suggestions` and `get_serp_results`, SAM fetches live data and synthesizes it into concise markdown tables, saving users from navigating complex API responses manually.

### 3. Duplicate Spend Prevention

Before executing paid tool calls, SAM consults the `research_log` to identify previously completed research arcs. If similar data exists, SAM prompts the user to confirm a refresh rather than silently re-purchasing the same intelligence.

### 4. Cross-Session Context Preservation

Results written to `memory` and `research_log` persist across chat turns and even across different browser sessions. A user can start research on Monday and resume Wednesday with SAM recalling exactly what was discovered.

## Working with SAM: Implementation Examples

### Creating a New Session

```typescript
import { SamSessionRepository } from '@/server/features/sam/SamSessionRepository';
import { SamChatAgent } from '@/server/features/sam/SamChatAgent';

// Persist session metadata
const session = await SamSessionRepository.create({
  projectId,
  userId,
  title: 'New chat',
});

// session.id becomes the Durable Object name
const samAgent = new SamChatAgent(); // Cloudflare instantiates the DO automatically

```

*Source: [[`SamSessionRepository.ts`](https://github.com/every-app/open-seo/blob/main/SamSessionRepository.ts)](https://github.com/every-app/open-seo/blob/main/src/server/features/sam/SamSessionRepository.ts)*

### Sending a Message from the Client

```typescript
await fetch(`/agents/${sessionId}`, {
  method: 'POST',
  body: JSON.stringify({ 
    role: 'user', 
    parts: [{ type: 'text', text: 'Give me keyword ideas for my blog.' }] 
  }),
  headers: { 'Content-Type': 'application/json' },
});

```

The Worker routes `/agents/*` to the corresponding `SamChatAgent` instance defined in [`src/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server.ts).

### Calling an MCP Tool Inside the Agent

```typescript
// Example: Domain overview with automatic context injection
const result = await getDomainOverviewTool({
  projectId,  // injected by adaptMcpTool
  domain: 'example.com',
});

```

The `adaptMcpTool` wrapper handles authentication and billing context automatically.

### Free Site Scraping Sequence

```typescript
// Map the project domain automatically
const map = await this.tools.map_links({});
// Read first 10 discovered pages
const pages = await this.tools.read_pages({ 
  urls: map.urls.slice(0, 10) 
});

```

These calls consume zero credits while providing comprehensive site context.

## Summary

- **SAM** is a Durable Object-based AI agent extending Cloudflare's Think framework, providing isolated, persistent chat sessions for each OpenSEO project.
- **Context persistence** is achieved through writable memory and research_log blocks stored in `sam_project_memory`, enabling continuity across sessions.
- **Tool integration** combines free scraping utilities (`map_links`, `read_pages`) with credit-metered MCP tools adapted via `adaptMcpTool`.
- **Billing protection** implemented in `beforeTurn` hooks prevents overspending by checking `checkUsageCreditsDepleted` before expensive operations.
- **Source files:** Core logic resides in [`src/server/features/sam/SamChatAgent.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/sam/SamChatAgent.ts), [`samSystemPrompt.ts`](https://github.com/every-app/open-seo/blob/main/samSystemPrompt.ts), [`samChatTools.ts`](https://github.com/every-app/open-seo/blob/main/samChatTools.ts), and [`SamSessionRepository.ts`](https://github.com/every-app/open-seo/blob/main/SamSessionRepository.ts).

## Frequently Asked Questions

### What makes SAM different from a standard ChatGPT integration?

SAM is purpose-built for SEO workflows within OpenSEO. Unlike generic chatbots, SAM maintains persistent project memory in `sam_project_memory`, automatically adapts MCP tools with correct billing context, and prevents duplicate credit spending through its research_log tracking. It runs as a Cloudflare Durable Object ensuring stateful, low-latency connections without managing external conversation history.

### How does SAM handle billing and credit limits?

Every turn is metered via `turnCostUsd` against the organization's balance. The `beforeTurn` hook in [`SamChatAgent.ts`](https://github.com/every-app/open-seo/blob/main/SamChatAgent.ts) (lines 41-61) calls `checkUsageCreditsDepleted` before executing any paid tool. If credits are insufficient, SAM returns a friendly refusal message immediately, preventing accidental overages on expensive backlink or SERP API calls.

### Can SAM access my website content without using credits?

Yes. SAM includes two free tools—`map_links` and `read_pages`—that discover and read up to 10 pages of your site without consuming credits. These are implemented in [`samChatTools.ts`](https://github.com/every-app/open-seo/blob/main/samChatTools.ts) and automatically trigger during onboarding when a new project lacks historical memory.

### How does SAM remember information between chat sessions?

SAM writes durable facts to the **memory** block and completed research summaries to the **research_log** block, both stored in the `sam_project_memory` table. These blocks are shared across all sessions for the same project, enabling SAM to recognize returning users and recall previous research regardless of which browser or device they use.