# AI-agent support

> Help AI agents discover and use your content with Markdown versions of your pages and an llms.txt per site.

---

Site [llms.txt](/fr/llms.txt)

---

> [!NOTE] Early evaluation
>
> Features described in this page are [experimental][], and are useful for early
> adoption and evaluation. Output details and validation coverage may change in
> future releases. To track the phased evolution of the agent-support feature,
> see [Improve support for AI-agent doc consumption #2614][#2614].

[#2614]: https://github.com/docsy/docsy/issues/2614

## Features

When your project opts in, these are the user-facing and machine-readable
behaviors Docsy enables:

- **[Markdown output format](#markdown-output)** support. Your project's
  `outputs` configuration controls which page kinds publish Markdown.
- **[Discovery](#discovery)**: how agents find Markdown versions and `llms.txt`.
- **View Markdown**: page meta area includes a **View Markdown** link to the
  Markdown version of the page.
- **[`llms.txt`](#llms-txt)**: a per-[site][] overview linking the site's
  Markdown content.

The remainder of this page explains how to enable each feature, and discusses
[validation and metrics](#validation-and-metrics) supported with examples.

## Markdown output

Hugo comes with several [built-in output formats][output formats], including
`markdown`.

Docsy provides the `markdown` template that Hugo uses to output a Markdown
version of a page, at `index.md` beside its `index.html`. The Markdown version
includes:

- Page title and description
- A link to the [site][]'s [`llms.txt`](#llms-txt), when the site publishes one
- Page content, with shortcodes expanded
- The list of child pages, if any

A shortcode without a Markdown variant emits its HTML there; for how to add one,
see [Shortcodes][shortcode-md-variants].

### Enabling {#enabling-markdown-output}

To enable Markdown output, add `markdown` to the Hugo [outputs][] configuration
for the page kinds you want to support. For example:



   <ul class="nav nav-tabs" id="tabs-0" role="tablist">
  <li class="nav-item">
      <button class="nav-link disabled"
          id="tabs-00-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-00" role="tab"
          aria-controls="tabs-00-00" aria-selected="false">
        Configuration file:
      </button>
    </li><li class="nav-item">
      <button class="nav-link active"
          id="tabs-00-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-01" role="tab"
          data-td-tp-persist="yaml" aria-controls="tabs-00-01" aria-selected="true">
        hugo.yaml
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-00-02-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-02" role="tab"
          data-td-tp-persist="toml" aria-controls="tabs-00-02" aria-selected="false">
        hugo.toml
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-00-03-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-03" role="tab"
          data-td-tp-persist="json" aria-controls="tabs-00-03" aria-selected="false">
        hugo.json
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-0-content">
    <div class="tab-body tab-pane fade"
        id="tabs-00-00" role="tabpanel" aria-labelled-by="tabs-00-00-tab" tabindex="0">
        
    </div>
    <div class="tab-body tab-pane fade show active"
        id="tabs-00-01" role="tabpanel" aria-labelled-by="tabs-00-01-tab" tabindex="0">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">outputs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">home</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">HTML, markdown]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">page</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">HTML, markdown]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">section</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">HTML, RSS, print, markdown]</span><span class="w">
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-00-02" role="tabpanel" aria-labelled-by="tabs-00-02-tab" tabindex="0">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="p">[</span><span class="nx">outputs</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">home</span> <span class="p">=</span> <span class="p">[</span> <span class="s2">&#34;HTML&#34;</span><span class="p">,</span> <span class="s2">&#34;markdown&#34;</span> <span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">page</span> <span class="p">=</span> <span class="p">[</span> <span class="s2">&#34;HTML&#34;</span><span class="p">,</span> <span class="s2">&#34;markdown&#34;</span> <span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">section</span> <span class="p">=</span> <span class="p">[</span> <span class="s2">&#34;HTML&#34;</span><span class="p">,</span> <span class="s2">&#34;RSS&#34;</span><span class="p">,</span> <span class="s2">&#34;print&#34;</span><span class="p">,</span> <span class="s2">&#34;markdown&#34;</span> <span class="p">]</span>
</span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-00-03" role="tabpanel" aria-labelled-by="tabs-00-03-tab" tabindex="0">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;outputs&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;home&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;HTML&#34;</span><span class="p">,</span> <span class="s2">&#34;markdown&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;page&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;HTML&#34;</span><span class="p">,</span> <span class="s2">&#34;markdown&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;section&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;HTML&#34;</span><span class="p">,</span> <span class="s2">&#34;RSS&#34;</span><span class="p">,</span> <span class="s2">&#34;print&#34;</span><span class="p">,</span> <span class="s2">&#34;markdown&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div>
    </div>
</div>


### Opting out {#opt-pages-out}

> [!TIP]
>
> By default, Hugo’s `outputs` map (whether in multi-file site config or page
> front matter) is a **full replacement** for each page kind, not a merge [^1].
> When you add `markdown`, keep every format your project already relies on --
> for example `RSS` and `print` on sections as is shown in the examples above.

[^1]:
    This is contrary to the documented Hugo behavior for front-matter
    configuration, but it is confirmed with our testing as of Hugo 0.158.0.

To opt pages out of Markdown output, set `outputs` in page front matter to
`HTML` only, or whatever your page's default output formats are while excluding
`markdown`. For example:

```yaml
---
title: HTML-only test page
outputs: [HTML]
---
...
```

## `llms.txt` files {#llms-txt}

An `llms.txt` file is a short overview (in Markdown) of the content under its
URL path. Agents use it to discover the content rooted at that path. For
details, see the [llms.txt proposal][llmstxt.org].

Docsy defines an `LLMS` [output format][] and a template that renders
`llms.txt`, one per [site][]. The file links to the following, each at the
target's Markdown version when available, otherwise its HTML version:

- A _site index_ consisting of the following list:
  - [site root][]
  - Main menu entries
- A _documentation index_ consisting of the site's top-level docs sections
- The [project][]'s [sites][site], by language, this one included

This organization is intended for rooted `llms.txt` files, not arbitrary
sections.

### Enabling {#enabling-llms-txt-output}

To enable `llms.txt` generation for every [site root][] (a practice Docsy
recommends), add `LLMS` to the Hugo `home` [outputs][] configuration. For
example:

```yaml
outputs:
  home: [HTML, markdown, LLMS]
  page: [HTML, markdown]
  section: [HTML, RSS, print, markdown]
```

> [!IMPORTANT]
>
> For a [doc-rooted site][], see the [doc-rooted `llms.txt`
> setup][doc-rooted-agent-support] instead.

For this site's `llms.txt`, see
[`/fr/llms.txt`](</fr/llms.txt>).

## Discovery

Agents find your Markdown content through:

- **Alternate links**: page heads include `rel="alternate"` links to the
  Markdown version of the page.
- **`describedby` link**: when the site publishes `llms.txt`, page heads include
  a `rel="describedby"` link to it, as the [llms.txt proposal][llmstxt.org] (v2)
  recommends. Projects that override the theme's `head.html` partial need to add
  the link themselves.
- **In-body directive**: when the site publishes `llms.txt`, each page body
  opens with a visually-hidden directive pointing agents to it and, when the
  page has one, its Markdown version. Projects that override the theme's
  `baseof` templates need to call the [`llms-directive.html`][] partial
  themselves.

## Customize output

Docsy's templates for the two outputs are:

- [`layouts/all.md`][] ([Markdown output](#markdown-output))
- [`layouts/all.llms.txt`][] ([`llms.txt`](#llms-txt))

Both follow Hugo's [template lookup rules][lookup], so your project's `layouts/`
overrides them. For `llms.txt`, override `all.llms.txt`, or add a template named
for the site root page's kind:

- [`home`][home-tmp-type] for regular sites: `layouts/home.llms.txt` (or
  `index.llms.txt`)
- [`section`][section-tmp-type] for doc-rooted sites: `layouts/section.llms.txt`
  for every section, or `layouts/TYPE/section.llms.txt` for sections of one
  [type][] (`docs`, unless the page sets `type`)

## Server-side support

While outside the scope of Docsy's support, sites can facilitate agent discovery
and access to Markdown content by implementing server-side content negotiation.
For example, honoring `Accept: text/markdown` on the same URL as HTML.

## Validation and metrics

We use [AFDocs][] to assess basic structural support for agent-facing content,
and to validate that generated outputs meet the configured checks. We also
encourage sites to implement their own monitoring and metrics on agent access
patterns—for example logging requests to Markdown URLs or `llms.txt`, and
collecting metrics on their use. For details, see
[Agent-support checks](/project/build/ci-cd/#agent-support-checks).

The `docsy.dev` project contains [AFDocs][] configuration and npm scripts so
maintainers can score a deployed URL against checks that overlap with Docsy’s
agent-support goals, including Markdown URLs, llms.txt, and related categories.

### Scorecard examples

For scorecard examples, see the [OpenTelemetry agent-readiness report][] on
CLOMonitor (CLOMonitor runs AFDocs, one check per category; its
`llms-txt-coverage` result reflects the curated-overview trade-off this site's
checks also make) and the AFDocs scorecard for this site:

<details>
<summary><code>docsy.dev</code> scorecard</summary>

Known gaps in this scorecard are tracked under [#2614][].

```text
Agent-Friendly Docs Scorecard
==============================

http://localhost:1313 · 8/25/2026, 4:17:55 PM

  Overall Score: 96 / 100 (A)

  Category Scores:
    Content Discoverability              100 / 100 (A+)
    Markdown Availability                 57 / 100 (F)
    Page Size and Truncation Risk        100 / 100 (A+)
    Content Structure                    100 / 100 (A+)
    URL Stability and Redirects          100 / 100 (A+)
    Observability and Content Health     100 / 100 (A+)
    Authentication and Access            100 / 100 (A+)

  Check Results:

    Content Discoverability
      PASS  llms-txt-exists                llms.txt found at http://localhost:1313/llms.txt
      PASS  llms-txt-valid                 llms.txt follows the proposed structure (H1, blockquote, heading-delimited link sections)
      PASS  llms-txt-size                  llms.txt is 1,129 characters (under 50,000 threshold)
      PASS  llms-txt-links-resolve         All 13 same-origin links resolve (13 total links)
      PASS  llms-txt-links-markdown        13/13 same-origin links point to markdown content (100%)
      PASS  llms-txt-directive-html        llms.txt directive found in HTML of all 50 sampled pages, near the top of content
      PASS  llms-txt-directive-md          llms.txt directive found in markdown of all 45 sampled pages, near the top of content; 5 had no markdown version

    Markdown Availability
      PASS  markdown-url-support           45/50 sampled pages support .md URLs (90%)
      FAIL  content-negotiation            Server ignores Accept: text/markdown header (0/50 sampled pages return markdown)
            Fix: Your server ignores Accept: text/markdown and returns HTML. Some agents (Claude Code, Cursor, OpenCode) request markdown this way. Configure your server to honor content negotiation.

    Page Size and Truncation Risk
      PASS  rendering-strategy             All 50 sampled pages contain server-rendered content
      PASS  page-size-markdown             All 45 pages under 50K chars (median 4K, max 47K)
      PASS  page-size-html                 All 50 sampled pages under 50K chars (median 54K HTML → 9K markdown (81% boilerplate))
      PASS  content-start-position         Content starts within first 10% on all 50 sampled pages (median 0%)

    Content Structure
      PASS  tabbed-content-serialization   8 tab group(s) across 7 of 50 sampled pages; all serialize under 50K chars
      SKIP  section-header-quality         7 page(s) with tabs found, but no section headers inside tab panels to evaluate
      PASS  markdown-code-fence-validity   All 157 code fences properly closed across 46 pages

    URL Stability and Redirects
      PASS  http-status-codes              All 50 sampled pages return proper error codes for bad URLs
      PASS  redirect-behavior              No redirects detected across 50 sampled pages

    Observability and Content Health
      PASS  cache-header-hygiene           All 51 endpoints have appropriate cache headers

    Authentication and Access
      PASS  auth-gate-detection            All 50 sampled pages are publicly accessible
      SKIP  auth-alternative-access        All docs pages are publicly accessible; no alternative access paths needed

Full spec: https://agentdocsspec.com/spec/
```


</details>

For details on how these checks are configured, see
[Agent-support checks](/project/build/ci-cd/#agent-support-checks).

<!-- prettier-ignore-start -->
[afdocs]: https://afdocs.dev/
[doc-rooted site]: /docs/content/adding-content/#doc-rooted-sites
[doc-rooted-agent-support]: /docs/content/adding-content/#agent-support
[experimental]: /project/about/changelog/#experimental
[home-tmp-type]: https://gohugo.io/templates/types/#home
[`layouts/all.llms.txt`]: https://github.com/docsy/docsy/blob/main/theme/layouts/all.llms.txt
[`layouts/all.md`]: https://github.com/docsy/docsy/blob/main/theme/layouts/all.md
[`llms-directive.html`]: https://github.com/docsy/docsy/blob/main/theme/layouts/_partials/llms-directive.html
[llmstxt.org]: https://llmstxt.org/
[lookup]: https://gohugo.io/templates/lookup-order/
[OpenTelemetry agent-readiness report]: https://clomonitor.io/projects/cncf/open-telemetry#community_agent_readiness
[output format]: https://gohugo.io/quick-reference/glossary/#output-format
[output formats]: https://gohugo.io/configuration/output-formats/
[outputs]: https://gohugo.io/configuration/outputs/
[project]: https://gohugo.io/quick-reference/glossary/#project
[section-tmp-type]: https://gohugo.io/templates/types/#section
[shortcode-md-variants]: /docs/content/shortcodes/#markdown-output-variants
[site]: https://gohugo.io/quick-reference/glossary/#site
[site root]: https://gohugo.io/quick-reference/glossary/#site-root
[type]: https://gohugo.io/content-management/front-matter/#type
<!-- prettier-ignore-end -->
