# Agent Terms, version 1

- **This version:** https://snuepi.com/spec/agent-terms/v1 (text: https://snuepi.com/spec/agent-terms/v1.md)
- **Latest version:** https://snuepi.com/spec/agent-terms/latest
- **Status:** Version 1, published 29 October 2026. Stable for implementation.
- **Document format:** 0.2 (the value of `agent_policy`)
- **JSON Schema:** https://snuepi.com/spec/agent-terms/v1/schema.json
- **Validator:** https://snuepi.com/spec/validate, and the command line tool in section 13
- **Editor:** snuepi (support@snuepi.com)
- **Licence:** the text is CC BY 4.0; the schema, the examples, the test vectors and the reference validator are Apache-2.0 (section 15)

## Abstract

Agent Terms is an open format in which a business tells AI agents how it wants to be contacted and booked: whether agents may contact it
at all, who must say what, which channel to use, when and how often, its booking rules, deposits and fees, the recording of its staff,
guardrails for regulated work, how sure a named verifier is that the business is real, and which operator tier it requires. A business
publishes one JSON document; any agent, from any agent maker, reads it before it calls, writes or books. Like `robots.txt`, but for commerce.

Anyone may publish, consume, implement or extend Agent Terms, with or without snuepi, without asking and without paying.

## 1. Introduction

AI agents phone, write to, book and poll small businesses that have no standard way to set terms. Staff cannot tell a real agent from a
scam, agents ignore booking rules they cannot read, and every agent maker builds its own guesswork. Agent Terms gives the business one place
to state its terms and gives every agent one place to read them.

### 1.1 Goals

- A business states its terms once, and every agent reads the same terms.
- The format is small enough to publish by hand and precise enough to be enforced by software.
- The terms can be signed, so an agent can tell they were issued for this business and not altered.
- No agent maker, platform or publisher is needed to publish or read the format, and none gets preferential treatment (section 14).

### 1.2 Non-goals

- Agent Terms is not a booking protocol. It points to the channels a business offers (for example MCP, A2A, REST, a booking page) and
  states the rules that apply on all of them.
- It does not decide whether an agent or a business is trustworthy. It carries verification results from a named verifier (sections 7 and 8).
- It is not legal advice and does not by itself create a contract. How terms bind the parties depends on the law that applies to them.

### 1.3 Relation to other work

Opening hours follow schema.org `OpeningHoursSpecification`. Signatures use JSON Web Signature (RFC 7515) with EdDSA (RFC 8037). Agent
identity uses HTTP Message Signatures (RFC 9421) as profiled by Web Bot Auth. The well-known URI follows RFC 8615.

## 2. Conventions and terminology

The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, NOT RECOMMENDED, MAY and OPTIONAL in this
document are to be interpreted as described in BCP 14 (RFC 2119, RFC 8174) when, and only when, they appear in all capitals.

- **Business:** the party whose terms the document states.
- **Publisher:** whoever serves and signs the document: the business itself, or a service acting for it (for example a registry or a
  booking system). The publisher is named by the `iss` of the signature.
- **Agent:** software that contacts a business on behalf of a person or company (its **principal**).
- **Operator:** the company behind an agent, identified by the domain its signing keys are published on. An **agent maker** is an operator.
- **Consumer:** software that reads a terms document, usually an agent.
- **Verifier:** a party that checks facts about a business or an operator against public registers and states a tier.
- **Registry:** a service that lists many businesses' terms and lets consumers look them up.

## 3. Conformance

There are four conformance classes.

1. A **conforming document** satisfies the JSON Schema and every MUST rule in section 13.2.
2. A **conforming publisher** serves conforming documents as described in sections 4, 5 and 9, and changes them as described in section 10.
3. A **conforming consumer** discovers terms as described in section 4 and behaves as described in section 6.
4. A **conforming validator** reports every MUST rule in section 13.2 as an error and every SHOULD rule as a warning, and agrees with the test
   vectors (section 13.3).

## 4. Discovery

A consumer about to contact a business looks for its terms in this order and stops at the first terms document it finds:

1. `https://<the business's host>/.well-known/agent-terms.json` (section 4.1);
2. the older name `https://<host>/.well-known/agent-policy.json`;
3. the `Link` header or an HTML `<link>` on the business's home page (section 4.2);
4. a registry lookup by domain, phone number or name (section 4.3).

A consumer that reaches a business by phone number or name only, without a website, starts at step 4.

### 4.1 Well-known URI

A business's site SHOULD serve `/.well-known/agent-terms.json` as one of:

- the terms document itself;
- a **pointer**: a JSON object whose member `agent_terms` is the absolute https URL of the business's terms document, for example
  `{ "agent_terms": "https://terms.example.net/salon-kim.json" }`;
- an HTTP redirect (301, 302, 307 or 308) to the terms document.

A pointer's `agent_terms` MUST be an absolute https URL. A consumer MUST follow at most one pointer and at most three redirects in a row.
Publishers that used the older name `/.well-known/agent-policy.json` SHOULD also serve `/.well-known/agent-terms.json`; consumers MUST
accept both.

A site MAY instead serve, at `/.well-known/agent-terms.json`, a **registry descriptor**: an object with the member `agent_terms_registry`
that describes a registry (section 4.3). A registry descriptor is not a business's terms.

### 4.2 HTML link and Link header

A page of the business MAY point to its terms with

```html
<link rel="agent-terms" href="https://terms.example.net/salon-kim.json">
```

or with the HTTP header `Link: <https://terms.example.net/salon-kim.json>; rel="agent-terms"`. Consumers MUST also accept the older
relation `agent-policy`. When both are present, `agent-terms` wins. A relative `href` is resolved against the page's URL.

### 4.3 Registries and lookups

A registry lists the terms of many businesses. A registry SHOULD offer a lookup by domain, phone number (E.164) and name with country,
and SHOULD describe itself at its own `/.well-known/agent-terms.json` with `agent_terms_registry` (its name), `lookup` (a URI template with
`domain`, `phone`, `name`, `country`), `feed` (a paged list of entries) and `entry_json` (the URL pattern of an entry). A registry MUST NOT
show in lookups an entry it has not verified as belonging to the business, and MUST mark such an entry with `registry.verification:
"unverified_claim"` where it serves it (section 5.13).

### 4.4 Fetching

- Terms documents MUST be served over https. Consumers MUST NOT use a document fetched over plain http, except from a development host.
- A consumer SHOULD honour HTTP caching headers and MUST NOT rely on a copy older than 24 hours when it contacts or books a business.
- A consumer MUST NOT send cookies or credentials when it fetches terms, and SHOULD identify itself in `User-Agent`.
- A document larger than 256 KB is not conforming; a consumer MAY stop reading after 256 KB.

### 4.5 When no terms are found

A consumer that finds no terms MUST behave as if the business had published `ai_must_identify: true`,
`unsolicited_sales_or_marketing: "not_accepted"` and `max_contacts_per_agent_per_day: 1`: it identifies itself, does not sell, and makes one
attempt.

## 5. The terms document

### 5.1 Media type, encoding and size

The document is a JSON object (RFC 8259), encoded as UTF-8, at most 256 KB. It SHOULD be served as `application/json`. Members whose meaning
is a time of day use `HH:MM` (24 hours) in the business's time zone (`booking.timezone`, an IANA name). Dates are `YYYY-MM-DD`. Amounts are
numbers in `booking.currency` (ISO 4217); country codes are ISO 3166-1 alpha-2.

### 5.2 Top-level members

Only `agent_policy`, `business`, `identification` and `contact` are REQUIRED. Every member is described below; the JSON Schema gives the
types.

| Member | Meaning |
|---|---|
| `agent_policy` | REQUIRED. The document format version: `"0.2"` for this specification (`"0.1"` is still accepted). |
| `spec` | The URL of the specification. Informative only. |
| `business` | REQUIRED. Who the business is (5.3). |
| `identification` | REQUIRED. What an agent must say and prove (5.4). |
| `contact` | REQUIRED. Whether, how, when and how often agents may contact the business (5.5). |
| `booking` | Booking rules, opening hours, deposits and fees (5.6). |
| `quotes` | Where binding prices come from, and site visits (5.7). |
| `request_types` | What agents can ask for: `book`, `quote`, `consult`, `order` (5.8). |
| `consultation` | The terms for `consult` (5.9). |
| `orders` | The terms for `order` (5.10). |
| `guardrails` | Rules for regulated work (5.11). |
| `negotiation`, `rate_limit`, `outreach`, `consumers`, `verified_outcomes`, `standards` | 5.12. |
| `registry` | Present when a registry serves the document (5.13). |
| `updated_at` | The date the terms last changed (10.3). |
| `signature` | The publisher's signature over the document (9). |

### 5.3 Business

`name` (REQUIRED), `organization_number`, `country`, `page` (a page about the business), and OPTIONAL `website`, `domain`, `maps`, `phone`
(E.164 with `+`), `type`. `verification` states how sure a verifier is that the business is who it says (section 7).

### 5.4 Identification

| Member | Meaning |
|---|---|
| `ai_must_identify` | REQUIRED and MUST be `true`: the disclosure duty (6.1). |
| `agent_name_required`, `on_behalf_of_required` | The agent names itself and its principal. |
| `signed_requests` | Whether HTTP Message Signatures are preferred, or required to book. |
| `verified_agents_only_for_booking` | `true`: only signed agents, agents with a key from the publisher, or an agent with the principal's own mandate may book. |
| `brand_names_without_proof` | How a known assistant's name without proof is treated (as an unverified claim). |
| `accepted_proofs_of_principal` | How the business verifies whom the agent acts for, for example `customer_mandate_oauth`, `customer_email_confirmation`, `http_message_signatures`, `business_registry_domain_match`, or a publisher's own buyer key. |
| `recording_of_staff` | `not_allowed`, `only_with_consent_asked_at_start` or `allowed`. A transcript counts as a recording. |
| `operator_verification` | The operator tiers and the tier the business requires (section 8). |

### 5.5 Contact

The contact rules, channels, rate limits and quiet hours.

| Member | Meaning |
|---|---|
| `agents_may_contact` | REQUIRED. `yes`; `channels_only`: only through the channels listed here, never cold calls or messages; or `no`. |
| `phone_calls_from_agents` | `accepted`, `accepted_in_hours` (then `phone_hours` MUST be present) or `not_accepted`. |
| `phone_hours` | `{ from, to }`: when calls are accepted. |
| `quiet_hours` | `{ from, to }` or `null`: no contact at all in this window, on any channel. `from` and `to` MUST differ. A window may run past midnight. |
| `max_contacts_per_agent_per_day` | The most contacts one agent may make in a day, on all channels together. No redialling. |
| `before_calling` | If an agent phones: `register` (where to register the call first), `say_the_code` (say the code it gets at the start of the call), `check_page` (where staff check the code), `verified_agents_only`. |
| `preferred` | The channel the business prefers. |
| `mcp`, `rest`, `ucp`, `request_page` | Channel URLs. |
| `acp` | `{ checkout, product_feed, discovery }`. |
| `email` | An email address for agents (not a URL). |
| `business_channel` | The business's own channel: `{ preferred: website | phone | email, booking_link, website, phone }`. |

When `agents_may_contact` is `channels_only`, at least one channel MUST be listed. Channel URLs MUST be absolute http(s) URLs and SHOULD use https.

### 5.6 Booking

Booking rules, opening hours, deposits and fees.

| Member | Meaning |
|---|---|
| `accepting_agent_bookings` | `false` while the business has paused bookings from agents; then `paused` is `{ until, until_local, message }`. |
| `instant_booking` | Whether some services can be booked without the business confirming. |
| `who_can_book_directly` | `anyone`, `customer_confirms_by_email`, `verified_businesses_only` or `nobody_owner_approves_all`. |
| `max_amount_without_owner_ex_vat` | Above this amount the business confirms itself. |
| `currency`, `timezone` | ISO 4217; IANA time zone. |
| `opening_hours` | A list of `{ days, opens, closes }` (1 = Monday … 7 = Sunday), like schema.org. A day can have several windows; a booking fits entirely inside one. A window MUST open and close at different times; `closes` earlier than `opens` runs past midnight and belongs to the day it opens. |
| `special_hours` | Dates that differ: `{ from, to, closed, hours, name }`. `from` MUST NOT be after `to`; a period that is not closed SHOULD list `hours`. |
| `working_days`, `working_hours` | Summaries of `opening_hours`; `working_hours` only when every open day has the same single window. |
| `lead_time_hours`, `cancellation_deadline_hours`, `max_agent_bookings_per_day`, `max_party_size`, `services_with_fixed_prices` | Limits. |
| `must_provide` | What the agent collects from its principal before booking, for example `address`, `photos`, `access_instructions`, `pets`, `allergies`, `party_size`, `parking`. |
| `deposit` | `null`, or `percent` or `amount` (exactly one of them), with `paid_to`, `when`, `pay_at`, and `applies_from_amount_inc_vat` when it applies only to larger bookings. |
| `card_guarantee` | A card the principal saves for the no-show fee; nothing is charged unless they do not come. |
| `no_show_fee_percent` | The fee for not coming, in percent of the price. |
| `one_booking_per_customer` | One upcoming booking per principal. |
| `resale` | `not_allowed` or `allowed`: whether bookings may be resold. |

### 5.7 Quotes

`price_source` (where a binding price comes from; agents MUST NOT quote prices from memory or a stale profile) and `site_visit`:
`required` (`never`, `larger_jobs`, `always`), `bookable`, `offering_id`, `price_ex_vat`, `booking_page`.

### 5.8 Request types

`request_types.offered` lists what agents can ask the business for: `book` (a time), `quote` (a price for a job that has to be seen or
described first), `consult` (an engagement or intro meeting, qualified first) and `order` (goods). Each type MAY have an object with
`offered`, `what`, and the operations that serve it (`mcp_tools`, `a2a_skills`, `rest`, `acp_checkout`, `ucp_profile`). A type's `offered`
flag MUST agree with `request_types.offered`. A consumer MUST NOT make a request of a type the business does not offer.

### 5.9 Consultation

The terms for `consult`, or `null`. A business that offers `consult` SHOULD publish them. `services`, `qualification_questions` (each with
an `id`: `scope`, `budget_band`, `deadline`, `client_type`; the agent asks its principal each one first and never guesses), `fee_basis`
(`basis`: `fixed`, `hourly`, `retainer` or `free_intro`, with `amount`, `minimum_engagement`, `currency`; `negotiable` is always `false`),
`conflict_of_interest`, `documents` (`none` or `descriptions_only`: an agent describes documents, never sends them), `intro_meeting`,
`eligibility_note` and `outcome`.

### 5.10 Orders

`max_order_without_owner_inc_vat` (above it only a verified buyer orders directly), `returns_policy` (to tell the principal) and `currency`.

### 5.11 Guardrails

A list of `{ id, rule }` for regulated work. Each id appears once. The ids defined in v1: `no_personal_advice_via_agents`,
`client_verified_before_account_specifics`, `no_instructions_or_payments_via_agents`, `patient_verified_before_health_details`,
`no_diagnosis_via_agents`. A request that crosses a guardrail is refused with the guardrail's id and the way forward; an agent MUST NOT try
to get around a guardrail by rephrasing the request.

### 5.12 Other members

- `negotiation`: `allowed`, `max_negotiations_per_sender_per_day`, `beyond_limit` (for example `list_price_only`), `mandate` (a signed
  mandate when the business lets agents agree terms).
- `rate_limit`: `requests_per_minute` an agent may send to the business's channels.
- `outreach`: `unsolicited_sales_or_marketing` and `data_collection_for_training`, each `accepted` or `not_accepted`.
- `consumers`: consumer-law facts an agent acting for a private person must respect, such as `withdrawal_period_days` and
  `early_start_needs_explicit_consent`.
- `verified_outcomes`: counts computed from principals who actually booked or bought (`completed_bookings`, `positive_feedback`,
  `problems_reported`, `source`). Not reviews anyone can write.
- `standards`: related standards the business also serves.

### 5.13 Registry

Present when a registry serves the document: `name`, `about`, `page`, `json`, `sign` (a printable sign), `lookup`, `verification`
(`domain_email`: the listing was confirmed from an address at the business's own domain; `unverified_claim`: it was not), `domain_verified`,
`phone_verified`, `listed_since`.

### 5.14 Extensions and unknown members

Consumers MUST ignore members they do not understand. Publishers MAY add members; a member that is specific to one publisher SHOULD be
grouped under a member named after it, so it cannot collide with a future version of this specification. A publisher MUST NOT use an
extension to weaken a term defined here.

## 6. Agent behaviour

A conforming consumer acting on terms it has read:

### 6.1 Disclosure

The disclosure duty: at the start of every call, message and request, the agent MUST say that it is an AI agent, which agent and operator it
is, and on whose behalf it acts. It MUST NOT present itself as a human, as the business, or as another operator. `ai_must_identify` is
always `true` in v1; a document that says `false` is not conforming, and a consumer MUST still disclose.

### 6.2 Respecting the terms

- When `agents_may_contact` is `no`, the agent MUST NOT contact the business. When it is `channels_only`, the agent MUST use only the
  listed channels.
- The agent MUST NOT phone when `phone_calls_from_agents` is `not_accepted`, nor outside `phone_hours`. If it phones, it SHOULD register the
  call first (`before_calling.register`) and say the code.
- The agent MUST NOT contact the business inside `quiet_hours`, nor more often than `max_contacts_per_agent_per_day` and `rate_limit`, and
  MUST NOT get around these limits with new names, keys, numbers or addresses.
- The agent MUST collect everything in `must_provide` before booking, MUST keep a booking inside one opening window, and MUST tell its
  principal about any deposit, card guarantee, no-show fee and cancellation deadline before it books.
- The agent MUST NOT book above `max_amount_without_owner_ex_vat` or `max_order_without_owner_inc_vat` without the business confirming, MUST
  respect `one_booking_per_customer`, and MUST NOT resell bookings when `resale` is `not_allowed`.
- The agent MUST NOT record staff unless `recording_of_staff` allows it, and then only after asking at the start.
- A "no" from the business, or from its publisher on its behalf, is final for that request.

### 6.3 Reporting back

The agent MUST report to its principal what the business actually said, including prices, times, terms, deposits and refusals, without
inventing or leaving out conditions.

## 7. Verification of the business

`business.verification` carries the result of a verifier's checks: `tier`, `checked_at` (the date of the check), `by` (the verifier),
`levels` (the tiers it uses) and `about` (where its method is described).

| Tier | Meaning |
|---|---|
| `T0` | An owner's email address is confirmed. |
| `T1` | T0, and the business controls its own website domain (an owner's confirmed email is on that domain, or the domain is proven). |
| `T2` | T1, and the legal entity is confirmed, for example a valid VAT number whose registered name matches, or a match in an official company register. |
| `T3` | T2, and matched in an official company register: found by its number, active, in the business's country, with a matching name. |

- A tier is a signal, never a reason to refuse a business or an agent.
- A document that states a tier SHOULD be signed by the verifier named in `by`, or by a publisher that serves the verifier's result. A
  consumer MUST treat a tier in an unsigned document as the publisher's own claim and MUST NOT present it as a third-party verification.
- A tier SHOULD come with `checked_at`. A verifier MUST NOT publish the people behind a business (directors, owners) in this block.

## 8. Agent operator tiers

`identification.operator_verification` lists the operator tiers (`tiers`) and the tier the business requires (`minimum_tier_for_fast_path`).

| Tier | Meaning |
|---|---|
| `unverified` | Not known to the verifier. It may still sign its requests. |
| `keys_proven` | The operator signs requests (HTTP Message Signatures, Web Bot Auth) with a key in its own domain's key directory. |
| `entity_verified` | And the legal entity it declared is confirmed against public registers. |
| `agreement_accepted` | And it accepted the verifier's current operator agreement with a request signed by its own key. |

`minimum_tier_for_fast_path` is the lowest tier whose requests the business completes without the principal's own confirmation, or `null`
for none. It MUST be one of `tiers` when both are given. Below it, the principal confirms the booking; the request is never refused for its
tier. An operator profile and the agreement MAY be linked with `operator_profile` and `agreement`. The tiers mean the same for every
operator: a verifier MUST apply the same checks to every agent maker.

## 9. Signatures

A publisher SHOULD sign every document it serves. The signature lets a consumer check that the document was issued by its publisher and was
not altered, and lets either side later show which terms were served.

### 9.1 Signing

The member `signature` is a JWS in compact serialization (RFC 7515):

- protected header: `alg` MUST be `EdDSA` (Ed25519, RFC 8037); `kid` MUST name the key; `typ` SHOULD be `agent-terms+jws` (documents
  signed before this specification use `snuepi-agent-policy+jws`, which is also valid);
- payload: a JSON object with `type` (MUST be `"agent_policy"`), `iss` (MUST: the publisher's origin, an https URL), `sub` (an identifier
  of the business chosen by the publisher), `iat` (the time of signing, seconds since 1970) and `policy` (MUST: the document without its
  `signature` member).

### 9.2 Keys

The publisher MUST publish its public keys as a JSON Web Key Set at `<iss>/.well-known/jwks.json`, each with `kty: "OKP"`, `crv:
"Ed25519"`, `x` and `kid`. A publisher keeps retired keys in the set for as long as documents signed with them may be checked.

### 9.3 Verifying

A consumer verifies a signature by:

1. parsing the JWS and checking `alg` is `EdDSA` and the payload's `type` is `agent_policy`;
2. checking that the payload's `policy` is the same JSON value as the document without `signature` (members in any order);
3. fetching the JWKS at `<iss>/.well-known/jwks.json` and finding the key by `kid`;
4. verifying the signature over the JWS signing input with that key;
5. checking that the document was served from the origin in `iss`, or reached from the business's own site through a pointer, a redirect
   or a link (section 4).

A signature that fails steps 1 to 4 is invalid, and a consumer MUST NOT rely on the document's verification claims (sections 7 and 8).
A consumer SHOULD then treat the document as unsigned, or fetch it again from the publisher.

### 9.4 Example

The examples in appendix A are signed with the Ed25519 key of RFC 8037 appendix A.1 for the fictional publisher
`https://terms-publisher.example`. That key is public and MUST NOT be trusted for anything else. Its public part is
https://snuepi.com/spec/agent-terms/v1/examples/jwks.json.

## 10. Versioning and change notice

### 10.1 Format version

`agent_policy` is the document format version, `0.<minor>`. A new minor version only adds members or values; consumers MUST ignore what
they do not understand and MUST NOT reject a document only because its minor version is newer. A change that alters the meaning of an
existing member needs a new major version of this specification.

### 10.2 Versions of this specification

Each version of this specification is published at its own URL (`/spec/agent-terms/v1`, `/v2` …) with its own schema, and stays available
after a newer version is published. `/spec/agent-terms/latest` points to the newest. Corrections that do not change a rule (typos,
clearer wording) may be made to a published version and are listed in its change log (appendix B). A new version is announced on
https://snuepi.com/spec at least 90 days before snuepi, as a publisher, stops serving documents that conform to the older one.

### 10.3 Change notice

- `updated_at` SHOULD be present and MUST NOT be in the future. A publisher MUST change it on the day the terms change.
- New terms apply to contacts and requests made after the publisher serves them. A consumer that cached a copy MUST fetch the terms again
  before it books, if its copy is older than 24 hours.
- A publisher SHOULD keep, for each version of a business's terms it served, the exact signed document (or its hash), so that the business
  and the agent can later show which terms applied.

## 11. Privacy considerations

- A terms document is public. It MUST NOT contain personal data beyond what the business chooses to publish as its contact details. Owners'
  names, private addresses, and the people behind a company (directors, owners) do not belong in it.
- Verification blocks carry a tier and a date, never the numbers, names or register data behind them.
- A consumer MUST NOT send cookies, user identifiers or principal data when it fetches terms. A publisher SHOULD NOT build profiles of
  consumers from fetches beyond what it needs to show which terms it served.
- A registry MUST let a business remove its entry at any time, and MUST NOT publish the email address used to list it.

## 12. Security considerations

- Channel URLs and the document SHOULD use https; a consumer MUST NOT act on a document fetched over plain http (section 4.4).
- A known assistant's name is a claim, not an identity. Identity comes from signed requests (Web Bot Auth) and from verifiers (section 8).
- A document's tiers are only as good as its signature (sections 7 and 9). An attacker who controls a business's website can change its
  pointer; a consumer that sees the pointer change to a new publisher SHOULD treat the new terms as unverified until they are signed.
- Consumers fetching terms on behalf of others (validators, crawlers) MUST NOT fetch private or internal addresses and SHOULD limit
  redirects, size and time.
- The guardrails in section 5.11 reduce what an agent can ask for; they do not replace the business's own checks.

## 13. Conformance testing

### 13.1 Tools

- The validator page https://snuepi.com/spec/validate checks a URL (with discovery, section 4) or a pasted document, and reports each rule it
  breaks with the path and the reason. The same check is `POST https://snuepi.com/api/public/spec/validate` with `{ "url": "…" }` or
  `{ "document": { … } }`.
- The command line tool runs anywhere with Node.js 22 and needs no account. Download https://snuepi.com/spec/tools/validate-agent-terms.mjs
  and https://snuepi.com/spec/tools/spec-validator.mjs into one folder, then run `node validate-agent-terms.mjs <file or https URL> [--json]`;
  `node validate-agent-terms.mjs --conformance` runs the test vectors.

### 13.2 Rules

Every finding names one of these rules. A MUST rule is an error (the document does not conform); a SHOULD rule is a warning.

| Rule | Level | What it checks |
|---|---|---|
| `schema` | MUST | The document conforms to the JSON Schema. |
| `size.max` | MUST | At most 256 KB as UTF-8 JSON. |
| `format.version` | MUST | `agent_policy` is a format this specification defines (`0.1` or `0.2`). |
| `format.newer` | SHOULD | A newer `0.x` format: members unknown to v1 are ignored. |
| `identification.disclosure` | MUST | `identification.ai_must_identify` is `true`. |
| `contact.phone_hours` | MUST | `accepted_in_hours` comes with `phone_hours`. |
| `contact.quiet_hours` | MUST | `quiet_hours.from` and `quiet_hours.to` differ. |
| `contact.channel_required` | MUST | `channels_only` lists at least one channel. |
| `contact.channel_urls` | MUST | Channel URLs are absolute http(s) URLs; `email` is an address. |
| `contact.https` | SHOULD | Channel URLs use https. |
| `booking.deposit` | MUST | A deposit has `percent` or `amount`, not both. |
| `booking.opening_hours` | MUST | A window opens and closes at different times, on days listed once. |
| `booking.special_hours` | MUST | A special period starts on or before the day it ends. |
| `booking.special_hours_windows` | SHOULD | A special period that is not closed lists its hours. |
| `request_types.offered` | MUST | `request_types.offered` and each type's `offered` flag agree. |
| `consultation.present` | SHOULD | A business that offers `consult` publishes `consultation`. |
| `guardrails.unique` | MUST | Each guardrail id appears once. |
| `operator.minimum_tier` | MUST | `minimum_tier_for_fast_path` is one of the `tiers` listed. |
| `verification.checked_at` | SHOULD | A tier comes with `checked_at`. |
| `verification.signed` | SHOULD | A document that states a tier is signed. |
| `updated_at.present` | SHOULD | `updated_at` is present. |
| `updated_at.future` | MUST | `updated_at` is not in the future. |
| `signature.present` | SHOULD | The document is signed. |
| `signature.valid` | MUST | A signature verifies and covers exactly this document (9.3, steps 1 to 4). |
| `signature.verifiable` | SHOULD | The publisher's key is found at `<iss>/.well-known/jwks.json`. |
| `signature.issuer_origin` | SHOULD | A signed document is served from its issuer's origin (9.3, step 5). |
| `discovery.found` | MUST | A document is found at the well-known URI, through a link, or at the URL given. |
| `discovery.https` | MUST | The document is served over https. |
| `discovery.pointer` | MUST | A pointer's `agent_terms` is an absolute https URL to a terms document. |
| `discovery.legacy` | SHOULD | The well-known URI is `/.well-known/agent-terms.json`. |
| `discovery.media_type` | SHOULD | The document is served as `application/json`. |
| `document.kind` | MUST | The document is a business's terms, not a registry descriptor or a pointer. |

### 13.3 Test vectors

https://snuepi.com/spec/agent-terms/v1/conformance/index.json lists documents with the result a conforming validator gives: `pass`, or
`fail` with the MUST rules that fire. The keys the signed vectors use are in the same file.

## 14. Governance and neutrality

- **Open.** Anyone may implement this specification, publish or consume documents, and build validators, registries or agents on it,
  without permission, registration or payment.
- **Neutral.** A publisher or verifier that follows this specification serves every agent maker on the same terms: the same documents, the
  same checks and tiers, and the same limits for the same verified facts. Where treatment differs (a higher limit, a faster path), it MUST
  depend only on published criteria that every agent maker can meet, such as a tier or a signature, never on which agent maker it is. No
  agent maker gets preferential treatment, and no tier can be bought.
- **Changes.** Anyone can propose a change, with the problem it solves and an example, to support@snuepi.com with "Agent Terms" in the
  subject, until a public issue tracker is announced on https://snuepi.com/spec. Proposals and the editor's decisions are published there.
  A change that adds a rule is open for comment for at least 30 days before it is published in a new version (section 10.2).

## 15. Licence

This specification text is licensed under the Creative Commons Attribution 4.0 International licence (CC BY 4.0). The JSON Schema, the
examples, the test vectors and the reference validator are licensed under the Apache License, Version 2.0. Implementing the specification
requires no licence at all.

## Appendix A. Examples per sector

Each example is a complete, signed document (section 9.4). They show the terms a business in that sector typically sets; any business can
set any term.

| Sector | Example |
|---|---|
| Trades and repairs (a plumber) | https://snuepi.com/spec/agent-terms/v1/examples/trades.json |
| Cleaning | https://snuepi.com/spec/agent-terms/v1/examples/cleaning.json |
| Outdoor and moving | https://snuepi.com/spec/agent-terms/v1/examples/moving.json |
| Beauty and appointments (a hair salon) | https://snuepi.com/spec/agent-terms/v1/examples/salon.json |
| Hospitality (a restaurant) | https://snuepi.com/spec/agent-terms/v1/examples/restaurant.json |
| Professional services (a law firm) | https://snuepi.com/spec/agent-terms/v1/examples/law-firm.json |
| Financial services (an accountant) | https://snuepi.com/spec/agent-terms/v1/examples/accountant.json |
| Health (a dental clinic) | https://snuepi.com/spec/agent-terms/v1/examples/dental-clinic.json |
| Retail (a shop) | https://snuepi.com/spec/agent-terms/v1/examples/shop.json |

A minimal conforming document:

```json
{
  "agent_policy": "0.2",
  "business": { "name": "Salon Kim", "country": "DE" },
  "identification": { "ai_must_identify": true },
  "contact": { "agents_may_contact": "channels_only", "request_page": "https://salon-kim.example/book" },
  "updated_at": "2026-10-29"
}
```

## Appendix B. Change log

- **Version 1 (29 October 2026).** First version of this specification. It specifies document format 0.2, which the Agent Policy drafts
  (0.1 on 24 October and 0.2 on 26 October 2026) introduced, and adds: the well-known URI `agent-terms.json` with pointers, the
  `agent-terms` link relation, the signature profile, the verification and operator tiers, the conformance rules and the test vectors.

## Appendix C. References

- BCP 14: RFC 2119 and RFC 8174, key words for requirement levels.
- RFC 7515, JSON Web Signature; RFC 7517, JSON Web Key; RFC 8037, CFRG curves (Ed25519) in JOSE.
- RFC 8259, JSON. RFC 8615, well-known URIs. RFC 8288, web linking.
- RFC 9421, HTTP Message Signatures; Web Bot Auth (IETF draft), signing agent requests with keys in a domain's key directory.
- schema.org `OpeningHoursSpecification`.
