# 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**: page HTML headers include `rel="alternate"` links to the
  Markdown version of the page.
- **View Markdown**: page meta area includes a **View Markdown** link to the
  Markdown version of the page.
- **[`llms.txt`](#llms-txt)**: site-root file listing.

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.157.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 `llms.txt` at the 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).

## 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 emit Markdown-friendly content when
  appropriate.
- **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:

- [OpenTelemetry agent score][] online report

- An AFDocs scorecard for this site:

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

  ```text
  <p>Running in docsy.dev&hellip;</p>
  <h1 id="agent-friendly-docs-scorecard">Agent-Friendly Docs Scorecard<a class="td-heading-self-link" href="#agent-friendly-docs-scorecard" aria-label="Heading self-link"></a></h1>
  <p>http://localhost:1313 · 4/26/2026, 5:43:59 AM</p>
  <p>Overall Score: 100 / 100 (A+)</p>
  <p>Category Scores:
  Content Discoverability              100 / 100 (A+)
  Markdown Availability                100 / 100 (A+)
  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+)</p>
  <p>Check Results:</p>
  <pre><code>Content Discoverability
    PASS  llms-txt-exists                llms.txt found at 1 location(s)
    PASS  llms-txt-valid                 llms.txt follows the proposed structure (H1, blockquote, heading-delimited link sections)
    PASS  llms-txt-size                  llms.txt is 1,131 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             llms.txt directive found in all 13 pages, near the top of content
  
  Markdown Availability
    PASS  markdown-url-support           13/13 pages support .md URLs (100%)
    PASS  content-negotiation            13/13 pages support content negotiation (100%)
  
  Page Size and Truncation Risk
    PASS  rendering-strategy             All 13 pages contain server-rendered content
    PASS  page-size-markdown             All 13 pages under 50K chars (median 2K, max 9K)
    PASS  page-size-html                 All 13 pages convert under 50K chars (median 2K, 0% boilerplate)
  
  Content Structure
    PASS  tabbed-content-serialization   No tabbed content detected across 13 pages
    PASS  section-header-quality         No tabbed content found; header quality check not applicable
    PASS  markdown-code-fence-validity   All 1 code fences properly closed across 14 pages
  
  URL Stability and Redirects
    PASS  http-status-codes              All 13 pages return proper error codes for bad URLs
    PASS  redirect-behavior              No redirects detected across 13 pages
  
  Observability and Content Health
    PASS  cache-header-hygiene           All 14 endpoints have appropriate cache headers
  
  Authentication and Access
    PASS  auth-gate-detection            All 13 pages are publicly accessible
    SKIP  auth-alternative-access        All docs pages are publicly accessible; no alternative access paths needed
  </code></pre>
  <p>Full spec: <a href="https://agentdocsspec.com/spec/">https://agentdocsspec.com/spec/</a></p>

  ```

  </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/layouts/all.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-templates/#output-format-specific-templates-shortcode-templates
