> ## Documentation Index
> Fetch the complete documentation index at: https://docs.firstflow.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Use these docs with AI

> How these docs are built for machine retrieval, and the two ways a coding agent consumes them as context, and as an operator through the MCP server.

These docs are written to be read by both people and AI. Every page is a single concept expressed as clean prose with exact field names, runnable examples, and stable internal links the shape a retrieval system can chunk without losing meaning.

There are two distinct ways an AI agent uses FirstFlow. It can **read** the docs as context to write integration code on your behalf, or it can **operate** your workspace directly through the [MCP server](/mcp/overview). This page explains how both work and when to reach for each.

## How it works

Retrieval-augmented assistants don't read a whole site; they fetch the few chunks that match a query and answer from those. That only works if each chunk stands alone. So these docs follow one discipline: each page is one Diátaxis type (explanation, reference, how-to), each H2/H3 restates the mechanism rather than referring to "the method above", and concepts use the same word every time the workspace container is always an **agent**, the shared id is always `sessionId` on the server and `conversationId` in the browser. A chunk retrieved in isolation still carries its full meaning.

On top of that prose, the site exposes machine-readable surfaces an agent can fetch directly:

| Surface           | URL                          | What it is                                                         |
| ----------------- | ---------------------------- | ------------------------------------------------------------------ |
| Per-page Markdown | append `.md` to any docs URL | The raw Markdown source of one page                                |
| Index             | `/llms.txt`                  | A structured list of every page, for an agent to crawl selectively |
| Full corpus       | `/llms-full.txt`             | The entire docs concatenated into one file                         |
| Ask AI            | search box in the top bar    | Natural-language Q\&A answered from the docs, with citations       |

The reading path and the operating path differ in what the agent is allowed to touch. Reading is inert: the agent pulls Markdown into its context window and writes code, and nothing in your FirstFlow workspace changes until you run that code. Operating is live: through MCP the agent calls authenticated tools that list agents, create experiences, and publish real mutations behind a scoped OAuth flow.

```mermaid theme={null}
flowchart TD
  Q["You ask your coding agent<br/>to add FirstFlow"]
  Q --> R["Read path<br/>(context)"]
  Q --> O["Operate path<br/>(MCP)"]

  R --> RM["Fetch /llms.txt,<br/>page.md, Ask AI"]
  RM --> RC["Agent writes integration code<br/>in your repo"]
  RC --> RD["Nothing changes in FirstFlow<br/>until you run it"]

  O --> OA["Scoped OAuth grant"]
  OA --> OT["Agent calls MCP tools:<br/>list agents, create experience, publish"]
  OT --> OL["Live mutations in your workspace"]

  classDef read fill:#1f6f54,stroke:#0c3a2b,color:#fff;
  classDef op fill:#7a3ea8,stroke:#3f1f59,color:#fff;
  classDef neutral fill:#3a3f44,stroke:#16191c,color:#fff;
  class R,RM,RC,RD read;
  class O,OA,OT,OL op;
  class Q neutral;
```

## Reading the docs as context

The fastest way to give a coding agent (Claude Code, Cursor, or any chat assistant) working knowledge of FirstFlow is to feed it the docs and let it write the integration. The integration contract is small and the same in every case: install [`@firstflow/sdk`](/server/overview) on the server, install [`@firstflow/react`](/react/overview) in the browser, [wrap your LLM client](/server/wrap-llm-client) so conversations are observed, and [mount the provider](/react/provider) plus a [widget](/react/widget). The docs describe each of those steps in a single page, so an agent rarely needs more than a handful of chunks.

Give the agent the docs in whichever form fits its tooling:

<Steps>
  <Step title="Point it at the index">
    Paste the URL `https://docs.firstflow.app/llms.txt`. The agent crawls it and pulls only the pages it needs (for example `/server/wrap-llm-client.md` and `/react/provider.md`) rather than the whole corpus.
  </Step>

  <Step title="Or hand it a single page">
    Open the page menu on any docs page and use **Copy page** to copy clean Markdown, or **View as Markdown** to grab the raw `.md`. Paste it into the chat. **Open in ChatGPT / Claude** starts a chat preloaded with that page.
  </Step>

  <Step title="Or let it use Ask AI">
    For a one-off question ("does the provider need an API key in the browser?"), the **Ask AI** box in the top bar answers from the docs with citations no copy-paste.
  </Step>
</Steps>

### What a grounded agent should produce

Because the docs use exact identifiers, a well-grounded agent writes code that matches the real SDK surface. The browser half mounts the provider with `agentId`, the browser-safe `publishableKey` (`pk_live_…`), the authenticated `user`, and a `conversationId` you own:

```tsx theme={null}
import { FirstflowProvider, FirstflowWidget } from "@firstflow/react";

<FirstflowProvider
  agentId="agt_123"
  publishableKey="pk_live_…"
  user={{ id: user.id, email: user.email, traits: { plan: user.plan } }}
  conversationId={conversationId}
>
  <FirstflowWidget />
  {children}
</FirstflowProvider>;
```

The server half wraps the LLM client and tags every observed call with the three identifiers the SDK requires `firstflowAgentId`, `sessionId`, and `userId` reading the secret `FIRSTFLOW_API_KEY` from the environment:

```ts theme={null}
import { OpenAI } from "@firstflow/sdk/openai";

const client = new OpenAI(); // reads FIRSTFLOW_API_KEY from env

await client.chat.completions.create({
  firstflowAgentId: "agt_123",
  sessionId: conversationId, // SAME value as the browser conversationId
  userId: user.id,
  model: "gpt-4o",
  messages,
});
```

The single most common thing to verify in agent-written code is that `sessionId` on the server equals `conversationId` in the browser. That shared id is what links the transcript, the realtime socket, the classifier, and any flow run into one conversation. The SDK strips `firstflowAgentId`, `sessionId`, and `userId` from the request body before it reaches OpenAI or Anthropic, so they never leak to the model. If the agent tags a call with only some of the three, the SDK passes the request through **unobserved** and logs a one-time warning the request still succeeds, but no experience will ever fire from it. See [Wrap your LLM client](/server/wrap-llm-client) for the full contract.

## Operating FirstFlow through MCP

Reading produces code; the [MCP server](/mcp/overview) lets the agent change your workspace. It exposes FirstFlow as a set of authenticated tools a coding agent can call list the agents you can access, inspect and create experiences, and publish them behind a scoped OAuth grant so the agent only gets the permissions you approve.

Use this path when you want the agent to *do* the work, not just describe it: "create a guide experience that fires after the user's first message and walk it through to a result node" becomes a sequence of real tool calls. The available tools and their arguments are catalogued at [MCP tools](/mcp/tools); what each grant can touch is defined by [scopes](/mcp/scopes); and the credentials live behind [API keys](/mcp/api-keys). To connect a coding agent to the server, follow the [MCP quickstart](/mcp/quickstart).

The boundary between the two paths is permission. The reading path needs no credentials and mutates nothing it is safe to point any assistant at the docs. The operating path is gated by OAuth and writes to your workspace, so treat its scopes the way you treat any production access token.

## Specific cases

<AccordionGroup>
  <Accordion title="The agent invented a prop or env var that doesn't exist">
    Ground it harder. Paste the exact reference page [`/react/provider`](/react/provider) for browser props, [`/server/wrap-llm-client`](/server/wrap-llm-client) for the server contract rather than letting it reason from a general description. The provider accepts only `agentId`, `publishableKey`, `user`, `apiUrl`, and `conversationId`; there is no `apiKey` prop in the browser. Browser code uses `publishableKey`; server code reads `FIRSTFLOW_API_KEY` from the environment and never hard-codes it.
  </Accordion>

  <Accordion title="Self-hosting the agent points at the wrong host">
    The defaults assume FirstFlow Cloud (`https://api.firstflow.app`). When [self-hosting](/self-hosting/overview), set the browser provider's `apiUrl` and the server's `FIRSTFLOW_API_BASE_URL` to your own host. Tell the agent your base URL explicitly; it cannot infer it from the docs.
  </Accordion>

  <Accordion title="The agent added a CSS import">
    Remove it. Styles auto-inject through the `@firstflow/react` package's `sideEffects` there is no stylesheet to import. An agent trained on older component libraries often adds one reflexively.
  </Accordion>

  <Accordion title="Stale answers from Ask AI or a cached page">
    The Markdown surfaces (`/llms.txt`, `/llms-full.txt`, and per-page `.md`) reflect the published docs. If an answer looks out of date, fetch the page's `.md` directly to confirm against the current source rather than trusting a cached context window.
  </Accordion>
</AccordionGroup>

## Next

Connect a coding agent to your workspace with the [MCP quickstart](/mcp/quickstart), or hand the docs to your assistant and follow the [integration quickstart](/quickstart) to wire the [provider](/react/provider) and [LLM wrapper](/server/wrap-llm-client).
