Коротко. llms.txt — markdown-файл в корне сайта (/llms.txt) с курируемым оглавлением: заголовок с названием проекта, короткое описание и списки ссылок на самые важные страницы с пояснениями. Это предложение сообщества, а не утверждённый стандарт: читать его никто не обязан. Ставка дешёвая — файл делается за час, ничему не мешает и заодно наводит порядок в описаниях.
Что такое llms.txt простыми словами
Обычная страница сайта — это навигация, баннеры, футер, скрипты, куки-баннер и где-то посередине полезный текст. Всё остальное для машины — шум, который нужно отфильтровать, потратив на это токены и время. Файл llms.txt предлагает другой заход: вы сами, руками, один раз пишете, что у вас есть ценного и куда идти за ответом на конкретный вопрос.
Ключевое слово — курируемый. Это не выгрузка всех URL и не второй sitemap. Это оглавление, которое вы отобрали: два-три десятка страниц, каждая с человеческим пояснением, зачем она нужна.
Полезная аналогия. sitemap.xml — телефонный справочник: полный, машинный, без объяснений. llms.txt — оглавление книги с аннотациями: короткое, читается и человеком, и моделью, и по нему сразу понятно, где что.
- Что файл даёт. Экономию контекста при разборе сайта, управление приоритетом («сначала смотри сюда»), единое место, где описания страниц сформулированы вами, а не сгенерированы из первого абзаца.
- Чего файл не делает. Не влияет на классическое ранжирование в поиске. Не открывает и не закрывает доступ ботам. Не гарантирует цитирование. Не заменяет ни один из существующих файлов.

llms.txt, robots.txt и sitemap.xml: в чём разница
Три файла лежат в одном месте — в корне сайта — и постоянно путаются в головах. Разница простая: robots.txt отвечает на вопрос «куда можно ходить», sitemap.xml — «какие адреса вообще существуют», llms.txt — «что здесь важного и о чём это».
| Файл | Назначение | Формат | Кто читает | Обязателен |
|---|---|---|---|---|
robots.txt | Разрешения и запреты на обход: какие пути каким ботам открыты | Текстовые директивы User-agent / Disallow / Allow | Поисковые роботы, AI-краулеры, сканеры | Нет, но соблюдается де-факто всеми серьёзными ботами |
sitemap.xml | Машинный перечень всех URL, пригодных к индексации, с датами обновления | XML по схеме sitemaps.org | Поисковые системы | Нет, но это устоявшаяся практика с поддержкой у поисковиков |
llms.txt | Курируемое человекочитаемое оглавление смыслов с пояснениями к ссылкам | Markdown: один #, блок описания, разделы ## со списками | LLM-агенты, AI-сканеры, разработческие инструменты | Нет. Предложение сообщества, поддержка не гарантирована |
llms-full.txt | Расширенная версия: полный текст материалов, склеенный в один файл | Markdown, один большой документ | Те же агенты, когда нужен весь контент разом | Нет, и нужен далеко не всем |
Отсюда две типовые ошибки. Первая — пытаться «закрыть» контент через llms.txt: файл не является директивой доступа, отсутствие страницы в нём ничего не запрещает. Вторая — написать красивый llms.txt, оставив AI-краулерам Disallow: / в robots.txt или капчу на входе. Тогда файл просто некому прочитать.
Порядок работ: сначала доступ, потом смыслы. Если AI-краулер заблокирован вrobots.txt, на WAF или антибот-защите,llms.txtне изменит ничего. Проверьте доступ на /robots-checker, разберитесь с User-agent в статье robots.txt и AI-краулеры — и только потом занимайтесь оглавлением.
Работает ли llms.txt: честный статус формата
Это главный вопрос, и на него стоит ответить прямо, без маркетинга.
Статус спецификации
llms.txt — предложение сообщества, опубликованное как открытая спецификация. Оно не проходило через процедуры стандартизации, не является RFC, не входит ни в один утверждённый стандарт и не имеет нормативной эталонной реализации. Формально это соглашение, к которому каждый присоединяется добровольно.
Поддержка со стороны ассистентов
Публичных обязательств уровня «наш краулер читает /llms.txt и учитывает его при ответе» в документации крупных AI-платформ, как правило, нет. Поведение конкретных агентов может меняться без объявления, поэтому любые утверждения вида «формат официально поддерживают такие-то ассистенты» стоит воспринимать критически и перепроверять по первоисточникам — документации самих краулеров.
В логах доступа вы почти наверняка увидите обращения к /llms.txt. Но по User-agent обычно видно, что это SEO-сканеры, чекеры AI-готовности, скрипты разработчиков и исследовательские боты — не всегда ассистент, отвечающий пользователю прямо сейчас.
Как к этому относиться на практике
- Как к дешёвой ставке. Час работы, ноль риска, потенциально ненулевой выигрыш. Это нормальное соотношение для инфраструктурной мелочи.
- Не как к гарантии. Обещать клиенту «попадание в ответы ИИ» через
llms.txtнельзя — проверяемых оснований для такого обещания нет. - Побочная польза, которая работает всегда. Чтобы написать файл, вы обязаны сформулировать: что у нас есть ценного и как описать каждую страницу одной строкой. Эти же формулировки потом идут в
title,description, подводки и анонсы. Работа полезна независимо от того, прочитает файл хоть кто-нибудь или нет. - Как к части набора, а не как к единственной мере. Один файл ничего не решает. Он имеет смысл вместе с открытым доступом для ботов, чистой разметкой и извлекаемым текстом — см. извлекаемость контента для AI.
Правило проверяемости. Из всего, что связано с llms.txt, измеряется ровно три вещи: файл отдаётся с кодом 200, он валиден по структуре, ссылки в нём живы. Всё остальное — вероятностная ставка. Если вам продают «гарантированное цитирование» — просите методику замера.
Формат файла: из чего состоит llms.txt
Формат намеренно примитивный: это markdown, который читается глазами. Порядок блоков фиксированный.
- Заголовок первого уровня —
# Название проекта. Ровно один на файл, первой строкой. Это единственный обязательный элемент. - Блок краткого описания — строка-цитата
> …сразу после заголовка. Одно-три предложения: что за проект, для кого, чем полезен. Формально необязателен, но без него файл теряет половину смысла. - Свободный markdown-текст — абзацы и списки без заголовков. Сюда идут детали: на каких языках контент, что считать первоисточником, какие ограничения. Необязательно.
- Тематические разделы —
## Название раздела, внутри маркированный список ссылок в формате- [Название](абсолютный URL): пояснение. Названия разделов — любые, на любом языке. - Раздел
## Optional— специальный, всегда последний. Означает: эти ссылки можно пропустить, если контекста мало. Туда идёт всё, что приятно иметь, но не критично: блог, архив, changelog, страница «о нас».
Почему ## Optional нельзя переводить
Это служебное имя, а не обычный заголовок. Раздел распознаётся именно по слову Optional. Русское «## Опционально» будет прочитано как ещё одна тематическая секция, и весь смысл «это можно не читать» потеряется. Все остальные заголовки разделов пишите как удобно — хоть «Каталог», хоть «Документация», хоть «Как выбрать».
llms-full.txt: когда расширенная версия оправдана
Если llms.txt — оглавление, то llms-full.txt — сама книга: полный текст материалов, склеенный в один markdown-документ, чтобы агенту не нужно было ходить по ссылкам. Это принципиально другой файл, и путать их не стоит.
- Когда оправдан. Документация продукта, база знаний, API-справочник, свод правил — то, что имеет смысл прочитать целиком и что помещается в разумный объём.
- Когда не оправдан. Интернет-магазин с десятками тысяч карточек, новостная лента, форум. Файл разрастётся до десятков мегабайт, и его никто не станет тянуть.
- Практический ориентир. Держите объём в пределах единиц мегабайт. Если больше — режьте по кластерам:
llms-docs.txt,llms-glossary.txt,llms-how-to.txt— и ссылайтесь на них из основногоllms.txtкак на обычные ресурсы. - Частая ошибка. Делать
llms-full.txtв виде «списка всех URL сайта». Полный перечень адресов — это работаsitemap.xml, дублировать его в другом формате бессмысленно. «Full» здесь про полный текст, а не про полный список.
Примеры llms.txt для трёх типов сайтов
Ниже — три законченных файла, которые можно взять как каркас. Обратите внимание на пояснения после двоеточия: именно по ним принимается решение, идти по ссылке или нет.
SaaS с документацией
Классический случай, для которого формат и придумывался: много структурированной документации, у пользователя конкретный технический вопрос.
# Acme Deploy
> Acme Deploy — сервис непрерывной доставки: сборка из Git, деплой в Kubernetes, откат в один клик. Поддерживает GitHub, GitLab и Bitbucket. Есть бесплатный тариф на один проект.
Документация ведётся на русском и английском, английская версия первична. Все примеры конфигурации проверены на актуальной версии CLI. Вопросы по лимитам и биллингу — в разделе «Тарифы и лимиты».
## Начало работы
- [Быстрый старт](https://example.com/docs/quickstart): первый деплой за 10 минут — от подключения репозитория до рабочего URL
- [Установка CLI](https://example.com/docs/cli-install): пакеты для Linux, macOS и Windows, проверка подписи релиза
- [Подключение репозитория](https://example.com/docs/connect-repo): права доступа, вебхуки, self-hosted GitLab
## Конфигурация
- [Справочник acme.yaml](https://example.com/docs/config-reference): все поля, значения по умолчанию, схема валидации
- [Переменные окружения и секреты](https://example.com/docs/secrets): хранение, ротация, доступ из шагов сборки
- [Стратегии выката](https://example.com/docs/strategies): rolling, blue-green, canary — когда какая подходит
- [Откат релиза](https://example.com/docs/rollback): автооткат по health-check и ручной откат на любую предыдущую сборку
## API
- [Аутентификация](https://example.com/api/auth): токены, срок жизни, ограничение прав по scope
- [Справочник REST API](https://example.com/api/reference): эндпоинты, коды ответов, лимиты запросов
- [Вебхуки](https://example.com/api/webhooks): события деплоя, подпись запроса, повторные доставки
## Решение проблем
- [Сборка падает на этапе install](https://example.com/docs/troubleshooting/install): кеш, приватные реестры, несовпадение версий Node
- [Деплой завис в статусе pending](https://example.com/docs/troubleshooting/pending): квоты кластера, image pull secrets, taints
- [Коды ошибок](https://example.com/docs/error-codes): расшифровка всех кодов вида ACD-1234 и что делать по каждому
## Тарифы и лимиты
- [Тарифы](https://example.com/pricing): что входит в бесплатный тариф, как считаются минуты сборки
- [Лимиты](https://example.com/docs/limits): параллельные сборки, размер артефакта, частота обращений к API
## Optional
- [Блог](https://example.com/blog): релизы и разборы инцидентов
- [Статус сервиса](https://status.example.com): текущая доступность и история инцидентов
- [Changelog](https://example.com/changelog): изменения по версиям
Интернет-магазин
Главная ошибка магазинов — попытка перечислить товары. Карточек тысячи, для них есть sitemap.xml и товарные фиды. В llms.txt идут разделы каталога и, главное, справочные страницы: именно их спрашивают у ассистента.
# Северный Свет — светильники и комплектующие
> Интернет-магазин светильников: 4200 позиций, доставка по России, гарантия 24 месяца. Работаем с 2014 года, шоурум в Санкт-Петербурге, отгружаем юридическим лицам.
Отдельные карточки товаров в этом файле не перечисляются — их полный список доступен в sitemap.xml. Здесь собраны разделы каталога и справочные материалы, отвечающие на типовые вопросы покупателей.
## Каталог
- [Потолочные светильники](https://example.ru/catalog/ceiling): люстры, споты, трековые системы, встраиваемые светильники
- [Настенные светильники](https://example.ru/catalog/wall): бра, подсветка картин, уличные светильники
- [Лампы и источники света](https://example.ru/catalog/lamps): цоколи E14, E27, GU10, GU5.3 — мощность и цветовая температура
- [Комплектующие](https://example.ru/catalog/parts): блоки питания, диммеры, шинопроводы, крепёж
## Как выбрать
- [Сколько люмен нужно на комнату](https://example.ru/guides/lumens): расчёт освещённости по площади и назначению помещения, таблица нормативов
- [Цветовая температура: 2700K, 4000K, 6500K](https://example.ru/guides/color-temperature): где какая уместна и как не ошибиться со спальней
- [Совместимость с диммерами](https://example.ru/guides/dimmers): какие LED-лампы диммируются, почему свет мигает и как это лечится
- [Степень защиты IP для ванной и улицы](https://example.ru/guides/ip-rating): расшифровка IP44, IP65, IP67 и где какая нужна
- [Как рассчитать шинопровод](https://example.ru/guides/track-systems): длина, число секций, максимальная нагрузка
## Покупателю
- [Доставка и самовывоз](https://example.ru/delivery): сроки и стоимость по регионам, условия бесплатной доставки
- [Способы оплаты](https://example.ru/payment): карта, счёт для юрлиц, рассрочка
- [Возврат и обмен](https://example.ru/returns): сроки, порядок действий, что вернуть нельзя
- [Гарантия](https://example.ru/warranty): условия, что считается гарантийным случаем, как оформить обращение
## Optional
- [О компании](https://example.ru/about): история, адрес шоурума, реквизиты
- [Отзывы покупателей](https://example.ru/reviews): собранные отзывы с проверкой покупки
Блог или медиа
Для блога важнее всего два блока: кто вы (сигнал доверия) и что у вас есть опорного. Перечислять все посты не нужно — вместо этого дайте рубрики и десяток самых сильных материалов.
# Дневник наблюдателя
> Независимый блог о городской транспортной инфраструктуре: разборы реформ, работа с открытыми данными, интервью с проектировщиками. Автор — транспортный инженер, пишет с 2019 года.
Материалы публикуются под своим именем, источники данных указываются в каждом тексте. Ошибки исправляются с пометкой о правке в конце материала.
## О блоге
- [Об авторе](https://example.net/about): образование, опыт, декларация конфликта интересов
- [Как мы работаем с данными](https://example.net/method): какие источники используем, как перепроверяем цифры, политика исправлений
## Опорные материалы
- [Как считать пассажиропоток без турникетов](https://example.net/passenger-flow): методика, типовые ошибки, готовая таблица расчёта
- [Выделенные полосы: данные пяти городов](https://example.net/bus-lanes): сравнение «до и после», исходные наборы данных
- [Почему пересадочные узлы не работают](https://example.net/interchange): пять типовых ошибок планирования на реальных примерах
- [Открытые данные о транспорте: где брать](https://example.net/open-data-sources): перечень порталов, форматы, частота обновления
## Рубрики
- [Транспортные реформы](https://example.net/tag/reforms): разборы конкретных городских реформ
- [Открытые данные](https://example.net/tag/open-data): работа с наборами данных и визуализация
- [Интервью](https://example.net/tag/interviews): разговоры с проектировщиками и урбанистами
## Optional
- [Архив по годам](https://example.net/archive): все материалы с 2019 года
- [Рассылка](https://example.net/newsletter): дайджест раз в две недели

Что класть в llms.txt и чего класть не надо
Отбор — единственная сложная часть работы. Всё остальное механика.
Класть
- Страницы, которые отвечают на вопросы. Гайды, справочники, расчёты, сравнения, разборы ошибок, FAQ. Именно с вопросов начинается диалог с ассистентом.
- Страницы с фактами о вас. Условия доставки, тарифы, гарантия, контакты, реквизиты, часы работы. Это самая частая категория вопросов про компанию — и самая частая категория, где ассистент выдумывает, если факта нет.
- Опорные материалы разделов. По одной-две «якорных» страницы на тему, а не весь список.
- Страницы, за которые не стыдно. Всё, что попадёт в файл, потенциально будет пересказано и процитировано.
Не класть
- Всё подряд из sitemap. Это ровно то, чего формат пытается избежать. Свалка URL без пояснений не помогает никому.
- Служебные страницы. Корзина, оформление заказа, личный кабинет, поиск по сайту, страницы с UTM и параметрами фильтров, страницы печати.
- Закрытое. Всё, что за авторизацией или под
Disallowвrobots.txt. Приглашать агента туда, куда вы сами закрыли доступ, — прямое противоречие. - Дубли и пагинацию. Вторые и третьи страницы листингов, версии для печати, языковые дубли одной и той же страницы (для другого языка сделайте отдельный файл на своём хосте или разделе).
- Страницы под удаление. Всё, что вы собираетесь снести в ближайший месяц. Ссылка переживёт страницу и превратится в 404.
Про пояснения. Текст после двоеточия — не украшение, а рабочий элемент: по нему решают, открывать страницу или нет. «Подробнее», «читайте тут», «наша статья» — потраченная строка. Пишите, на какой конкретно вопрос страница отвечает и что на ней есть: «расчёт по площади и таблица нормативов» работает, «всё о освещении» — нет.
Про объём. Разумный ориентир — десятки ссылок, а не тысячи. Если файл не помещается в один экран внимания человека, он не поможет и машине: смысл курирования в отборе.
Простая проверка на здравый смысл: если вы не готовы, чтобы ассистент пересказал эту страницу своими словами и сослался на неё в ответе постороннему человеку, — страницы не должно быть в llms.txt.
Где размещать файл и как его отдавать
Половина проблем с llms.txt — не про содержимое, а про доставку. Требования короткие и жёсткие.
- Строго корень домена:
https://example.com/llms.txt. Не/docs/llms.txt, не в поддиректории. У каждого поддомена — свой файл в своём корне. - Код ответа 200. Классическая ловушка — soft 404: сервер отдаёт красивую HTML-страницу «ничего не найдено», но с кодом 200. Сканер видит «файл есть», а внутри вёрстка сайта. Внешне в браузере это выглядит как рабочая ссылка.
- Content-Type:
text/plain; charset=utf-8(допустимоtext/markdown; charset=utf-8). Если отдаётсяtext/html, часть парсеров начнёт искать разметку и не найдёт её. - Кодировка UTF-8 без BOM. BOM в начале файла приклеивается к первому символу, и строка
# Названиеперестаёт распознаваться как заголовок. - Никакой защиты на этом пути. Ни basic-auth, ни капчи, ни геоблокировки, ни «челленджа» антибот-системы. Проверяйте не из браузера, где вы залогинены и уже прошли все проверки.
- HTTPS и минимум переходов. Один редирект с
httpнаhttps— норма. Цепочка из трёх хопов с потерей пути — нет. - Внутреннее переписывание вместо внешнего редиректа. Если файл генерируется скриптом, направляйте запрос на обработчик правилом веб-сервера (rewrite), а не ответом 301 на
/llms.php. Внешний редирект уводит с канонического адреса и добавляет лишний хоп.
# nginx: статический файл с гарантированным типом и кодировкой
location = /llms.txt {
default_type text/plain;
charset utf-8;
add_header Cache-Control "public, max-age=3600";
try_files /llms.txt =404;
}
# nginx: то же самое, но содержимое отдаёт PHP-обработчик.
# Внутреннее переписывание — URL в адресной строке не меняется, редиректа нет.
location = /llms.txt {
rewrite ^ /llms.php last;
}
# Apache (.htaccess в корне): принудительный тип для готового файла
<Files "llms.txt">
ForceType text/plain
Header set Cache-Control "public, max-age=3600"
</Files>
# Apache: внутреннее переписывание на обработчик — без внешнего редиректа.
# Флаг [L] завершает обработку правил, [R] сознательно НЕ используем.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^llms\.txt$ /llms.php [L]
<?php
// llms.php — отдача файла с гарантированным кодом ответа и типом.
// Кладётся рядом с корнем, вызывается через rewrite (см. правила выше).
declare(strict_types=1);
$path = __DIR__ . '/data/llms.txt';
if (!is_readable($path)) {
http_response_code(503);
header('Retry-After: 3600');
header('Content-Type: text/plain; charset=utf-8');
echo "llms.txt is temporarily unavailable\n";
exit;
}
header('Content-Type: text/plain; charset=utf-8');
header('Content-Length: ' . (string) filesize($path));
header('Cache-Control: public, max-age=3600');
readfile($path);
Как выложить llms.txt на Tilda, Битрикс, WordPress, MODX и статике
Технически задача сводится к одному: файл должен физически лежать в корне публичной директории либо запрос к корневому пути должен попадать в код, который отдаёт нужное содержимое с нужными заголовками. Дальше — особенности платформ.
| Платформа | Как положить файл в корень | Подводный камень |
|---|---|---|
| Tilda | В настройках сайта есть раздел для загрузки произвольных файлов в корень домена (название пункта зависит от версии панели). Загружаете готовый llms.txt и публикуете сайт. | Возможность может быть недоступна на младших тарифах и при работе без своего домена. Файл отдаётся с инфраструктуры конструктора — проверяйте код ответа и Content-Type запросом на свой домен, а не в панели. Автообновления нет: при изменении структуры сайта файл нужно перезаливать руками. |
| 1С-Битрикс | Кладёте файл в корень публичной части (DOCUMENT_ROOT) по SFTP или через файловый менеджер в админке. Веб-сервер отдаёт существующий файл раньше, чем запрос попадает в urlrewrite.php. | Права доступа: файл должен быть читаем пользователем, под которым работает PHP-FPM или Apache, иначе получите 403. Если файл генерируется скриптом, правило нужно добавить явно — в .htaccess или конфиг nginx, потому что штатный обработчик 404 вернёт HTML-страницу. Проверьте, что кеш композита не отдаёт закешированную HTML-версию по этому пути. |
| WordPress | Самый надёжный путь — положить файл по FTP или SSH туда же, где лежит wp-config.php. Стандартное правило WordPress в .htaccess перехватывает только несуществующие пути, поэтому физический файл всегда выигрывает. | Если вместо файла делаете виртуальный маршрут через хук, обязательно выставьте заголовок, код 200 и завершите выполнение — иначе движок дорисует шаблон и вернёт HTML. Часть SEO-плагинов умеет генерировать llms.txt самостоятельно: убедитесь, что у вас не появилось двух источников правды, которые перетирают друг друга. |
| MODX | Проще всего — физический файл в корне рядом с index.php. Вариант «нативно»: создать ресурс с алиасом llms, выбрать тип содержимого text/plain с расширением .txt и очистить поле шаблона. | Если оставить шаблон по умолчанию, в ответ уйдёт HTML-обёртка вокруг вашего markdown. Если не сменить тип содержимого — адрес получится вида /llms.html. Для варианта с ресурсом должны быть включены человекопонятные URL, иначе адрес будет с параметром идентификатора. |
| Статика и CDN | Кладёте файл в каталог публикации (public/, dist/, static/) — сборщик выложит его как есть. Для объектного хранилища (например, у Selectel) — загружаете объект с ключом llms.txt в корень бакета. | Хранилища угадывают тип по расширению: .txt обычно даёт text/plain, но без charset — кириллица поедет. Выставляйте метаданные явно. Следите, чтобы сборщик не добавил хеш к имени файла и не убрал его как «неиспользуемый ассет». На CDN не забудьте сбросить кеш после обновления. |
Если платформа не даёт положить файл в корень
Такое бывает у закрытых конструкторов, SaaS-платформ и корпоративных порталов. Варианты по убыванию предпочтительности:
- Правило на веб-сервере или реверс-прокси перед платформой. Если перед CMS стоит ваш nginx, Traefik или подобное — перехватите путь
/llms.txtи отдайте файл с диска или проксируйте на отдельный бэкенд. Это самый чистый вариант: платформа вообще не участвует. - Виртуальный маршрут в коде. Если доступ к коду есть, а к корню — нет: зарегистрируйте обработчик пути, выставьте
Content-Typeи код 200 вручную и завершите выполнение до того, как движок начнёт рисовать шаблон. Это и есть тот самый случай «llms.txt через PHP». - Функция на границе (edge / serverless). Если сайт стоит за CDN с поддержкой пользовательских функций — обработчик на границе отдаёт файл, не трогая origin.
- Внешний редирект — крайний вариант. Ответ 301 с
/llms.txtна другой адрес формально работает: клиенты, следующие за редиректами, дойдут до содержимого. Но канонический путь перестаёт отдавать 200, добавляется хоп, а часть сканеров отмечает это как замечание. Используйте, только когда все предыдущие варианты недоступны, и никогда — вместо внутреннего rewrite.

Как сгенерировать llms.txt: вручную, скриптом, по расписанию
Вручную
Если значимых страниц до сотни — пишите руками. Это займёт час-полтора и даст лучший результат: пояснения будут человеческими, а не собранными из первого попавшегося абзаца. Возьмите за основу примеры выше, замените ссылки, перечитайте вслух каждое пояснение.
Скриптом из sitemap или базы
Для крупного сайта ручная сборка нереальна и, главное, быстро устаревает. Два источника данных:
- Из
sitemap.xml— универсально, работает без доступа к базе: берём адреса, фильтруем по разделам, тянемtitleиdescriptionс каждой страницы. - Из базы или CMS — точнее и быстрее: у вас уже есть заголовок, краткое описание, дата обновления и признак «важная страница». Не нужно ходить по HTTP и парсить HTML.
#!/usr/bin/env python3
# build_llms.py — собрать llms.txt из sitemap.xml
import re
import urllib.request
import xml.etree.ElementTree as ET
SITEMAP = "https://example.com/sitemap.xml"
NS = {"sm": "http://www.sitemaps.org/schemas/sitemap/0.9"}
SECTIONS = [("/docs/", "Документация"), ("/guides/", "Руководства")]
HDR = {"User-Agent": "llms-txt-builder/1.0 (+https://example.com/)"}
def get(url):
req = urllib.request.Request(url, headers=HDR)
with urllib.request.urlopen(req, timeout=20) as resp:
return resp.read().decode("utf-8", "replace")
def clean(m):
return re.sub(r"\s+", " ", m.group(1)).strip() if m else ""
def title_desc(html):
t = re.search(r"<title>(.*?)</title>", html, re.S)
d = re.search(r'name="description"\s+content="(.*?)"', html, re.S)
return clean(t), clean(d)
urls = [loc.text.strip() for loc in ET.fromstring(get(SITEMAP)).findall(".//sm:loc", NS)]
out = ["# Example", "", "> Кратко о проекте: чем занимаемся и для кого.", ""]
for prefix, heading in SECTIONS:
picked = sorted(u for u in urls if prefix in u)
if not picked:
continue
out += ["## " + heading, ""]
for u in picked:
title, desc = title_desc(get(u))
out.append("- [%s](%s): %s" % (title or u, u, desc or "описание не задано"))
out.append("")
with open("llms.txt", "w", encoding="utf-8") as f:
f.write("\n".join(out) + "\n")
Почему генерацию надо ставить на автообновление
Файл, собранный один раз «на посмотреть», через полгода начинает вредить: он ссылается на удалённые разделы и переименованные страницы. Вы своими руками отправляете агента на 404 — и получаете сигнал качества хуже, чем если бы файла не было вовсе.
Два места, где генерацию стоит запускать:
- По расписанию. Раз в сутки ночью достаточно для большинства сайтов. Задание в crontab:
# crontab -e — ежедневная пересборка в 04:15 с логом
15 4 * * * /usr/bin/python3 /opt/site/build_llms.py >> /var/log/llms-build.log 2>&1
# проверка ссылок раз в неделю, по воскресеньям в 05:30
30 5 * * 0 /opt/site/check_llms_links.sh >> /var/log/llms-links.log 2>&1
- В конвейере сборки. Шаг после деплоя гарантирует, что файл не отстанет от сайта. Добавьте туда же проверку ссылок и обрушьте сборку, если появились битые.
Ограничение автоматики: описания, вытянутые из meta description, почти всегда слабее написанных руками — они писались под сниппет в поиске, а не под ответ на вопрос. Рабочий гибрид: структуру разделов и десяток ключевых страниц пишете вручную, длинные хвосты (глоссарий, справочник кодов ошибок, каталожные разделы) добираете скриптом.
Файл со ссылками на удалённые страницы хуже отсутствующего файла. Если не готовы поставить генерацию на расписание — хотя бы поставьте напоминание на квартальную ревизию и проверку ссылок. Разовая публикация «и забыли» — самый частый сценарий деградации.
Как проверить llms.txt
Код ответа, тип содержимого, редиректы
Первое и главное: убедиться, что по адресу действительно лежит текстовый файл, а не HTML-страница.
# 1. Сводка одной строкой: код, тип, число редиректов, конечный адрес
curl -sIL -o /dev/null \
-w 'code=%{http_code} type=%{content_type} redirects=%{num_redirects} final=%{url_effective}\n' \
https://example.com/llms.txt
# 2. Полные заголовки как есть — смотрим Content-Type, Content-Length, кеш
curl -sI https://example.com/llms.txt
# 3. Первые строки содержимого: должно быть "# Название", а не "<!DOCTYPE html>"
curl -s https://example.com/llms.txt | head -20
# 4. Есть ли BOM в начале файла (ожидаем НЕ "efbb bf")
curl -s https://example.com/llms.txt | head -c 3 | xxd
# 5. Размер файла в байтах — контроль, что не раздулся
curl -s https://example.com/llms.txt | wc -c
Что должно получиться: code=200, type=text/plain; charset=utf-8 (или text/markdown), redirects=0 при обращении на канонический хост, первая строка вида # Название проекта.
Валидация структуры
Нормативного валидатора llms.txt не существует — и это стоит сказать прямо. Формат не является утверждённым стандартом, эталонной проверки, на которую можно сослаться как на обязательную, нет. Сторонние чекеры проверяют доступность файла и его формальную структуру, но их вердикт — не «соответствие стандарту», а мнение конкретной реализации.
Ручной чеклист структуры:
- первая непустая строка начинается с
#и такой заголовок в файле один; - сразу после заголовка — строка-цитата
>с описанием проекта; - разделы только второго уровня (
##), без###и глубже; - каждая ссылка — абсолютный URL по
https, а не относительный путь; - у каждой ссылки есть пояснение после двоеточия;
- нет таблиц, вложенных списков и HTML внутри — только плоский markdown;
## Optionalнаписан по-английски и стоит последним разделом.
Быстрая механическая проверка первых четырёх пунктов:
curl -s https://example.com/llms.txt | awk '
NR==1 && $0 !~ /^# / { print "FAIL: первая строка не заголовок H1: " $0 }
/^# / { h1++ }
/^#{3,} / { print "WARN: заголовок глубже второго уровня: " $0 }
/^- \[/ && $0 !~ /\): ./ { print "WARN: ссылка без пояснения: " $0 }
/^- \[/ && $0 !~ /\(https:\/\// { print "WARN: ссылка не абсолютная https: " $0 }
END { if (h1 != 1) print "FAIL: заголовков H1 в файле: " h1 }
'
Все ли ссылки живы
Самая ценная проверка: файл с битыми ссылками отправляет агента в никуда. Однострочник вытаскивает все URL из markdown-ссылок и печатает только те, что ответили не 200.
curl -s https://example.com/llms.txt \
| grep -oE 'https?://[^) ]+' \
| sort -u \
| while read -r u; do
printf '%s %s\n' "$(curl -sL -o /dev/null --max-time 15 -w '%{http_code}' "$u")" "$u"
done \
| grep -v '^200 '
Пустой вывод — всё в порядке. Любая строка на выходе — адрес, который надо чинить или убирать из файла. Этот же скрипт удобно повесить в конвейер сборки и валить сборку при непустом выводе.
Чем проверить на enterno.io
- /llms-txt — наличие файла, разбор структуры, разделы и ссылки.
- /http-headers — код ответа,
Content-Type, кодировка, цепочка редиректов по пути к файлу. - /robots-checker — не закрыт ли доступ AI-краулерам в
robots.txt. - /ai-check — общая AI-готовность сайта:
llms.txt, структурированные данные, отдача markdown, agent cards. - /broken-links — битые ссылки на сайте, включая те, что вы перечислили в файле.
Типовые ошибки: симптом → причина → проверка → фикс
В браузере файл открывается, а сканер пишет «не найден»
Причина. Soft 404: сервер отдаёт HTML-страницу «ничего не найдено» с кодом 200, либо браузер показывает вам старую версию из кеша. Проверка. curl -sI плюс curl -s … | head -5 — смотрим код и первые строки тела. Фикс. Положить физический файл в корень или добавить явное правило веб-сервера; убедиться, что код 200 и тело — markdown, а не вёрстка.
Content-Type: text/html вместо text/plain
Причина. Запрос попадает в CMS и отдаётся через шаблон. Проверка. curl -sI https://example.com/llms.txt | grep -i content-type. Фикс. Правило веб-сервера с default_type (nginx) или ForceType (Apache); если содержимое отдаёт скрипт — выставить заголовок явно и завершить выполнение до рендера шаблона.
Вместо кириллицы кракозябры
Причина. В Content-Type не указан charset, файл сохранён не в UTF-8 или в начале стоит BOM. Проверка. file llms.txt локально и curl -s … | head -c 3 | xxd удалённо. Фикс. Пересохранить в UTF-8 без BOM, добавить charset utf-8 в конфиг, для объектного хранилища — прописать метаданные объекта явно.
Файл идеальный, но AI-краулеры до сайта не доходят
Причина. Доступ закрыт в robots.txt, на WAF, антибот-защите или по геолокации. Проверка. /robots-checker и грепы по логам доступа по User-agent. Фикс. Решить вопрос доступа осознанно — какие боты пускаем, какие нет; детали в статьях про AI-краулеров и как AI-краулеры читают сайты.
Часть ссылок в файле отдаёт 404
Причина. Файл собран один раз и не обновлялся, сайт с тех пор менялся. Проверка. Однострочник обхода ссылок из раздела выше или /broken-links. Фикс. Генерация по расписанию плюс проверка ссылок в конвейере сборки с падением на непустом выводе.
Файл раздулся до сотен килобайт
Причина. В llms.txt свалили весь sitemap. Проверка. curl -s … | wc -c и просто взгляд на файл. Фикс. Оставить курируемое ядро на десятки ссылок, длинные перечни вынести в отдельные кластерные файлы и сослаться на них.
Раздел Optional переведён на русский
Причина. Естественное желание перевести всё. Проверка. Глазами: последний раздел должен называться ## Optional. Фикс. Вернуть английское имя. Это служебное слово, а не заголовок для читателя.
Файл есть на одном хосте, но не на другом
Причина. Сайт доступен и на www, и без, и по http, а файл лежит только на одном варианте. Проверка. Прогнать curl -sIL по всем четырём комбинациям. Фикс. Единая канонизация: неканонические варианты отдают 301 на канонический, канонический отдаёт файл с кодом 200.
Связка с robots.txt и структурированными данными
llms.txt — один элемент набора, и сам по себе он мало что решает. Соседи по задаче:
robots.txt. Определяет, пустят ли краулера вообще. Общая механика — в гайде по robots.txt, конкретные User-agent AI-ботов — в robots.txt и AI-краулеры. СтрокаSitemap:вrobots.txtпри этом никуда не девается:llms.txtеё не заменяет.- Структурированные данные. Schema.org даёт фактам машинную типизацию: что здесь товар, что организация, что автор, что цена. Разметка отвечает на вопрос «чем является этот объект»,
llms.txt— «где вообще искать». См. структурированные данные для AI-поиска. - Отдача markdown по
Accept. Логическое продолжение идеи: тот же материал отдаётся агенту чистым текстом без вёрстки — content negotiation для AI. - Agent cards в
/.well-known/. Описания возможностей и точек интеграции для агентов — agent cards и .well-known. Именно сюда сместилась тема машинных дескрипторов; старый файл.well-known/ai-plugin.jsonотносился к экосистеме плагинов, которая свёрнута, и сегодня упоминать его как актуального «соседа»llms.txtне стоит. - Извлекаемость контента. Если текст рисуется скриптом на клиенте, никакое оглавление не поможет — извлекаемость контента для AI.
- Стратегия целиком. Как это складывается в подход: generative engine optimization и как получить цитирование в ChatGPT.

Частые вопросы
Обязателен ли llms.txt?
Нет. Это не стандарт и не требование какой-либо платформы, а предложение сообщества. Отсутствие файла не является ошибкой сайта и не наказывается ни поиском, ни ассистентами.
Работает ли llms.txt на самом деле?
Честный ответ: проверяемых гарантий нет. Публичных обязательств крупных AI-платформ читать этот файл, как правило, не публикуется, и поведение агентов может меняться без объявления. Разумная позиция — относиться к файлу как к дешёвой ставке: час работы, отсутствие риска, возможная польза. И помнить, что сама работа по отбору страниц и написанию пояснений полезна независимо от того, прочитает файл кто-нибудь или нет.
Заменяет ли llms.txt sitemap.xml или robots.txt?
Нет, ни то, ни другое. robots.txt — разрешения на обход, sitemap.xml — машинный перечень адресов для индексации, llms.txt — курируемое оглавление смыслов. Все три решают разные задачи и живут параллельно.
Есть ли официальный валидатор llms.txt?
Нормативного — нет, потому что нет и утверждённого стандарта. Есть сторонние чекеры, включая нашу проверку: они смотрят доступность файла, код ответа, тип содержимого и формальную структуру. Это полезно, но их вердикт — мнение конкретной реализации, а не соответствие обязательным требованиям.
Как сделать llms.txt на Tilda или Битриксе, если нет доступа к серверу?
В Tilda используйте штатную загрузку файлов в корень домена из настроек сайта — этого достаточно, но файл придётся обновлять руками. В Битриксе доступ к корню обычно есть: положите файл через файловый менеджер админки или по SFTP и проверьте права на чтение для пользователя веб-сервера. Если корень недоступен в принципе — перехватывайте путь правилом на веб-сервере перед платформой либо отдавайте содержимое обработчиком в коде.
Можно ли отдавать llms.txt редиректом на PHP-файл?
Работать будет, но это не лучший вариант. Внешний редирект (301/302) уводит с канонического адреса и добавляет лишний переход, а часть сканеров отмечает это как замечание. Правильнее — внутреннее переписывание: rewrite ^ /llms.php last; в nginx или RewriteRule ^llms\.txt$ /llms.php [L] в Apache. Адрес в этом случае остаётся /llms.txt, редиректа нет, а содержимое формирует скрипт. Не забудьте выставить в обработчике Content-Type: text/plain; charset=utf-8.
Влияет ли llms.txt на позиции в поиске?
Прямого влияния на ранжирование в классическом поиске у файла нет — он адресован не поисковым алгоритмам. Ничто не мешает поисковым роботам его прочитать, но рассматривать llms.txt как фактор ранжирования не следует. Если задача — видимость в поиске, работайте с обычным техническим SEO и содержанием страниц.
Чеклист внедрения
- Файл лежит по адресу
https://канонический-домен/llms.txt, в корне, без поддиректорий. curl -sILпоказываетcode=200,redirects=0на каноническом хосте.Content-Type—text/plain; charset=utf-8илиtext/markdown; charset=utf-8.- Кодировка UTF-8, BOM в начале файла нет.
- Первая строка — единственный заголовок
# Название проекта. - Сразу после заголовка — строка-цитата
>с описанием проекта в одно-три предложения. - Разделы только второго уровня, ссылки абсолютные, у каждой есть пояснение по делу.
- Служебный раздел называется
## Optionalпо-английски и стоит последним. - В файле нет служебных, закрытых, дублирующих и готовящихся к удалению страниц.
- Объём — десятки ссылок, а не весь sitemap; тяжёлые перечни вынесены в отдельные файлы.
llms-full.txtсделан только если контент реально читается целиком, и держится в пределах единиц мегабайт.- Все ссылки из файла отдают 200 — проверено обходом, а не на глаз.
- AI-краулерам не закрыт доступ в
robots.txt, на WAF и антибот-защите. - Генерация стоит на расписании или в конвейере сборки; проверка ссылок валит сборку при битых.
- После обновления сброшен кеш CDN, если он есть.
- В команде записано, кто и когда пересматривает содержимое файла.