# Reading these docs as an agent

Most readers of this site are people. An increasing share are not: coding
agents and LLMs read documentation on a developer's behalf before that
developer writes a line of integration code. If what they read is stale,
incomplete or expensive to parse, the integration comes out wrong — and the
developer experiences that as *SEON is hard to integrate*.

This page is the contract for those readers. Everything below is a build
output of this repository, regenerated on every merge.

{% callout type="note" title="Why this is cheap for us and not for everyone" %}
Our source of truth is already Markdown. Serving Markdown to an agent is a
file copy. Sites whose source is HTML have to convert back to Markdown at the
edge to offer the same thing — Cloudflare built a whole network-layer product
to do exactly that. Being Markdown-native means we skip that component.
{% /callout %}

## Getting a page as Markdown

Every page is published at three URLs: one for people, two for agents.

| Purpose | URL shape | Example |
|---|---|---|
| Human-readable page | `<path>.html` | `/integration/orchestration.html` |
| Markdown, sibling path | `<path>.md` | `/integration/orchestration.md` |
| Markdown, appended index | `<path>/index.md` | `/integration/orchestration/index.md` |

Two Markdown conventions exist because agents guess differently. Appending
`/index.md` to a URL is the more widely adopted convention; the sibling `.md`
is what a static site naturally produces. Both serve identical bytes, so it
does not matter which one an agent tries first.

The Markdown is the source file with its front matter stripped — no
navigation, no scripts, no styling, no hydration payload. Just the page.

## Content negotiation

The canonical URL also answers to an `Accept` header, so an agent that already
holds a link does not need to know our path conventions:

```bash
curl https://docs.seon.dev/integration/orchestration \
  -H "Accept: text/markdown"
```

{% callout type="warning" title="This part is a serving change, not a content change" %}
The `.md` files above are static build artifacts — they exist as soon as the
site is deployed. Content negotiation is different: it needs the web server or
CDN in front of the site to inspect the request and pick a representation.
That is configuration, not documentation, and it is the one piece of this page
that cannot be satisfied by writing more Markdown.
{% /callout %}

Any response that varies on the request header **must** say so, or a shared
cache will serve Markdown to a browser and HTML to an agent:

```nginx
# Serve the Markdown twin when the client asks for it.
location ~ ^/(?<page>.+?)/?$ {
    if ($http_accept ~* "text/markdown") {
        rewrite ^ /$page.md last;
    }
    try_files /$page.html /$page/index.html =404;
}

location ~ \.md$ {
    add_header Content-Type "text/markdown; charset=utf-8";
    add_header Vary "Accept";
}
```

## Discovery: llms.txt

Agents need to find pages before they can read them. The build emits three
indexes, following the [llmstxt.org](https://llmstxt.org/) convention.

| File | Contents | Use |
|---|---|---|
| `/llms.txt` | Every page, grouped by section, with descriptions | Start here |
| `/<section>/llms.txt` | One section only | Pull a single product without the rest |
| `/llms-full.txt` | The entire corpus inline | Bulk ingestion, vectorisation, offline use |

The root index looks like this:

```text
# SEON Docs

> Documentation for SEON's fraud prevention, AML and identity verification
> platform — API reference, SDK integration guides and knowledge base.

## Integration

- [Orchestration](/integration/orchestration.md): Running IDV, liveness and
  proof of address inside a configurable workflow.
```

## Pages we do not want agents to read

Not every live page is a page we still recommend. Legacy integration paths stay
published because existing customers have them bookmarked, but an agent that
learns from them will confidently recommend the wrong approach to somebody
starting today.

Marking a page deprecated in its front matter removes it from every agent
surface:

```yaml
---
title: Legacy IDV session endpoints
status: deprecated
---
```

A deprecated page still renders, and its Markdown twin is still written so
direct links resolve. But it is excluded from `llms.txt`, excluded from
`llms-full.txt`, and disallowed in `robots.txt`.

{% callout type="important" title="This is the second axis of the disclosure config" %}
The pipeline's configuration layer already decides **what is public and what is internal**.
Deprecation is the same mechanism on a second axis: **what is current and what is superseded**.
Both matter to an agent, and only one of them was obvious before we started
writing docs for machines.
{% /callout %}

## What this costs, measured

The Orchestration integration page, fetched three ways and tokenised with
`cl100k_base`:

| Source | Tokens | Relative |
|---|---:|---:|
| Live `docs.seon.io` page, as served | 60,281 | 13.2× |
| This site's rendered HTML | 26,232 | 5.8× |
| This site's Markdown | 4,551 | 1× |

The middle row is worth noticing. Even a clean, purpose-built HTML page costs
roughly six times what the Markdown costs, because HTML is markup-dense and
tokenises badly. Serving Markdown is not a marginal optimisation over serving
better HTML — it is a different order of magnitude.

On the live site the gap is wider still: roughly half of a knowledge-base page
is a JSON hydration payload duplicating content the agent already received.

## Summary for implementers

Adding the agent surface to a Markdown-native docs site is four things, and
only one of them is content:

1. **Build** — emit `<path>.md` and `<path>/index.md` beside every HTML page
2. **Build** — emit `/llms.txt`, `/<section>/llms.txt` and `/llms-full.txt`
3. **Serve** — content negotiation on `Accept: text/markdown`, with `Vary: Accept`
4. **Content** — front matter that marks deprecated pages, plus this page

Items 1, 2 and 4 live in this repository. Item 3 lives in the web server
config, and is the only part that cannot ship as Markdown.
