# For AI agents

These docs are written so an agent can do the job from them alone. Give it the docs, the key, and a clear request.

## Pick a style

If your agent (or the code it maintains) already knows one registrar's API, tell it to use that style: Dynadot, Spaceship, Cloudflare, GoDaddy, Porkbun or Namecheap. Otherwise use the Dynadot style, as the briefing below does: one URL, form parameters, and the live check built in.

## Give your agent the docs

| URL | What it is |
|---|---|
| `https://maildns.io/llms.txt` | A short index in the [llms.txt](https://maildns.io/llms.txt) format: what MailDNS is, the rules that matter, and a link to every page |
| `https://maildns.io/llms-full.txt` | Every docs page in one markdown file, in reading order. The best single thing to hand an agent. |
| `https://maildns.io/docs/<page>.md` | Any docs page as plain markdown: add `.md` to its address, for example `https://maildns.io/docs/dynadot.md` |

Each docs page also links its markdown in the page header (`<link rel="alternate" type="text/markdown">`), and the markdown links point at other markdown pages, so an agent that follows links stays in clean text.

## Give it the key safely

- Put the key in an environment variable the agent's tools can read, such as `MAILDNS_KEY` (and `MAILDNS_SECRET` for Spaceship style).
- Don't paste the key into the conversation: chat logs and traces are kept in places keys should not be.
- If the agent runs on a fixed machine, ask for the key to be locked to that machine's IP address. Then a leaked key is useless anywhere else.

## A briefing to paste

Paste this into the agent's instructions (system prompt, project rules, or the top of the task). It holds the rules that keep an agent from doing damage.

```text
You manage DNS records through MailDNS, a Dynadot-compatible DNS API.
Docs: https://maildns.io/llms-full.txt (read it before your first call).

1. The key is in the MAILDNS_KEY environment variable. Never print it, log it
   or show it in a command you report back.
2. Call POST https://api.maildns.io/api3.json, form-encoded, with key and
   command. URL-encode every value (DKIM keys contain + / =).
3. Address each host as its own domain: domain=advisor.example.com. Records at
   the host are main records (main_record_type0, main_record0); records under
   it use subdomain0 / sub_record_type0 / sub_record0 (google._domainkey,
   _dmarc). Record types are lowercase: a, aaaa, cname, mx, txt.
4. Always send add_dns_to_current_setting=1. Without it, set_dns2 replaces
   every record on the host. Only replace when asked to change or delete a
   record, and only after reading the host with get_dns and re-sending every
   record that should stay.
5. A call succeeded when str(ResponseCode) == "0". Otherwise read Error. Retry
   only "too many requests" and "another change ... still running", after a
   pause. Any other error: stop and report it word for word.
6. Never write records for the root domain (example.com) or for any name that
   is not at or under a host that list_domain returns.
   Never try to change nameservers or add NS records. The answer is always
   "This API key doesn't work for nameservers." Report it; don't retry.
7. TXT values go in one piece, without quotes. One SPF record and one DMARC
   record per name: read get_dns first and merge rather than add a second.
8. After a write, call dns_status with domain, subdomain (@ for the host
   itself), record_type and value every 15 seconds until Live is "yes". Give
   up after 15 minutes and report. Only ask Google or Microsoft to verify once
   it is "yes".
9. When done, report every record you changed: host, name, type, value, and
   whether dns_status says it is live.
```

## Ask it like this

Concrete requests work best: the host, the record, and what "done" means.

```text
Add the Google verification record below to advisor.example.com, wait until
dns_status says it is live, then tell me so I can press Verify.

google-site-verification=3J9tq0iV8pTt1yW5zKc2mE7aR4bN6hD0sF1gL8xQ
```

```text
For every host in hosts.txt, add the Google Workspace MX, SPF and DMARC
records from https://maildns.io/docs/google-workspace.md. Skip any host that
already has a different SPF or DMARC record and list those at the end.
```

```text
List my MailDNS hosts and, for each one, which of these are live: Google
verification TXT, MX smtp.google.com, SPF, DKIM at google._domainkey, DMARC.
Change nothing.
```

## If the agent writes code

Agents that write their own scripts get the right shape from the [Google Workspace recipe](https://maildns.io/docs/google-workspace.md#many-hosts-a-complete-script): one `call()` helper that checks `ResponseCode` and retries only the rate limit and busy errors, `add_dns_to_current_setting=1` on every write, and a `dns_status` loop before anything is verified.

## Agents that know another registrar

An agent that already knows one of the other styles can use it unchanged; give it the style's page as well as the briefing.

| Style | Base URL | Watch out for |
|---|---|---|
| [Spaceship](https://maildns.io/docs/spaceship.md) | `https://api.maildns.io/api/v1` | Nothing replaces: `PUT` adds, `DELETE` removes exactly what is sent. Has its own status check. |
| [Cloudflare](https://maildns.io/docs/cloudflare.md) | `https://api.maildns.io/client/v4` | Look up the zone id first. A changed record gets a new id. |
| [GoDaddy](https://maildns.io/docs/godaddy.md) | `https://api.maildns.io/v1` | `PATCH` adds; `PUT /records` and `PUT /records/{type}` replace. |
| [Porkbun](https://maildns.io/docs/porkbun.md) | `https://api.maildns.io/api/json/v3` | Every call is a `POST` with the key in the body. |
| [Namecheap](https://maildns.io/docs/namecheap.md) | `https://api.maildns.io/xml.response` | `setHosts` always replaces: read with `getHosts` first. |

The live check is Dynadot style in every case: `dns_status` with the same key.
