# AI-agent support

> Opt-in features that help AI agents and automated tools discover and use your site content, including Markdown output, alternate links in HTML, and llms.txt.

---

LLMS index: [llms.txt](/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/google/docsy/issues/2614

## Features

When your site 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)**: alternate links and a hidden in-body directive
  lead agents to each page's Markdown version and to `llms.txt`.
- **View Markdown**: page meta area includes a **View Markdown** link to the
  Markdown version of the page.
- **[`llms.txt`](#llms-txt)**: per-language site index of links to Markdown
  content.

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

## Enable Markdown output {#markdown-output}

Hugo comes with several [built-in output formats][], including `markdown`. 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>


### Opt pages 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 site 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]
---
...
```

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

The `llms.txt` format is a simple text format for listing machine-readable links
to site content. It is designed to be easy for agents to discover and parse, and
to complement the richer but more complex Markdown outputs. To learn more, see
[llmstxt.org][].

Docsy generates an `llms.txt` index at each language's site root, and includes
links to the home page, main menu pages, and Markdown alternates where they
exist. To enable it, add `LLMS` to the Hugo [outputs][] configuration for the
home page. For example:

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

For an example of the generated `llms.txt` for this site, see
[/llms.txt](/llms.txt).

## Discovery

Agents find your Markdown content through:

- **Alternate links**: page HTML headers include `rel="alternate"` links to the
  Markdown version of the page.
- **In-body directive**: when `llms.txt` is enabled, each page body opens with a
  visually-hidden directive pointing agents to the language's `llms.txt` index
  and, when the page has one, its Markdown version. Sites that override the
  theme's `baseof` templates need to call the `llms-directive.html` partial
  themselves.

## Customize output

Docsy renders Markdown output via [layouts/all.md][] and generates `llms.txt`
via `layouts/index.llms.txt`. You can override these defaults at several levels:

- **Per kind** — Add templates such as `home.md` or `_default/single.md` under
  `layouts/` in your project to tailor Markdown output for specific [Hugo
  kinds][].
- **Per shortcode** — Add [output-format-specific shortcode templates][sof] to
  project-local shortcodes so they render Markdown-friendly content when
  appropriate. For example, this site's [readfile.markdown.md][] is the
  Markdown-output variant of the theme's `readfile` shortcode.
- **Per page** — Provide page-specific content or structure for high-value pages
  that need a curated agent-facing view.

## 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 score][] online report 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).

[afdocs]: https://afdocs.dev/
[built-in output formats]: https://gohugo.io/configuration/output-formats/
[experimental]: /project/about/changelog/#experimental
[Hugo kinds]: https://gohugo.io/templates/types/
[layouts/all.md]: https://github.com/google/docsy/blob/main/theme/layouts/all.md
[readfile.markdown.md]:
  https://github.com/google/docsy/blob/main/docsy.dev/layouts/_shortcodes/readfile.markdown.md
[llmstxt.org]: https://llmstxt.org/
[OpenTelemetry agent score]:
  https://buildwithfern.com/agent-score/company/opentelemetry
[outputs]: https://gohugo.io/configuration/outputs/
[sof]: https://gohugo.io/templates/shortcode/
