# For AI agents

> llms.txt, a Markdown twin of every page, and the prompt that installs the chat with Claude Code or Cursor.

These docs are written for coding agents as much as for people. Everything below is plain HTTP, with no account and no key.

## Where to start

| Address | What it is |
|---|---|
| [`https://tolkly.io/llms.txt`](https://tolkly.io/llms.txt) | A short map of the docs ([llmstxt.org](https://llmstxt.org)): a summary, instructions for agents, links to every page's Markdown |
| [`https://tolkly.io/llms-full.txt`](https://tolkly.io/llms-full.txt) | Every English page in one file |
| [`https://tolkly.io/docs/ru/llms.txt`](https://tolkly.io/docs/ru/llms.txt) | The same in Russian; untranslated pages are given in English |

English is the source of these docs and is always complete. Russian pages are translations of it.

## Markdown for every page
Every page has a Markdown twin, built from the same source as the HTML. Links in it are absolute and point at other twins. An agent can follow them without parsing HTML.

- Add `.md` to the page's address: `https://tolkly.io/docs/en/install.md`.
- Or ask for Markdown at the page's own address: the server reads the `Accept` header.

```sh
curl -H 'Accept: text/markdown' https://tolkly.io/docs/en/install
```

A page served as HTML sends `Vary: Accept` and names its twin and llms.txt:

```http
Link: </docs/en/install.md>; rel="alternate"; type="text/markdown", </llms.txt>; rel="describedby"; type="text/plain"
```

The HTML has the same `<link rel="alternate" type="text/markdown">` in its `<head>`. On each page, «Copy as Markdown» puts the twin on the clipboard, and «Open in…» opens it in Claude or ChatGPT with a question about it.

## The install prompt
In the app, owners see «Hand it to an AI agent» under the install code in the project's «Install» section. It is the prompt below, with the project and the endpoint filled in. Here it has `your-project` in place of the project's id. On the install pages, «Open in…» → «Prompt for an AI agent» copies it.

```text
Install the Tolkly support chat on this website.

Project: your-project
Widget endpoint: https://api.tolkly.io

1. Read https://tolkly.io/llms.txt, then https://tolkly.io/docs/en/install.md and the section for this site's stack in https://tolkly.io/docs/en/frameworks.md. If they do not load, this prompt is enough.
2. Work out how the site is built: static HTML, a server-rendered framework (Next.js, Nuxt, Laravel, Django…), a single-page app (React with Vite, Vue, Angular) or a CMS (WordPress, Tilda, Bitrix).
3. Add these two lines exactly once, in the layout every page shares, just before </body>:

   <script type="module" src="https://api.tolkly.io/widget.js"></script>
   <tolkly-chat project="your-project"></tolkly-chat>

   Add no other attributes: the chat's name, greeting, colours and who answers come from the server. Load the script from https://api.tolkly.io; do not copy or bundle it.
4. In a single-page app the chat must survive route changes: put the tag outside the router outlet (index.html or the root layout) and load the script once, never per page. In TypeScript JSX, declare tolkly-chat as an intrinsic element instead of casting to any.
5. If the site sends a Content-Security-Policy, allow https://api.tolkly.io, https://ru.tolkly.io in script-src, connect-src and img-src, and add blob: to img-src (file previews). style-src needs nothing: the widget uses constructed stylesheets (Chrome 73+, Firefox 101+, Safari 16.4+). If the policy uses a nonce, put the same nonce attribute on the <tolkly-chat> tag so older Safari gets styles too. If script-src has 'strict-dynamic', host sources are ignored: put the nonce on the widget's <script> tag as well. If the policy cannot allow this, stop and tell me.
6. Do not add a domain allowlist: the chat works on any of my domains by default.
7. If visitors sign in on this site, ask me before adding signed identity (https://tolkly.io/docs/en/identity.md). The secret stays on the server in an environment variable, never in browser code.
8. Check it in a browser: run the site, open two different pages, and confirm the chat button shows on both and, in the network panel, the request to https://api.tolkly.io/v1/projects/your-project/widget answers 200 without a "refused" field. A request from curl proves nothing: without the page's Origin it is always allowed. Then list the files you changed. Within a few minutes of the deploy, the «Install» section of the project in Tolkly says the chat is live on this site.
```

What the prompt leaves out on purpose:

- **No secret.** The identity secret stays with the owner. The owner puts it on the site's server by hand, through an environment variable ([Signed visitor identity](https://tolkly.io/docs/en/identity.md)).
- **No forged requests.** The check is a real page in a browser. A request with a made-up `Origin` would add a stranger's site to the project's domains.
- **No chat settings.** The owner changes the name, colours and greeting, not the site's code.

## Rules agents get wrong
- The tag goes once into the layout every page shares. Not into a page component, and not twice.
- The tag gets `endpoint` and `project` only. Theme, greeting and who answers come from the server ([attributes](https://tolkly.io/docs/en/widget-attributes.md)).
- The script is loaded from the endpoint as a module. Never copy it into the repository or bundle it.
- With a Content-Security-Policy, `style-src` needs nothing added, not even `'unsafe-inline'`. If the policy has a style nonce, put the same `nonce` on the tag ([CSP](https://tolkly.io/docs/en/csp.md)).
- No domain allowlist unless the owner asks for one: by default the chat runs on any domain ([domains](https://tolkly.io/docs/en/domains.md)).
