# Full content (llms-full.txt) > Concatenated markdown of all primary pages. For LLMs that prefer a > single document over per-page fetches. Sources are canonical URLs > on https://turva.dev/. # My gate could not see a sixth 2026-08-04 I built a gate that checks that the five agent readiness categories are declared the same way on six surfaces. It went green and it stayed green. 79 static checks with no failures, 212 checks against the live site with no failures, and 53 mutation cases across three runners that all reported no holes. Then I had a hostile reader go through the gate itself, and it came back with three holes. All three were one defect in three shapes. The two posts before this one came at the same thing from other sides. The first was about a check that keeps passing after it has stopped measuring the right thing. The second was about a red reading that turned out to be about my own client rather than the server. This one is neither. The gate measured what it measured correctly, and it was blind by construction to everything it did not measure. ## The gate asked the wrong question On every surface the gate asked whether these five were present. It never asked what else was there. That is the whole finding, and it is worth putting plainly. A check that asks whether these five are present is not a check of the set. It is a check of a list you wrote yourself, and it is blind to every element you did not know to write down. A sixth category went through three of the four static surfaces untouched. I measured each one by running it rather than by reading the code, because reading my own code is how I ended up here. Add a sixth category to the surface, run the gate, read the output. RESULT: OK, zero failures, sixth category sitting on the page. ## Three shapes of one defect The first was a filter that ran before the count. The table rows in the README are collected, filtered down to the ones that resolve to a known category, and only then counted. A row whose name the fact file does not recognise disappeared in the filter, so the counter never went up. The filter is there to keep unrelated rows out of the count, and it kept the finding out with them. The second was a span that ends on the last element's own sentence. The gate lifts a paragraph out of the audit guide by anchoring on the first category and the last one, and the closing anchor is commerce's own sentence. That is exactly where a sixth gets appended. Anything added after it falls outside the span the gate is reading. The third was a substring test standing in for an equality test. One surface carries a twin sentence built entirely from the fact file, and the gate compared the page against it with includes. A sixth appended to the end of the list was caught. A sixth inserted at the front was not, because the string the gate wanted was still in there. It just was not the whole of it any more. ## The fourth one was in the tool doing the checking There was a fourth, and it sat in the thing I was using to prove the other three. One of the mutation runners reported no holes across ten cases. Seven of those ten had come back with applied=0 and HTTP 429, which means the rate limit refused the request and the mutation was never in place at all. The runner counted a case that never ran as a case with nothing wrong. It read a red run as a pass. That is the same defect one level up, and it is the one I would rather report than the three below it. The runner asked whether the failures it knew to look for had appeared, and it never asked whether the run had happened. A tool that certifies the other tools is where this class of mistake does the most damage, and a green summary sitting on top of seven refused requests is exactly what it looks like from the outside. The same blindness turned up in a different gate a few hours later. Cases aimed at an agent skills file were matching any agent skills line instead of the one they named, so a digest check stood in for a content check and one real hole went through. The mutation had put a wrong business identifier in the declared field. The check passed because the correct identifier still appeared elsewhere in the same file, inside a registry link, and the check was searching the file rather than reading the field. ## What a set check has to do instead A check that watches a set must not search. Searching answers a question about one string at a time, and a set is not a bag of strings you happened to remember. The check has to enumerate what the surface actually contains, then compare that enumeration against the set. Three conditions, all of them at once. - The enumeration and the set are the same length. - Every element found on the surface resolves to a member of the set. - No member of the set is resolved twice. The third condition earns its place. Without it a surface can carry the right number of rows with one member listed twice and another missing entirely, and the first two conditions are still satisfied. Then the part my original code had backwards. Every element that does not resolve is a finding. In the gate I wrote, an unresolvable row was a row to skip, and it was a row to skip because the code had been written to answer whether the known five were present. The question shapes the data structure, and the data structure then makes the other question impossible to ask. ## The version that transfers None of this is new and none of it is rare. Anyone who has written against a schema has met it under the name additionalProperties, and the repair is the same repair. The reportable part is not the class of defect. It is that three instances of it were sitting in my own code, in a gate I had negative tested, on a day it reported green three separate ways. The version that transfers to anyone with a test suite: your test asserts that the fields you remembered are present in the response. It does not ask what else is in the response. Add a field to the payload and the test stays green, which is correct behaviour for a compatibility check and wrong for anything you believe is watching a set. If a test's name says it validates a schema or a contract, open it and check whether it enumerates or whether it searches. ## About the hostile read It was a tool of mine in a session of mine. It is not an audit and I am not going to call it one. It produced 17 observations, 13 of them carrying evidence and 4 flagged as suspicion, and I verified the four most serious by running them myself before I believed any of them. A second reader's finding is a lead. It becomes a measurement when you run it, and until you run it you have only swapped one reader's confidence for another's. ## What these gates still do not read The gates watch what they watch. The category set is now compared across six surfaces where it used to be compared across two. Two things they do not touch at all: the markdown twins on pages other than the homepage, and the values inside the well-known manifests. Nothing here says the site cannot drift. It says that one specific way of drifting now costs a red run, and that I know the names of the next two. ## Related - [The checks that pass for the wrong reason](/blog/checks-that-pass-for-the-wrong-reason) - [A red reading that measured my own client](/blog/red-reading-that-measured-my-own-client) - [Measurement-led agent readiness](/guides/measurement-led-agent-readiness) --- # A red reading that measured my own client 2026-07-30 I posted yesterday about checks that keep passing after they have stopped measuring the right thing. The next reading I took was the same defect turned around. A request against my own MCP server came back red, and the red was about my request. ## Two responses that agreed on the wrong story I was working on the README for that server and sent a request at the endpoint to see what it was serving. The first was server/discover, which the 2026-07-28 revision of the Model Context Protocol requires every server to implement. It answered -32601 Method not found. So I sent initialize with protocol version 2025-06-18, the handshake that revision removes, and it answered 200 with the server's identity. Taken at face value that is a server that never migrated. The required new request is missing and the removed handshake still works. The migration had gone out that morning. ## The server was right and my request was not Reaching the new lane takes three things at once, and I had none of them. The request has to carry the header MCP-Protocol-Version: 2026-07-28. It has to carry an Mcp-Method header naming the same method as the body. And params._meta has to carry the keys io.modelcontextprotocol/protocolVersion and io.modelcontextprotocol/clientCapabilities. Send none of that and the request is not malformed. It is a legacy request, and the library's compatibility lane answers it correctly, because answering it correctly is what the lane exists to do. That is the part worth stopping on. A compatibility lane is built to be invisible, which is right for a client and wrong for anyone taking a measurement. When the old lane answers politely, "this server does not implement the new revision" and "my client did not ask for the new revision" arrive looking the same. Neither response carries the thing that would separate them. ## The cheap test There is one and it costs a single request. If initialize answers, you are on the legacy lane, and whatever you conclude next is a statement about your client. A server serving 2026-07-28 does not offer initialize on the new lane at all, so a working handshake is evidence about the caller. ## What the four requests returned - Without the version header, server/discover returns HTTP 200, framed as an event stream, carrying -32601 Method not found. The same request sent as initialize with protocol version 2025-06-18 returns 200 and the server's identity. - With the version header and no _meta, HTTP 400 and -32602, and the message says the header names revision 2026-07-28 while the request is missing the required per-request envelope key _meta. - With the header and a _meta whose keys are spelled protocol-version and client-capabilities, HTTP 400 and -32602 again, and this time the message lists the two names the server does want. - With all three in place, HTTP 200, supportedVersions holding 2026-07-28 alone, capabilities.tools.listChanged true, resultType complete, ttlMs 3600000, cacheScope public, and the server identity in result._meta. ## What this is not This is not a defect in the SDK and not a gap in the spec. The compatibility lane is a deliberate decision and the right one, and being invisible is the whole point of it. The trap is downstream, in what a reader does with a response that arrives clean. It is also not a story where the information was missing. Read the second and third rows again. The server named the envelope key I had left out, then the two keys I had misspelled. The correct request was written inside the failures from the moment the version header went on, and I read the first response as a verdict instead of reading the rest as instructions. Rechecking all of this turned up one more of my own. A note of mine says this endpoint refuses anything that does not accept both JSON and an event stream. That holds on the legacy lane. On the new one a plain JSON Accept is answered, and so is a request with no Accept header at all. I had written down the behaviour of the lane I happened to be standing in and filed it as the rule. ## The shape, both times Yesterday it was a green check reading a lane the server no longer serves. Today it was a red reading of a lane my client never asked for. A response tells you what happened and you supply what it means, and the supplying is where it goes wrong. It goes wrong quietly, because a clean status code and a well-formed error object look like a measurement. So the habit, for anything with a compatibility layer beneath it. Before reading the result, work out which lane answered. If the protocol will not tell you, put the discriminator in the request yourself and check that the answer moves. None of this is visible to an agent-readiness scanner. Scanners do not speak MCP, so a passing readiness level says nothing about whether an MCP endpoint serves the current revision. That one belongs to whoever runs the server. ## Related - [The checks that pass for the wrong reason](/blog/checks-that-pass-for-the-wrong-reason) - [MCP server card](/guides/mcp-server-card) - [Measurement-led agent readiness](/guides/measurement-led-agent-readiness) --- # The checks that pass for the wrong reason 2026-07-29 The Model Context Protocol cut revision 2026-07-28 on 28 July. I read the released tree that evening, the way I read any spec I am about to depend on, and the finding was not in the prose. It was in the step that produced the release. ## Thirteen links that resolved Cutting a revision copies the living draft tree into a dated one, and every reference inside the copy has to be dated with it. That is the whole promise a dated snapshot makes. Reading the 2026-07-28 tree a year from now should give what it gives today. The promote step rewrote one link pattern when it copied the spec tree, and that part worked. Two other patterns were not covered. Three links still pointed at the draft schema, including the one whose own next line calls it the source of truth for all protocol messages and structures. Nine pointed at the draft docs tier, eight of those at the security best practices page. The changelog's compare link was the thirteenth. Not one of them was broken. Every one resolved, just to the living tier rather than the frozen one, which is presumably why a preview check did not catch them. The reader who follows a link labelled 2026-07-28 in a year gets whatever the draft has become by then, and nothing anywhere reports a problem. I filed it with the line numbers and the two greps I had run to find them. It was closed the same day. The fixed release carries thirteen corrected links, and the promote step now runs all three rewrites over all three copied trees with the changelog compare pinned to the new tag. The second half is the half that matters. A file fix is good for one revision and a workflow fix is good for every revision after it. ## The same shape, one day later, in my own gate The revision is a large breaking one. Sessions are gone, the initialize handshake is gone, the protocol is stateless, and there is a new server discovery request that servers must implement. Both dependencies my own MCP server needed went stable within two days of the cut, so I moved it over. My site has a verification script that proves the signed MCP server card describes the server that is actually running. It exists because a card once declared capabilities the server did not implement, for weeks, invisibly. The way it proved parity was to run the initialize handshake against the live server and compare what came back. The new revision has no initialize. The library keeps a compatibility lane that still answers it. So the gate would have kept passing. It would have reported the same clean count it always reports, and it would have been measuring the old lane while the new one went untested. Not a failure, not a warning, just a number that no longer meant what it said. I rewrote the parity block around the new discovery request before the migration shipped rather than after, and added two checks the old transport had no equivalent for. ## What the two have in common Both are the same defect wearing different clothes. In the release it was links that resolve, so nothing is broken. In my gate it was a check that passes, so nothing is red. In both cases the text and the tooling were fine in isolation and the thing between them had quietly stopped being true. The practical version, for anyone maintaining a checker: a gate that only fails on breakage cannot tell you that it has started measuring the wrong thing. When the thing under test changes shape, read what your own check actually speaks to. Mine was one line of code and a protocol version, and I would not have found it by running it. The lesson I took from reading three specs this way is narrower than I expected. On a mature spec, the prose has been over hundreds of eyes and the review process works. The publishing machinery around it has been over far fewer. That is where a fresh reader still has something to contribute. ## Related - [MCP server card](/guides/mcp-server-card) - [Measurement-led agent readiness](/guides/measurement-led-agent-readiness) - [Honesty and the checker](/blog/honesty-and-the-checker) - [A red reading that measured my own client](/blog/red-reading-that-measured-my-own-client) --- # Finishing the optional commerce checks 2026-07-20 Agent-native payments are moving from proposal to plumbing. This summer the x402 protocol became a Linux Foundation project, with Visa, Mastercard, Google and Stripe among its founding members. The chain being built runs from discovery to transaction, which means a site's payment surface has to be something an agent can find and read before any money moves. isitagentready.com scores that surface in its Commerce category. The category is optional and does not change the overall score, so turva.dev already read 100/100 and Level 5 with three of the five commerce checks green. Two were still red, x402 and MPP. This is the log of taking them green and leaving settlement exactly where it was. ## What the scanner actually checks The two checks failed for a plain reason, and not the one an earlier note had assumed. The scanner exposes its own audit detail, so you can see what it fetches. For MPP it reads /openapi.json and looks for the payment fields directly on each payable operation. turva had declared them inside an offers array, a form the payment-discovery draft allows and this scanner does not read. Flattening the declaration to the single-offer form, same Stripe charge and same price, was all it needed. For x402 the scanner requests /api and expects an HTTP 402 with payment terms. turva served an open index at /api and a dedicated 402 endpoint elsewhere, so the probe saw a 200 and stopped. The fix was to make /api itself answer with the canonical x402 402, backed by a real wallet on Base, and to move the free endpoint index to /api/v1. The 402 is a genuine challenge, and the free discovery surfaces stay open at /openapi.json, under /.well-known, and at /api/v1. ## Settlement did not change What did not move is the part worth stating plainly. turva does not auto-settle. The 402 challenge and the OpenAPI discovery both declare a real payment surface, priced in USDC on Base and payable by card through Stripe, but the money is confirmed out of band rather than taken by the site. An agent can discover the offer and read the terms. A person or an agent then completes the purchase, and scope for bespoke work is agreed in writing first. A green check here says the surface is present and correct. It does not say the site quietly charged anyone. An earlier post left these two checks red, on the reasoning that satisfying them meant disturbing surfaces that were already correct. Reading the scanner's probe more closely showed a cleaner path, so the position changed. That is the use of measuring against a tool you do not control. It shows you where you were wrong. ## The services, and how a card payment works The three fixed offerings have a card checkout link each, prices ex VAT: - [Agent-readiness audit, €6,500](https://buy.stripe.com/aFadR995G5xV6hi43N5EY00) - [Monthly advisory, €3,000, minimum three months](https://buy.stripe.com/7sYcN5eq04tRfRSeIr5EY01) - [Implementation day, €1,500](https://buy.stripe.com/6oUaEX81C0dBfRSbwf5EY02) Scope is agreed in writing before any of the three is paid. That is what the terms say, and it is what the OpenAPI spec says about these same three links. The link is how the card payment is made once scope is settled, not a way around settling it. VAT is added on the invoice rather than by the link, so an EU business buying under reverse charge sends its VAT ID with the scope. Corrected 2026-08-02. This section used to present the three links as an invitation to pay before scope was agreed, which contradicted the terms and the description of the same three links in the OpenAPI spec. The measurements in this post are unchanged. ## The rule, again A green check is worth something only when it reflects what an agent actually finds. Commerce is optional, so none of this moved the headline number. It moved whether the payment surface is real and discoverable for the moment agents start to pay, which is the part that will matter. The worker that produces these results is open source at github.com/erekola/turva-worker, readable line by line. For an agent-readiness audit that reports measured results, contact info@turva.dev. ## Related - [x402 and agent payments](/guides/x402-agent-payments) - [Agentic commerce readiness](/guides/agentic-commerce-readiness) --- # The twin is the page 2026-07-19 Every page of this site lives as a markdown string inside the Worker's source file. For the guides and the blog posts that has always been literal. The Worker renders those pages from the markdown at request time, and a client that asks for text/markdown gets the same string untouched. Ten pages worked differently. The homepage, the services page, the validator and the other card-style pages were hand-written HTML, and the markdown lived beside them as a twin. Same content, two homes. Two homes means every edit happens twice, and sooner or later one home gets the edit and the other does not. I knew that when I chose the layout. For a while the honest description of the arrangement was a sentence I never liked writing: a checker keeps the pairs in sync, and I am not sure that is the right call. ## Six drifts nobody saw The checker earned its keep before it retired. A parity gate went into the deploy checks the day before this conversion, comparing each hand-written page against its twin paragraph by paragraph. In its short life it found six real drifts, wording that had quietly diverged between the HTML and the markdown. None of them were visible by reading. I had read those pages many times. ## One home for every sentence This week the two homes became one. The ten card pages now render their prose from the twin at request time. Seventeen small helpers, under two hundred lines between them, read a named section of the twin and render its paragraphs into the page. The structure around the prose stays hand-built. The hero, the terminal demo, the validator form and the price cards are HTML that the markdown does not try to describe. Every sentence now lives once, and editing the twin is editing the page. ## The gate that replaced the comparison The parity comparison is gone, because there is nothing left to compare. What replaced it is a stricter check on the end state. Before every deploy a script walks each card function and fails the run if it finds a literal prose paragraph outside two named exceptions, if a twin section is neither rendered nor declared markdown-only, or if a function references a section its twin does not have. The gate is mutation-tested from both sides. A planted paragraph fails the run, and so does a misspelled section name. An exception that exists but goes unused fails it too, which keeps the exception list from rotting into a list of ghosts. ## Proving it with rendered output The gate was not enough on its own, because the risk in a rewrite like this is a rendering change nobody asked for. So every batch of the conversion shipped against a rendering harness. The same worker file runs in plain Node before and after the change, all ten pages and their markdown twins are snapshotted, and the outputs are diffed after normalization. The blog index came out byte-identical. The company page came out identical after normalization. Every other page changed only in ways the diff named, mostly apostrophes turning into HTML entities. The harness also caught one real bug before it went anywhere. A sentence on the validator page named the fetched path with a placeholder domain written in URL form. As hand-written HTML it was inert text. Rendered through the markdown pipeline it matched the bare URL rule and became a link to a domain that does not exist. The fix was rewording the sentence without the URL shape. The general lesson: prose that moves into a markdown renderer starts playing by markdown's rules, and rendered output is the only place you see that. ## What did not change From the outside almost nothing moved. The scanner read the site before and after the conversion and reported the same result. The homepage still serves a markdown version that is deliberately shorter than its HTML, and the layout is still code. That boundary is the honest one to draw. The markdown is the content contract, and the structure around it is the site's own business. Two limits are worth stating plainly. The checks run on my machine before a deploy, and there is no CI behind them. And the blast radius of a bad edit is unchanged, because all content lives in template literals in module scope, so one stray interpolation marker would still take down every page rather than one. A build step would solve that differently, and at some size it wins. At this size, one file that renders itself is cheaper to keep honest. If you want to check any of this, request any guide or blog post with Accept: text/markdown and diff the response against its string in worker.js. They match byte for byte. ## Related - [When honesty and the checker disagree](/blog/honesty-and-the-checker) - [Every response promised a rate limit. Nothing enforced it.](/blog/enforcing-the-rate-limit-i-advertised) - [Serving markdown to agents](/guides/markdown-for-agents) --- # Every response promised a rate limit. Nothing enforced it. 2026-07-18 One function in this site's Worker attaches security headers to every response it renders. Until yesterday two of them were RateLimit-Limit: 100 and RateLimit-Policy: "default";q=100;w=60. They went out with the homepage, with all 24 guides, with every markdown twin and with every 404. This site also publishes a guide on response headers for agents, and that guide teaches the RateLimit family on the reasoning that a well-behaved agent reads the declared budget and throttles itself before anyone has to throttle it. No code enforced either number. The Worker had no rate limiting logic and no path that returned a 429, and the config declared no limiter. The 100 had never been connected to a counter, so every response was advertising a budget the server had no way to spend. It surfaced while I was preparing answers to the hardest questions this site could be asked, which is the only reason it surfaced at all. That is the exact defect this business sells finding. A declared surface that no code resolves is the first thing an agent-readiness audit looks for, and an agent polite enough to trust the header would have been rationing itself against a limit that lived only in text. ## What enforcement looks like Cloudflare's Workers rate limiting binding does the work now. The configuration is a block in wrangler.jsonc naming a limiter with a simple limit of 100 requests per 60 seconds, so the config carries the same numbers the header had been promising on its own. At the top of the fetch handler the Worker calls limit() keyed on the client IP, and past the limit it returns 429 with Retry-After: 60, built by the same security header function as every other response, so the rate limit header rides on the 429 itself. It fails open, deliberately. If the binding is missing or limit() throws, the request is served normally, because a limiter that takes the site down when its own plumbing breaks is a worse trade than a burst that gets through. That choice has a cost this post comes back to: from the outside, a guard that has failed open is indistinguishable from a guard doing its job, and only the logs can tell them apart. The key is the client IP, and Cloudflare advises against that. Their best practices say it plainly: "It is not recommended to use IP addresses or locations (regions or countries), since these can be shared by many users in many valid cases." They are right. The identifiers they recommend are stable properties of a caller, an API key in an Authorization header or a user or tenant ID, and none of those exist here. This site is public documentation with no accounts and no login, so the IP is what is left, and the cost is real. Several agents behind one corporate proxy or one mobile NAT share a single budget of 100, and the one that gets refused may be the one that asked politely. ## The test that found nothing Reading the code is what caught this. That finding needed no instrument: no limiter logic anywhere, nothing that could say 429. On the same morning a probe seemed to corroborate it, 130 requests in about six seconds, zero 429s back. I would have quoted the probe over the code reading in a heartbeat, because it has a number in it and numbers travel. The probe proves nothing, and that is now measured rather than suspected. I ran the same burst against the fixed site, enforcement live, from a network that had never touched it. 130 requests, ten in parallel, and all 130 came back 200 with not one 429. The identical result the broken site gave. In the larger burst below, not one of the first 130 requests was refused either. A hundred and thirty requests never reach the point where this platform starts refusing, so the working site and the absent limiter answer that probe in exactly the same voice. A test that returns the same answer whether or not the thing is broken is not weak evidence. It is not evidence. It is worse than no number at all, because a number gets quoted, and this one would have been quoted by me. The code reading found the defect. The curl agreed with it by coincidence. ## Cloudflare documents the looseness The binding's documentation says, in a section titled Accuracy, that the API "is permissive, eventually consistent, and intentionally designed to not be used as an accurate accounting system." The Performance section above it explains why: the counters are cached on the machine the Worker runs on and updated asynchronously against a backing store in the same Cloudflare location, which is how limit() costs no meaningful latency. And the counters are local. For each key there is a separate limit per Cloudflare location, so 100 per 60 seconds is a budget per IP per location, never a global one. Measured from here, permissive looks like this. A parallel burst of 300 requests, ten at a time, returned 279 responses of 200 and 21 of 429. That run tagged each request with its index, so it could see where the refusals sat: all of them pooled at the end, indexes 240 through 299. A second run from another network split 281 and 19. A single request sent straight after the burst was refused on one network and served on the other, which is eventual consistency behaving exactly as advertised, and why the Retry-After: 60 on the 429 is a declared ceiling rather than a measured wait. The contrast that stings is local. A wrangler dev run enforces the limit exactly, 100 requests pass and the rest are refused, so the environment where you would naturally verify your own code is the one environment that behaves nothing like production. There is also a slower path to the limit, and our first test walked toward it without knowing. The budget refills at 100 per 60 seconds, a little under two requests a second. A sequential loop at three per second drains faster than the refill, so on a bucket model it would meet its first refusal somewhere past request 220. Ours stopped at 115 requests and 38 seconds, saw nothing but 200s, and I misread that as a broken deploy and asked for a second one. The deploy had been fine. The measurement was too small to say anything in either direction, and the possibly wasted deploy is part of this story's bill. ## If you want to test it A slow loop tells you nothing here, and a hundred requests tell you nothing. Both come back all 200s whether the limit is enforced or absent. What reaches the limit is a parallel burst big enough to outrun the counters: seq 300 | xargs -P 10 -I{} curl -s -o /dev/null -w "%{http_code}\n" https://turva.dev/ | sort | uniq -c Expect most of the burst to pass and a tail of it to be refused. My two runs split 279 to 21 and 281 to 19. Yours will be a third pair of numbers, because you will be filling a counter in your own Cloudflare location rather than in mine. The shape repeats, the arithmetic does not. And if a burst of 300 gets you no 429 at all, I want to hear about it, because that is either the fail-open path hiding a broken binding or a behavior I cannot presently explain. The address is info@turva.dev. ## One header was from a retired revision The guide on this site names the current pair of fields, RateLimit and RateLimit-Policy. The code was sending RateLimit-Limit and RateLimit-Policy. Before touching anything I went to the IETF archive to check which surface was right, and the answer was unambiguous. Revision 11 of draft-ietf-httpapi-ratelimit-headers, the active revision from May 2026, defines exactly two fields, RateLimit-Policy and RateLimit. RateLimit-Limit belongs to the early revisions, and where revision 11 mentions it at all is inside a section whose own heading says it is to be removed before publication as an RFC, in a survey of the legacy header names the draft is trying to replace. The site was sending one field from the current draft and one from a retired lineage in the same response. The guide had been right all along. Only the code was wrong. The fix shipped yesterday: RateLimit-Limit is gone and RateLimit-Policy stays. The field the current draft does define, RateLimit, was deliberately not added. Revision 11 makes its r parameter, the remaining quota, required, and Cloudflare's limit() returns a success boolean and nothing else, no remaining and no reset, so sending RateLimit would mean inventing the very number the field exists to carry. The draft also says the policy field alone lets a client control its own flow of requests, and positions the RateLimit field for limits that are highly dynamic. This limit is a static 100 per 60 seconds. For a static limit, RateLimit-Policy alone is the correct form. ## What to take from it A declared limit is a claim about behavior, and claims about behavior rot silently, because nothing breaks when they do. The check that catches this class of defect is reading the code. Probing the endpoint cannot do it, because on an eventually consistent platform the probe returns the same comfortable 200s for a working guard, for a missing one and for one that has failed open. If a header on your site promises something, the interesting question is not whether the value looks sensible. It is which line of code makes it true. If you want your own agent-facing claims read the way a skeptic would read them, an audit is what I do. Email info@turva.dev. ## Related - [Response headers that help agents](/guides/response-headers-for-agents) - [When honesty and the checker disagree](/blog/honesty-and-the-checker) --- # Microsoft said the patches would get bigger. I measured how much bigger. 2026-07-15 On 9 July 2026 the head of Windows published a post about AI-powered vulnerability discovery. One line in it was a warning to customers: "As AI helps defenders discover more issues, customers will see a higher volume of security updates included in each security release." It does not say how much higher. The post runs about 1400 words and contains no numbers at all. Five days later Microsoft shipped the July package: 1150 CVEs. The number Microsoft would not put in the blog post is sitting in Microsoft's own API. The Security Update Guide publishes every monthly package as machine-readable CVRF, acknowledgments included, no key required. So I pulled twelve months of it and did the arithmetic. ## What the data says I sampled eight months before the ramp and four after it. | Month | CVEs | Month | CVEs | | --- | --- | --- | --- | | 2024-07 | 454 | 2026-04 | 737 | | 2025-01 | 343 | 2026-05 | 991 | | 2025-04 | 374 | 2026-06 | 1281 | | 2025-07 | 527 | 2026-07 | 1150 | | 2025-10 | 427 | | | | 2026-01 | 310 | | | | 2026-02 | 169 | | | | 2026-03 | 460 | | | The eight pre-ramp months average 383 CVEs. July 2026 is 1150, so the package is 3,0 times the old normal. The baseline broke in April and peaked in June at 1281. April to July inclusive is 4159 CVEs. At the old rate that is 10,9 months of output, delivered in four. ## The number I am not going to use February 2026 had 169 CVEs. It is the lowest month in two years, less than half the baseline. Divide July by February and you get 6,8 times, which is a much better number for a headline. I am not using it, because choosing your denominator is how honest people produce dishonest numbers. February is an outlier, and the only reason to anchor to it is that it flatters the story. The real multiplier is 3,0. It does not need help. ## It is not noise The obvious objection is that volume without quality is just a bigger pile. If AI were generating low-value findings that got patched anyway, the severity distribution would sag. It did the opposite. | Measure | 2025-07 | 2026-07 | | --- | --- | --- | | CVEs | 527 | 1150 | | CVSS median | 6,5 | 7,5 | | CVSS mean | 6,47 | 7,26 | | CVSS 7,0 and above | 48,0 % | 71,9 % | | CVSS below 4,0 | 4,2 % | 0,8 % | | Rated Moderate | 33,4 % | 4,8 % | | Rated Critical | 26 | 66 | | Remote code execution | 42 | 165 | | Elevation of privilege | 58 | 256 | Three times the volume, and the median CVE is a full point more severe. The Moderate band collapsed from a third of the package to under five per cent. Remote code execution roughly quadrupled. One caveat, stated plainly. The share of CVEs Microsoft did not assign a CVSS score to rose from 5 % to 38 %. Those are likely Chromium-inherited Edge issues, which Microsoft does not usually score itself. The severity claim above holds for what Microsoft scored. I cannot speak for the rest, and neither can anyone who has not opened the file. ## Why the well did not run dry Windows has been patched for thirty years. Intuition says the supply of findable bugs should be thinning. Instead it tripled. The explanation is in Microsoft's own May post about MDASH, their multi-model agentic scanning harness. Run against five years of confirmed vulnerabilities in clfs.sys, it re-found 96 % of them. In tcpip.sys, 100 %. A harness re-found almost everything human researchers took five years to find. The bugs were discoverable the entire time. There were never fewer of them. Nobody was looking hard enough, because looking was rate-limited by human attention rather than by how many bugs were actually there. The well was not draining. It was being sipped. What we are watching is not a bug explosion. It is a backlog, and the backlog is as old as the code. ## The capability is in the harness MDASH is over a hundred agents, multi-model debate across model families, and a separate pipeline that proves candidates before a human ever sees them. Microsoft reports it at 88,45 % on CyberGym, a benchmark for real-world vulnerability discovery. Anthropic's gated frontier model, Claude Mythos, is reported at 83,1 % on the same benchmark. I am not going to tell you the harness beats the model. Those two figures come from two different parties under conditions neither published, and five points is well inside what a difference in evaluation setup can produce. What the pair does establish is an order of magnitude: an orchestration layer running an ensemble, distilled models included, lands in the same range as the most capable model anyone has built. That has a consequence worth sitting with. Access to Mythos is controlled by Anthropic under Project Glasswing. Orchestration is controlled by nobody, and it is described in a public blog post. If the scaffolding carries that much of the capability, the interesting question is not how far open weights trail the frontier model. It is how far an open harness trails MDASH. Scaffolding is cheaper to copy than a frontier model. ## The same technology closed a bug bounty In January 2026 the curl project shut down its bug bounty. Twenty reports arrived in the first twenty-one days of the year. Not one was valid. Daniel Stenberg described it as being DDoSed. HackerOne submissions rose 76 % year over year through March, and roughly three quarters of them were noise. Google stopped taking AI-generated submissions to its open-source reward programme. GitHub tightened its requirements. So in the same six months, one organisation used AI to ship 1150 real CVEs and another was driven out of the bounty business by AI reports that were worth nothing. Same technology. The difference is the prove pipeline. Microsoft built one, with dedicated cloud infrastructure behind it. curl is volunteers, and volunteers cannot fund a filter, so the only move left was to close the door. ## Check it yourself The CVE counts and the severity split above come from one endpoint. No key, no account. https://api.msrc.microsoft.com/cvrf/v3.0/cvrf/2026-Jul Send an Accept: application/json header, count the Vulnerability array, read Threats for severity and CVSSScoreSets for the scores. Change the month and run it again. If my baseline of 383 is wrong, the file will say so, and I would rather you tell me than take my word for it. Note added July 16: one fair objection surfaced when this post was re-read with hostile eyes. The eight-month baseline includes the February outlier, the same kind of number the denominator section warns about. Excluding February, the baseline is 414 and the multiple is 2,8 rather than 3,0. The direction survives either denominator, and now both numbers are on the record. Note added July 17: this post tells you to run the query yourself, so it owes you the reason your numbers will not match mine. Microsoft keeps revising these documents after release. Re-pulled on 17 July 2026, May 2026 returns 1123 rather than 991, June returns 1205 rather than 1281, and July returns 1169 rather than 1150. The May document is on revision 2275 and June on revision 1141, both last revised on 15 July 2026. The eight baseline months have not moved, so the baseline of 383 stands. On the figures the endpoint returns today, July is 3,1 times the baseline rather than 3,0, April to July is 4234 CVEs or 11,1 months of output at the old rate, and June is still the peak. The table above is what the endpoint returned when I ran it, and the pull date is now part of the number. ## Why this matters if you are buying anything This is the method I sell, pointed at someone else. A vendor made a qualitative claim: volume will go up. The receipt was public, machine-readable and free the whole time. The gap between the press release and the API was the entire story, and closing it took an afternoon and no privileged access. That is what measurement is for. Not to catch anyone out. Microsoft's post is accurate, and the data supports the direction it describes more strongly than the post itself does. The point is that "higher volume" and "3,0 times, and the median CVE gained a full point of severity" are different sentences, and only one of them can be checked. Agent-readiness works the same way. A site can assert it is ready for AI agents. A scanner reads the site and returns a number. One of those is an opinion. ## Related - [Why agent-readiness should be measured, not asserted](/guides/measurement-led-agent-readiness) - [How to let an AI agent work in your repo without leaking your secrets](/blog/agent-secret-hygiene) - [When honesty and the checker disagree](/blog/honesty-and-the-checker) --- # How to let an AI agent work in your repo without leaking your secrets 2026-07-12 Coding agents now run with your shell. They read your files and run your build. They push commits under your name. That is the point of them. It also means every plaintext secret on your disk is readable by the agent, and by every backup or synced folder that copies your working directory. A token in a text file was a small risk when only you could read it. It is a larger one the moment something else is holding the keyboard. This is the question an agent-readiness audit asks about your product, turned inward. If you care how a third party exposes data to an agent, your own machine is the first place to get it right. Here is the posture I would defend, the reasoning behind it, and one Windows trap that cost me an afternoon. ## Keep secrets out of plaintext files The old habit is a token in a dotfile, a key in .npmrc, an unencrypted service account JSON sitting next to the code. It works because the file is only yours. An agent breaks that assumption. So does a leaked backup, a synced folder, or someone watching a screen-share. Move every secret into storage the operating system encrypts and scopes to your account. On Windows that is the Data Protection API. On macOS the Keychain. On Linux libsecret through the Secret Service. The value is encrypted at rest, only your logged-in account can decrypt it, and a copied file is useless to anyone else. Your scripts ask for the secret when they run instead of reading it off disk. ## Git credentials through a credential manager Most people still authenticate git with a personal access token pasted into a credentials file. Drop that. Use a credential manager that speaks OAuth, so the token lives in the OS store, refreshes on its own, and never lands in a file you can commit or copy by accident. One trap to know if you are on Windows and your forge is not GitHub. The common advice is git-credential-oauth with the wincred store. That store writes to Windows Credential Manager, which caps a single entry at 2560 bytes. Some forges issue OAuth tokens well past that, and the write fails with a bare "CredWrite failed" while fetch still works, so nothing looks wrong until you notice every command re-authenticating. Git Credential Manager handles the large token by splitting it across entries and refreshes it silently. If a self-hosted GitLab, Gitea, or Forgejo keeps opening a browser prompt on push, this is usually why. ## A small vault for everything else Credential managers are built to store one username and password per host. They are the wrong shape for an API key you set as an environment variable, or a private key you would rather not keep as a loose file. Some values also run past the size limit above. For those, a small file based vault does the job. Encrypt each value with the same OS primitive, keep them in one file, and give it a get command. A deploy script then reads the token when it runs, setting the environment variable from that call instead of from a file on disk. The file is encrypted and tied to your account, so a backup or a stray copy exposes nothing. Two caveats. A vault tied to your OS user cannot be decrypted after a reinstall, so keep an offline backup of anything you cannot regenerate, like a private signing key. And do not write your own crypto here. Call the OS primitive. It is audited, and it is the same mechanism your credential manager already trusts. ## Why this matters for buyers I build this into my own setup because I sell the audit that checks for it. A prospect who asks for an NDA is asking a real question about whether you treat access seriously or leave keys lying around while an agent works next to them. The honest answer shows in how you work, before it shows in any report. None of this is exotic. It is one habit applied everywhere. The operating system holds the secret, encrypted and scoped to you, and the code asks for it when it needs it. An agent can then do its work in your repo without ever seeing a key in the clear. ## Related - [Letting agents act on your data](/guides/letting-agents-act-on-data) - [AI agent use cases](/guides/ai-agent-use-cases) --- # How agent-ready are Finnish B2B sites? I scanned sixteen 2026-07-07 Over the past weeks I ran an independent agent-readiness scanner over sixteen Finnish company websites, mostly industrial and B2B, a few in healthcare. The scanner was isitagentready.com, which grades on a Level 0 to 5 scale. This is a small, non-random sample. The sites came from my own prospecting, not a statistical draw, so read it as a snapshot, not a census. The pattern was consistent enough to be worth writing down. ## Key figures - Sixteen Finnish B2B sites scanned with an independent scanner, isitagentready.com. - Almost all sites landed at isitagentready Level 1 of 5, a couple at Level 0, one at Level 2, none higher. - The three most common gaps: HTML-only pages with heavy token overhead, missing structured data, and no action or capability layer. - Largest measured token saving: about 16500 tokens of HTML where 1400 tokens of markdown carry the same content, a 91 percent saving. - The two sites that published a real llms.txt sat at the top of the range. ## The numbers On the isitagentready Level scale almost all of the sixteen landed at Level 1 of 5, the floor an ordinary CMS site reaches, a couple sat at Level 0, and only one reached Level 2. None reached Level 3 or above. To be clear about what that means, these are not broken websites. They load, they rank, a person can use them without trouble. The scanner measures something else, whether an AI agent can read the site and act on it. ## The three gaps that showed up almost everywhere Discoverability was usually fine, legibility was not. Most sites had robots.txt, a sitemap, sometimes explicit AI-bot rules, so an agent can find them. But the same sites served HTML only, often with heavy token overhead. One consumer-facing corporate site returned about 16500 tokens of HTML where 1400 tokens of markdown would carry the same content, a 91 percent saving. An agent can fetch the page, but reading it is slow and lossy. The second gap was structured data, or the lack of it. Missing JSON-LD and product data was common, so an agent reaches the site, sees a wall of markup, and cannot answer a plain question like what this company makes or sells. The third and most consistent gap was the action and capability layer. No markdown negotiation, no MCP server, no API discovery, no agent-auth metadata. One site that belongs to an AI company itself passed zero of eight checks in that discovery group. This is the layer that lets an agent move from finding a site to operating it, and it was absent almost everywhere. ## Why this matters now AI agents are becoming a discovery and transaction channel. When an agent reads a site and cannot parse or act on it, the business does not rank lower, it becomes invisible inside the answer. The sites in this sample are not behind on SEO, most rank fine. They are behind on the next thing, being legible and actionable to the agents that increasingly read on a person's behalf. The encouraging part is that the fixes are mostly known and mechanical. Serve markdown alongside HTML, add structured data, publish an llms.txt, expose the discovery manifests. Two of the sixteen had already started, they published a real llms.txt, and that is exactly why they sat at the top of the range. Note added July 17: one reading of the llms.txt point is circular, since the scanner scores llms.txt directly, so publishing one raises the score by construction. The observation stands as a description of the measured range, not as a causal claim about readiness. To check where a site stands, the free llms.txt validator is at turva.dev/llms-txt-validator, and the agent-readiness audit and advisory work is at turva.dev. ## Related - [Common agent-readiness gaps on marketing sites](/guides/agent-readiness-gaps) - [Why agent-readiness should be measured, not asserted](/guides/measurement-led-agent-readiness) - [What an agent pays to read your site](/blog/cheaper-pages-for-agents) --- # When honesty and the checker disagree 2026-07-06 During the line-by-line pass that read every line of this site, one of the smallest surfaces turned into the sharpest question in the audit. This site serves an auth.md file, a plain description of how an agent authenticates here. It said two things that did not sit together. One line read no issued credentials. Another said an API key is issued out of band on request. Both were trying to be honest, and side by side they were a contradiction. ## Cleaning up a signal made the scanner fail The obvious repair was to drop the credential machinery and let the file say the simple true thing, that nothing here needs a credential. So the agent_auth block lost its credential types, the fields that name what kind of key or token a service hands out. To a reader they looked like box-ticking, the sort of hollow detail an audit is meant to strip. Then the scanner failed. isitagentready.com runs a check on auth.md, and that check reports agent_auth metadata was not found the moment the block has no complete registration method. Its own published recipe requires at least one method, and every method has to declare the credential types it supports. Fields removed to look more honest read to the checker as no auth surface at all. The pass count for the whole site leans on that check, and gutting the block would have dropped the 100/100 the front page shows. ## Two honest stories, and the fork between them So there were two true things to write. This site really does issue no credential that any resource requires, and I could say exactly that and let the check fail. Or this site really does hand out an API key out of band when someone asks, and I could declare that key properly and keep the check green. Both are honest. The checker accepts only one of them. The tempting read is that the checker is the villain here, rewarding the file that ticks more boxes. That story is wrong. The credential the check wanted was not a fiction, because a key really does get issued on request. The first draft was dishonest for a different reason. A true detail sat next to a line that flatly denied it. ## The honest form is the precise one The fix was to make the whole block exactly true, rather than gut it or inflate it. The API key is declared and issued out of band on request. The file describes it for exactly what it is. It attributes correspondence and nothing more. No resource on this site requires it, and holding it unlocks no extra access. Two other fields went the other way and were deleted, because they were the real hollow signals. One named an access token the service never issues. The other named an events channel that does not exist. Those were claims with nothing behind them. The API key is a claim with a key behind it. That is the line between a hollow signal and a modest true one, and a scanner cannot draw it for you. It can tell that a field is present and parses. It cannot tell whether the thing the field describes is real. The judgment that took the longest landed on the surface that moved no score at all. ## What this leaves on the page auth.md now says one thing instead of two. The key it names is the key you get if you email and ask, and it labels the message and grants nothing. The fields that described things the service does not do are gone. The check reads green because the declaration is finally true. Nothing was padded to please it. For an agent-readiness audit that reads your agent-facing claims the way a skeptic would, contact info@turva.dev. ## Related - [How agents authenticate](/guides/agent-authentication) - [Why agent-readiness should be measured, not asserted](/guides/measurement-led-agent-readiness) --- # Four AI agents re-checked the guides 2026-07-04 The guides on this site describe other people's specifications, and specifications move. A sentence that says "the specification says" is true the day it ships and starts aging the day after, and no scanner will tell you when it has gone stale. So the four AI agents that read this site line by line came back for a second pass, all running Claude Fable 5, each taking one family of standards: the agent commerce stack, MCP discovery, the discovery files from agents.json to llms.txt, and the plumbing of authentication and response headers. Their job was to re-read every specification claim in those guides against the primary source behind it. ## What had moved The pass came back with one finding rated high, one medium and six small. The high one sat in the MCP guide. It described the server card proposal, SEP-2127, in the present tense, and the proposal had moved. As of July 2026 it sits on MCP's extensions track as an experimental extension, and the current draft recommends serving the card relative to the server's endpoint plus a catalog at /.well-known/mcp/catalog.json. Nothing in the old sentence was wrong when it was written. It stayed still while the proposal moved. The medium finding was quieter. The response-header guide leaned on the IETF draft for standard RateLimit headers, and that draft expired in March 2026 without a successor. The six small ones were wording: vocabulary that predated A2A 1.0, stale lines about the Open Knowledge Format, a Cache-Control nuance, and one phrase about ai-catalog.json contributors that had aged in two places at once, because a blog post here had quoted the guide. Update, July 16: the RateLimit sentence above was wrong when it was published. The draft had not expired, revision 10 was active in January 2026, and revision 11 from May 2026 remains active in the httpapi working group today. The response-header guide now cites the active draft. ## The sharpest findings were not in the guides Two of the machine-readable profiles this site serves had drifted from their own specifications, and that is a harder failure than stale prose, because these files exist for software and both had passed every scan since they shipped. The UCP profile used service keys in a namespace the specification reserves for its own governing body, and listed transports its enum does not contain. The MPP manifest declared a version field the protocol does not define. A scanner checks that a profile exists and parses. It does not check that the vocabulary inside it exists in the specification, so an invented key passes as easily as a real one. Both profiles are now in the specification's own shape, verified against the primary text and validated programmatically, and the scanner stayed green through the change. The honest form cost nothing. ## What the scores did not measure The scanner was re-run after the fixes. isitagentready.com reads Level 5, the same result as before the pass. The scores did not move in either direction, and that is worth pausing on. A score measures the shape of a site at scan time, and the currency of a sentence about somebody else's specification is outside every scanner's reach. If reading every line is part of the promise, somebody has to re-read the lines after the world moves. ## Claims now carry their date The lasting repair is anchoring. A guide claim about a moving specification now carries its date, as of July 2026, so when the specification moves again the sentence stays true as a dated statement instead of quietly turning false. The families that move fastest, agent commerce and MCP discovery, go back on a re-check schedule, because this pass showed the drift interval there is a matter of weeks. For an audit that reads your agent-facing claims against the specifications they cite, contact info@turva.dev. ## Related - [MCP server cards explained](/guides/mcp-server-card) - [Agent commerce discovery: A2A, AP2, and ACP](/guides/agent-commerce-discovery) --- # The page grew, the agent bill did not 2026-07-04 In late June this site published [a post on what an agent pays to read a page](/blog/cheaper-pages-for-agents), and the measurement in it said the homepage as markdown cost roughly a third of the HTML form. The most recent scan reports the same homepage at 10,320 tokens as HTML and 1,723 as markdown. That is a sixth of the cost, an 83% saving, and nothing in the meantime was done to improve the number. ## Where the weight came from Since that post went out the site has gained seven blog posts before this one, two tool pages, a feed, a share image for every page and related links at the end of every post. None of that was content negotiation work. It was ordinary growth, and it landed where growth always lands, on the human-facing page. Between the 1 July and 4 July scans alone the HTML form of the homepage went from 9,560 tokens to 10,320, about 8% heavier in three days. The markdown form went from 1,750 to 1,723. It got slightly smaller. ## Two surfaces, two growth rates The HTML form of a page carries everything a site accumulates: navigation, styling, social metadata, structured data and links to whatever shipped last week. Each of those earns its place for a human reader or a search engine. The markdown form carries the words and the links and nothing else, so it grows only when the actual content grows. Serve one surface to everyone and every agent pays for the whole accumulation on every visit. Serve both forms from the same URL and the costs come apart on their own, the human page free to get richer while the agent page stays at the price of the text. ## Read the number yourself The token split is not self-reported. It comes from scanning both forms of the page, and this site logs the pair after every deploy. The June post carried the measurement of its day and this one carries the measurement of 4 July. If the pattern holds, a later post will quote a wider gap still, because the human surface keeps accumulating and the text does not. For an audit that measures what agents pay to read your site, contact info@turva.dev. ## Related - [What an agent pays to read your site](/blog/cheaper-pages-for-agents) - [Serving markdown to agents](/guides/markdown-for-agents) --- # Moving the source from GitHub to Codeberg 2026-07-04 Status, July 26: the source is on GitHub only, at github.com/erekola. This post is the dated log of a move that later reversed, and the three updates at the end record each step in order. The account of the incident itself stands as written. The company page of this site tells a buyer they can read every line before hiring me. That promise depends on the source being reachable, and for two weeks it was not, in a way I could not see. This is the log of what broke and why the source moved to codeberg.org/erekola. ## Two weeks of 404s I could not see On June 18 GitHub's spam detection flagged my account. There was no notification. Logged in, everything looked normal and every repo was in place. Logged out, the profile and every repo returned 404, and the search API answered "flagged as spammy". Every public pointer at the source was dead for everyone except me: the homepage hero, the guides, the READMEs, the profile links. ## How it surfaced No scanner caught it. The agent-readiness scanner this site is measured with reads the site, not the code hosting, so every score stayed green while the trust chain behind those scores was broken. It surfaced on July 2 during a fact-check pass, when an AI agent followed the site's own "read the source" link without a logged-in session and got a 404. That is the trap in this failure mode: the owner is the one person who cannot see it. ## What GitHub said The support ticket had been open since June 18 with one virtual-assistant reply. On July 3 a human answered: the account had been "flagged by mistake" by their spam-detection scripts, and the flag was removed. The reply did not say what had triggered it. The response was polite and the fix was real. It also arrived after the source had already moved. ## What it cost The measurable part is two weeks of broken pointers. The probable part is worse. An inbound lead wrote in on the same day the flag landed, and my reply pointed them at the open-source Worker as proof of how I work. From that moment every source link I had sent them returned 404, and after one more exchange they went quiet. A silent failure hides its own cost on top of causing it: I cannot prove the 404s ended that conversation, and I cannot rule it out. ## Why the move, and why it stuck I moved the repos to Codeberg on July 2 with full history, updated every public link the same day, and deleted the GitHub account once the flag was lifted. Codeberg is run by a non-profit on open-source infrastructure, which I like, but that is not the reason. No host is immune to mistakes. The reason is what the incident showed about the failure mode: a silent flag, no notification, an appeal channel that took two weeks to reach a human, and a breakage only visible from outside my own session. A dependency that can fail that way gets treated accordingly. Source hosting now sits in the site's threat model like any other third-party dependency, and the monthly self-audit checks logged-out visibility of every external pointer, because no scanner runs that check for you. Update, July 7: GitHub is back, in a different role and on my own initiative. The account erekola now exists as a push mirror: every push lands on both hosts, and Codeberg stays canonical for fetch and for every source link on this site. The failure-mode reasoning above is unchanged, and losing the mirror would break nothing. Update, July 21: the roles flipped again, on my own initiative. Codeberg's repeated instability that month (a days-long server-side ref lock, a 503 outage) kept blocking work, so GitHub is canonical again and Codeberg is the push mirror. Every source link on this site points at GitHub now. The failure-mode reasoning above still stands, which is exactly why the mirror stays. Update, July 24: the mirror is gone. Codeberg published new Terms of Use this week that disallow cryptocurrency-related projects and projects whose code is mostly written with generative AI tools. This repo falls under both lines: the payment surface declares a real on-chain wallet, and the code is built with AI assistance. Deleting the mirrors myself the same day was cleaner than waiting for a takedown under rules the repos no longer fit. The source lives on GitHub only now. The failure-mode reasoning above still holds, but the fallback is no longer a second forge: the full source ships inside the deployed Worker, and offline backups remain. External pointers rot in ways your own monitoring does not see, so they get checked the way a stranger's agent reaches them: from outside, logged out, against the primary source. For an audit that checks a site the way a stranger's agent reaches it, contact info@turva.dev. ## Related - [Moving turva.dev off prerender.io](/blog/moving-off-prerender) - [Owning your fediverse identity](/blog/owning-your-fediverse-identity) --- # A free llms.txt validator 2026-07-02 turva.dev now has a free llms.txt validator at https://turva.dev/llms-txt-validator. Enter a domain and it fetches that site's /llms.txt, checks the structure against the format and reports each check as pass, warn or fail. Nothing is stored and there is no signup. ## What the format asks for llms.txt is a small format, and that is the point of it. One H1 line names the site. A blockquote under the title carries a one line summary. H2 sections group markdown links an agent can follow to the content itself. A file that follows this shape gives an agent a map of the site at a fraction of the cost of crawling it. ## What the validator checks - The file exists at /llms.txt and answers HTTP 200 - The response is plain text, not an HTML page - The first non-empty line is an H1 title - A blockquote summary follows the title - H2 sections group the content - Markdown links parse and use absolute URLs - The file stays small enough to be cheap to read The second check earns its place. A site that returns its 404 page with status 200 looks like it has an llms.txt until something actually reads it, and an agent that fetches markup where it expected markdown wastes its tokens on tags. ## Agents can use it too The same URL answers JSON. Send Accept: application/json with a url parameter and the checks come back as data, so the validator works in a script or an agent pipeline as well as in a browser: curl -H "Accept: application/json" "https://turva.dev/llms-txt-validator?url=example.com" ## One build note The first deploy failed its own self check. A Cloudflare Worker cannot fetch a URL served by a Worker on its own zone, so asking the validator about turva.dev started a request that could never return and timed out after eight seconds. The fix reads the same constant that serves /llms.txt instead of fetching it. External domains are fetched normally, and the validator was proven against the llmstxt.org file before this post went out. ## What it is not The validator reads one file and checks its shape. It does not measure whether agents can discover the site, read its pages as markdown, find its API or complete a purchase. That is audit territory, and an audit here runs a site against an independent scanner and manual review rather than one checklist. For an audit of the whole surface an agent sees, not just this one file, contact info@turva.dev. ## Related - [llms.txt explained](/guides/llms-txt) - [Serving markdown to agents](/guides/markdown-for-agents) - [What an agent pays to read your site](/blog/cheaper-pages-for-agents) --- # Free llms.txt validator Enter a domain and this page fetches its /llms.txt and checks the structure: the first non-empty line is an H1 title, an optional blockquote summary, H2 sections with link lists. Free, no signup, nothing stored. ## How to use it - In a browser: open https://turva.dev/llms-txt-validator and enter a domain - Without typing anything: https://turva.dev/llms-txt-validator?url=turva.dev runs the checks against this site's own file - As an agent: GET https://turva.dev/llms-txt-validator?url=example.com with Accept: application/json Both views list the same checks below. The browser page and this markdown twin are kept in sync deliberately. ## What it checks - The file exists at /llms.txt and returns HTTP 200 - The response is plain text, not an HTML error page - The file starts with an H1 title - A blockquote summary follows the title (recommended by the format) - H2 sections group the content - Markdown links parse and use absolute URLs - The file stays small enough to be cheap for an agent to read - No HTML markup in the file, since llms.txt should be plain markdown (HTML tags are flagged as a warning) ## What it does not do This is a structure check against the llms.txt format, not an agent-readiness score. A full audit measures discoverability, content accessibility, access control and more: see [services](/services), or start with [llms.txt explained](/guides/llms-txt). Only the target site's /llms.txt is fetched, following a redirect to the same host or its www twin when there is one. Agents can call this with Accept: application/json. All free tools on this site are collected on [the tools page](/tools). ## Frequently asked **What is llms.txt?** llms.txt is a plain text file at the root of a site that tells AI agents what the site contains and where the important content lives. It opens with the site name and a short summary, then lists the key pages as markdown links grouped under headings. This validator checks that structure. **What does the validator check?** Eight structural checks: the file exists at /llms.txt and returns HTTP 200, the response is plain text rather than an HTML error page, the file starts with an H1 title, the recommended blockquote summary follows it, H2 sections group the content, markdown links parse and use absolute URLs, the file stays small enough to be cheap for an agent to read, and the file carries no inline HTML, since llms.txt should be plain markdown. **Why is there no score?** Deliberately. Eight structural checks can honestly report pass, warn or fail, and a number stacked on top of them would look like an agent-readiness score without measuring one. Agent readiness is measured with an independent public scanner, published security scans and a manual review, which is the paid audit rather than this free check. **How does an agent call the validator?** GET https://turva.dev/llms-txt-validator?url=example.com with an Accept: application/json header returns the same checks as JSON. Only the target site's /llms.txt is fetched, following a redirect to the same host or its www twin when there is one, and the response carries a no-store header. **Does the validator store anything?** No. The fetched file is checked and discarded, the result goes back with a no-store header, and there is no signup. The validator reads the single llms.txt file, following a redirect to the same host or its www twin when there is one, and never crawls the rest of the site. **Can I run the checks in CI?** Yes. The same eight checks are published as an open npm package, turva-llms-txt-validator, with a llms-txt-validate command whose --json output matches this page's JSON exactly. One line in a pipeline, npx turva-llms-txt-validator your-domain.com --strict, fails the build when the file breaks. ## Related - [llms.txt explained](/guides/llms-txt) - [Serving markdown to agents](/guides/markdown-for-agents) - [Free tools for agent-readiness](/tools) --- # Free tools for agent-readiness Three tools this site publishes for anyone to use: an llms.txt validator, an embeddable agent-ready badge and a public read-only MCP server. All free, no signup, and each one works for an agent as well as for a person. ## llms.txt validator Checks a site's /llms.txt structure against the format and reports each check as pass, warn or fail. Nothing is stored. An agent gets the same result as JSON by calling the same URL with an Accept: application/json header. Open it at [turva.dev/llms-txt-validator](/llms-txt-validator), or [run it against this site's own file](/llms-txt-validator?url=turva.dev) without typing anything. The same checks run in CI as an open npm package, [turva-llms-txt-validator](https://www.npmjs.com/package/turva-llms-txt-validator), with a CLI and the same JSON shape. Source on [GitHub](https://github.com/erekola/llms-txt-validator). ## The agent-ready badge A small SVG badge a site can embed to show it meets public agent-readiness criteria, linking back to the criteria page. It is a self-declared claim and checkable by design: anyone can run the same public scanner against the displaying site at any time. Criteria and embed instructions at [turva.dev/badge](/badge). ## Public MCP server A read-only Model Context Protocol server at mcp.turva.dev/mcp over streamable HTTP. It exposes the service catalog and pricing, turva.dev's own agent-readiness score, the published web-security scan results and the engagement principles. No authentication, and its server card is published at /.well-known/mcp/server-card.json. ## Where to go next These tools cover the same surfaces an agent-readiness audit measures. The audit itself, with fixed prices, is on the services page. See [services](/services). ## Related - [llms.txt validator](/llms-txt-validator) - [The agent-ready badge](/badge) - [MCP server cards explained](/guides/mcp-server-card) --- # The agent-ready badge A small SVG badge a site can embed to show it meets public agent-readiness criteria, linking back to this page. The badge is served from turva.dev, the criteria are listed below, and anyone can re-check the claim by running the same public scanner. ## Who may display it - Sites that have completed a turva.dev agent-readiness audit - Sites that score 100/100 on a public agent-readiness scanner (isitagentready.com) ## What it is, and what it is not The badge is a self-declared claim against public criteria, not a certification. turva.dev does not police its use. The value of the badge is that the claim is checkable: the scanner can be run against the displaying site by anyone, at any time. ## How to embed it Copy this HTML where you want the badge to appear: agent-ready, criteria at turva.dev/badge The image is 216 by 36 pixels, dark background, under one kilobyte. ## If your site is not there yet An audit measures where you stand and lists what to fix first. Services and prices are on the [services page](/services). Email and you get a reply within one business day. All free tools on this site are collected on [the tools page](/tools). --- # Notes on AI agents and agent-readiness The work here is letting an agent read a site and act on a system safely. Each entry is dated, and anything that can be measured is checked against an independent scanner rather than asserted. - [My gate could not see a sixth](/blog/my-gate-could-not-see-a-sixth). 2026-08-04. - [A red reading that measured my own client](/blog/red-reading-that-measured-my-own-client). 2026-07-30. - [The checks that pass for the wrong reason](/blog/checks-that-pass-for-the-wrong-reason). 2026-07-29. - [Finishing the optional commerce checks](/blog/finishing-the-optional-commerce-checks). 2026-07-20. - [The twin is the page](/blog/the-twin-is-the-page). 2026-07-19. - [Every response promised a rate limit. Nothing enforced it.](/blog/enforcing-the-rate-limit-i-advertised). 2026-07-18. - [Microsoft said the patches would get bigger. I measured how much bigger.](/blog/measuring-the-ai-patch-surge). 2026-07-15. - [How to let an AI agent work in your repo without leaking your secrets](/blog/agent-secret-hygiene). 2026-07-12. - [How agent-ready are Finnish B2B sites? I scanned sixteen](/blog/agent-readiness-finnish-b2b). 2026-07-07. - [When honesty and the checker disagree](/blog/honesty-and-the-checker). 2026-07-06. - [Four AI agents re-checked the guides](/blog/re-checking-the-guides). 2026-07-04. - [The page grew, the agent bill did not](/blog/cheaper-pages-revisited). 2026-07-04. - [Moving the source from GitHub to Codeberg](/blog/moving-source-to-codeberg). 2026-07-04. - [A free llms.txt validator](/blog/free-llms-txt-validator). 2026-07-02. - [Agent access is now a setting](/blog/agent-access-is-now-a-setting). 2026-07-02. - [Publishing an ai-catalog.json for agentic discovery](/blog/publishing-an-ai-catalog). 2026-06-29. - [What the Open Knowledge Format is, and what it is not](/blog/open-knowledge-format). 2026-06-27. - [What an agent pays to read your site](/blog/cheaper-pages-for-agents). 2026-06-26. - [When an agent can prove it is Claude](/blog/verifiable-agent-identity). 2026-06-25. - [What makes an AI agent's decisions reliable](/blog/reliable-agent-decisions). 2026-06-22. - [Owning your fediverse identity](/blog/owning-your-fediverse-identity). 2026-06-21. - [Moving turva.dev off prerender.io](/blog/moving-off-prerender). 2026-06-20. --- # What the Open Knowledge Format is, and what it is not 2026-06-27 Google Cloud shipped the Open Knowledge Format a couple of weeks ago, and the posts about it are running ahead of the spec. OKF is described as your data models turned into plain markdown that humans and agents can read, with no catalog lock-in and no SDK. Most of that is true. Some of it is sold harder than version 0.1 earns. Here is the honest read. ## What it actually is OKF represents a body of knowledge as a folder of markdown files. Each file is one concept, with a block of YAML frontmatter and a free-form body. The only required field is type. The rest is optional and open. Concepts link to each other with plain markdown links, so the folder reads as a graph. It is vendor-neutral, a person can read it, and an agent can parse it without a client. Google Cloud published it in June 2026 as version 0.1. ## What it is not It is not a data-model format, even though that is how it is being pitched. A concept can be a metric, a runbook or an API just as easily as a table, so framing it mainly as a way to draw data models narrows it to the one use that makes a good demo. It is also not a semantic standard yet. Version 0.1 fixes the shape of the files, the folder, the frontmatter and the one required field. It does not fix what any field means or how two teams should agree on the same names. The spec itself is clear that this is structural interoperability, with the semantic half left to producers and to conventions that do not exist yet. A shared folder layout is real progress. It is not the same as a shared meaning, and that gap is the whole reason these formats are hard. ## Why it still matters The instinct behind OKF is the right one. It wants plain text an agent can read, owned by you, with no service sitting in the middle. It is the same move as serving markdown to agents and publishing an llms.txt, applied to the knowledge behind a site rather than the pages on it. Formalizing that pattern into something portable is useful even at version 0.1, because the alternative is every team inventing its own folder of context files and none of them agreeing. ## How it relates to what I do An agent-readiness audit asks whether an agent can read your public site. OKF is one layer in from that, the format of the data and context the agent works from once it is inside. The two belong together, and I expect the second to matter more over time, but they are not the same thing and I will not pretend a readiness score measures one by measuring the other. For now OKF is worth understanding and worth watching. It is early to rebuild a knowledge catalog around it. If you already serve clean text to agents, you are most of the way there already. For an audit of how legibly AI agents read your site and the data behind it, contact info@turva.dev. ## Related - [Serving markdown to agents](/guides/markdown-for-agents) - [Agentic Resource Discovery and ai-catalog.json](/guides/agentic-resource-discovery) - [llms.txt explained](/guides/llms-txt) --- # What an agent pays to read your site 2026-06-26 When an AI agent visits your site to check a price or finish a task for someone, it pays to read the page. That cost is counted in tokens, and a normal HTML page is expensive. Navigation, styling, scripts and structured data all arrive whether the agent needs them or not. The agent either spends its budget getting past that markup or runs out of room and reads only part of the page. Both outcomes are yours to deal with, because they decide whether the agent gets your facts right. ## Your surface sets the cost Most advice about agent token cost is aimed at the people building agents. Cache the prompt, route easy work to a cheaper model. That is real, but it misses the half of the bill that the publisher controls. If your page is heavy, every agent that reads it pays for that weight, on every visit. You cannot tune someone else's model, but you can decide how much your own content costs to read. ## The same page, served as clean text The mechanism is content negotiation. The site keeps serving its normal HTML to browsers, and when an agent asks for the markdown form of a page it gets the same content with the markup stripped out. Nothing is hidden and nothing is duplicated. One URL answers in the format the client asked for. On turva.dev the homepage as markdown costs roughly a third of the HTML, a couple of thousand tokens against several thousand. An llms.txt sits alongside it as a map of the whole site, so an agent can read the structure in one request instead of crawling it page by page. ## What it buys you A cheaper page is a more reliable one. When the content fits comfortably inside the agent's budget, the agent reads all of it instead of stopping halfway, so it quotes your real price and your real terms rather than a guess. For anything that ends in a transaction, that is the difference between a completed action and a wrong one. It also widens who can reach you. The assistants that answer questions and cite sources read better from clean text, so your pages are more likely to be used in full and represented accurately. The work an agent does against your site gets cheaper for whoever runs it, which makes you the easier site to integrate with when an agent is choosing where to act. The benefit is measurable. An independent scanner checks for markdown content negotiation and for an llms.txt, and the result shows up as a higher score in the categories that name it. You do not take the improvement on faith. You read the number before the change and after it. ## A small change that lasts None of this is a rebuild. It is a small piece of code at the edge that picks the response format from the request header, and it keeps working as the site grows. The Worker that does it on turva.dev is public, so you can read exactly what it does before deciding whether it belongs on your own site. For an audit of how cheaply agents can read your site, contact info@turva.dev. ## Related - [Serving markdown to agents](/guides/markdown-for-agents) - [Response headers that help agents](/guides/response-headers-for-agents) - [The page grew, the agent bill did not](/blog/cheaper-pages-revisited) --- # When an agent can prove it is Claude 2026-06-25 A site that wants to let an AI agent act has a problem it rarely says out loud. It cannot tell which agent is actually at the door. A user-agent string is just text, and anything can send it. An IP range drifts as providers move their infrastructure around. So the site guesses, and the guess collapses into one of two bad defaults. Block too much, and the helpful agent never reaches the page. Trust too much, and anything wearing the right header walks straight in. ## What the tag actually is Web Bot Auth is the piece that removes the guess. It comes from active work at the IETF and is already in production at Cloudflare, and it lets an agent prove who it is on every request. The agent generates a signing key and publishes the public half at a fixed location, /.well-known/http-message-signatures-directory. It then signs each request it sends. The receiving site, or Cloudflare at its edge, checks that signature against the published key. A match is a verifiable claim about the sender. Copying the header does not reproduce it, because only the holder of the private key can sign. Cloudflare calls the end-user-directed form of this a signed agent, and opened the program in August 2025 with a first cohort: ChatGPT agent, Goose, Browserbase, and Anchor Browser. The list lives in the public bots and agents directory on Cloudflare Radar, readable by anyone, customer or not. That public directory is the part that matters to me, because it makes the identity checkable by a third party instead of asserted by the agent itself. ## Where Claude stands today Claude is not on the signed list yet, and the gap is not academic. A site that switches on Cloudflare's Block AI Bots rule can, right now, block Claude's own request to a server it was asked to reach. Operators have run into exactly that and had to add a manual exception to let Claude back through, which is why there is an open request to register Claude as a verified bot. I am writing this ahead of the fact rather than after it, because the mechanism is live and the direction is set. The day Claude carries a signed identity, the request a site has to guess about today becomes one it can verify in a millisecond at the edge. Nothing else about the site has to change for that to pay off. ## Why this lands on my desk An agent-readiness audit has mostly answered one question: can an agent read this site. Verifiable identity adds the other half. Can the site tell which agent is reading, and admit it on purpose. The two questions are different, and the second one is where most marketing sites have nothing in place at all. The concrete uses are easy to name. Validate Web Bot Auth signatures at the edge instead of pattern-matching user-agent strings that anyone can fake. Base allow rules on the public directory rather than on IP lists kept by hand. The decision envelope, the set of actions an agent is permitted to take, should then turn on a verified identity rather than on an unverified claim. A site built this way can open a real capability to a known agent and keep it closed to everything else, without falling back on the blunt switch that blocks every bot at once. ## The honest version None of this is live for Claude on the day I publish this, and I will not write as though it were. The directory is public for a reason. Check it, and admit what it actually says rather than what a vendor page claims. When the entry appears, the work on the receiving side is already done, and the audit has a new line that can be measured rather than asserted. For an agent-readiness audit that covers how your site recognizes and admits AI agents, contact info@turva.dev. ## Related - [How agents authenticate](/guides/agent-authentication) - [The /.well-known directory for agents](/guides/well-known-for-agents) - [What agents.json is](/guides/agents-json) --- # What makes an AI agent's decisions reliable 2026-06-22 In the audits I have run, including this site's own, one thing keeps surfacing. An agent that is instructed well, and given the right settings and checks, can take in data and make the decision the rules call for, consistently. The capability is real, and it is wider than most of the conversation around it. The limits are rarely the model. They sit in two places that are easy to overlook. ## A decision is only as good as its inputs The decision an agent reaches is bounded by the data that reaches the agent. In a clean datacenter that is invisible, so it gets ignored. Move the same agent to where the work actually happens and it becomes the whole problem. A link drops as a crane passes over it. A satellite hop adds the better part of a second. One lost packet stalls every packet queued behind it, and the agent waits on stale input while the moment it needed to act goes by. The agent did not get worse. Its inputs did. Most of the reliability of an autonomous decision lives in the unglamorous layer below the model, where data either arrives in order and on time or it does not. A site or a system that wants an agent to act on live data has to earn that layer first. ## The right decision is the one the settings allow A correct decision is not an agent doing whatever it infers. It is an agent acting inside an envelope that was defined for it. The settings are the decision, made ahead of time by a person who knew the stakes. Draw the envelope loosely and a capable agent will still do something, just not the thing you wanted. Draw it well and the same agent is one you can leave alone. This is the part that gets skipped when people picture autonomy. They imagine judgment appearing from nowhere. In practice the judgment is front-loaded into permissions and thresholds, and into an explicit list of what the agent may touch and what it may not. Good autonomy looks less like a clever model and more like a well-set boundary. ## The hardest case is where no one can step in The clearest test of all this is the environment where a person cannot be in the loop. Distance and latency, with help too far away to matter in the seconds that count. When the round trip to a human is longer than the decision can wait, the decision has to be made locally, under rules agreed in advance. The fields that operate in those conditions worked this out first, because they had no choice. They learned to package a human expert's judgment into something a machine could carry to the far end and apply without asking. That discipline used to look exotic. It is now the same thing any team needs before it lets an agent act on a system that matters. ## The point is not to remove the person Autonomy is not the absence of people. The strongest setups take an expert's judgment and place it where the work is, then let the machine handle the parts that have to be instant or exact. The person sees what the agent sees and acts through the same channel, and the agent extends their reach instead of standing in for them. This is why I have stopped describing my work as only agent-readiness. Reading a site is the first step, the precondition for everything after it. What an agent can actually do once the inputs are clean and the envelope is set, with a person kept where judgment belongs, is the rest of the distance. That is the work I am moving toward. For an agent-readiness audit, or a conversation about letting agents act on your systems safely, contact info@turva.dev. ## Related - [Letting agents act on data](/guides/letting-agents-act-on-data) - [AI agent use cases](/guides/ai-agent-use-cases) - [Agentic commerce readiness](/guides/agentic-commerce-readiness) --- # Agent access is now a setting 2026-07-02 On 1 July 2026 Cloudflare shipped its second Content Independence Day package: crawler controls that split search, agent and training bots for every customer, a research program that tells crawlers which pages actually changed, experiments that turn Pay Per Crawl into Pay Per Use, and a waitlist for a gateway that charges for any resource over x402. Read together, they move decisions that used to live in a site's code into the CDN dashboard. That relocation is what matters for agent readiness. ## The edge can undo everything the page does right A site can serve clean markdown, an llms.txt, structured data and signed manifests, and none of it counts if a network rule turns the crawler away before the request reaches the page. Cloudflare says more than 20% of the web sits behind its network, and the new controls ship with per-crawler block toggles and defaults that change over time. This site's own crawler list turned out to contain seven blocked entries, including the Internet Archive and an AI search engine that pays publishers. However they got there, nothing in the markup shows it. You find it in the dashboard, or when your content stops appearing in answers. An agent-readiness review therefore has to read the edge configuration next to the content. robots.txt, the WAF and the AI crawler list must say the same thing the content strategy says, and they must keep saying it, because platform defaults move without a deploy. ## Citations are replacing clicks, and both are measurable now Cloudflare's stated reason for the package is a 2025 Pew Research Center finding: when Google shows an AI summary, users click a traditional result 8% of the time and a link inside the summary about 1% of the time. The visit is no longer where the value moves. Cloudflare's response is to make the citation itself payable. Ceramic.ai pays publishers per query their content answers, You.com lets agents buy individual premium pages, and participating sites get reporting on which AI-search queries surfaced their content, down to the page and the snippet. The reading this is meant to price is already routine. Over the past seven days this site answered 604 requests from identified AI and search crawlers, and AI answers and search referred 88 human visits (Cloudflare edge data), most from Google, the rest led by Meta, DuckDuckGo and Bing. Whether that reading starts to pay is what the new programs will test. ## Payment rails are becoming configuration The Monetization Gateway waitlist points the same direction: charge for any page, dataset, API or MCP tool behind Cloudflare, settled over the x402 protocol, with no payment stack of your own. Charging an agent moves from an engineering project to a setting. The honesty bar moves with it. An x402 surface that quotes terms no agent can complete gets found out by the first agent that tries, which is why the x402 endpoint on this site answers HTTP 402 with its real terms instead of a pretend checkout. ## What to check this week - Open your CDN's AI crawler list and compare it against your intent. A block you did not choose is configuration drift, and it overrides everything your pages declare. - Re-scan after any edge change. The public agent-readiness scanners read a site from outside, so a network-level block shows up as a dropped score before a buyer sees the gap. - If your content earns citations, look at the Pay Per Use programs. The reporting alone, which queries put your pages into AI answers, is visibility data you cannot get anywhere else today. For an agent-readiness audit that reads the edge configuration next to the content, contact info@turva.dev. ## Related - [What an agent pays to read your site](/blog/cheaper-pages-for-agents) - [x402 and agent payments](/guides/x402-agent-payments) - [Sitemaps, robots.txt and agent access](/guides/sitemaps-and-robots-for-agents) --- # Publishing an ai-catalog.json for agentic discovery 2026-06-29 Google and a Linux Foundation working group published Agentic Resource Discovery in 2026, an open specification for telling agents what a site offers in one machine-readable file at /.well-known/ai-catalog.json. turva.dev now serves one. This is the log of adding it, and of why the change could not move the scanner score either way. ## What the file says The manifest is a small envelope with a specVersion, a host block, and an entries array. Each entry names one agentic resource with an identifier, a type, a url, and a description. turva.dev publishes four entries, and every one points at a surface that already resolves: the MCP server card, the A2A agent card, the OpenAPI description, and the agent skills index. Nothing in the catalog is aspirational. If a line names a resource, that resource answers. ## Why it is additive The catalog is a new file and a new route. It does not change a single existing surface, so it cannot lower a score, and because the independent scanner does not check for ai-catalog.json yet, it cannot raise one either. turva.dev already reads Level 5 on isitagentready.com, and it read the same after this change. The point of publishing now is not the number. It is that a Google-backed discovery standard exists, and a site that sells agent-readiness should serve the surface before its buyers ask for it. ## Discovery, not ranking An ai-catalog.json is easy to misread as another search file. It is not. It indexes the agentic resources a site exposes so an agent can find them and call each one through its own protocol. Google has said publicly that llms.txt does not affect its search results, and the same holds here. Agent-readiness and search ranking remain different things, and neither should be sold as the other. ## Honest about adoption In a June 2026 check I ran against their public well-known paths, none of the companies named as contributors to the specification yet served a discoverable ai-catalog.json. The specification is an early draft and adoption is near zero. That is the honest frame for this post. turva.dev is early rather than late, and being early on a verifiable standard is a position worth holding when the work is open source and readable line by line at github.com/erekola/turva-worker. For an audit of a site's discovery surface, contact info@turva.dev. ## Related - [Agentic Resource Discovery and ai-catalog.json](/guides/agentic-resource-discovery) - [The /.well-known directory for agents](/guides/well-known-for-agents) - [MCP server cards explained](/guides/mcp-server-card) --- # Moving turva.dev off prerender.io 2026-06-20 For a while the turva.dev homepage was rendered by a third party. The page was built on Sitejet, served to people as a JavaScript app, and served to agents through prerender.io, which returned a finished HTML snapshot so a crawler did not read an empty shell. It worked and it scored well, but it was a workaround. A site that sells agent-readiness should not depend on a separate service to be readable by agents. Today the homepage moved into the Cloudflare Worker that already fronts the domain. The Worker renders the finished HTML itself, on every request, at the edge. There is no client-side hydration step and no prerender hop. An agent reads the real content in the first response, and so does a person. ## What the Worker returns The Worker decides by the request. A browser asking for HTML gets the rendered page. An agent that sends Accept: text/markdown gets a markdown version of the same content, at a fraction of the tokens. An agent that sends Accept: application/json gets a structured summary of the business and its services. The same facts, in the form the client asked for. ## What this removed The prerender.io branch is gone from the Worker. No request is sent to an external prerender service, and the token it used is no longer read. Sitejet now serves only static assets such as the social image, and those move to the Worker next. The page is one codebase, under version control, open source at github.com/erekola/turva-worker. ## The result is measured, not asserted The change was verified the same way the service verifies client work: by an independent scanner, before and after. isitagentready read Level 5, Agent-Native. The homepage migration did not drop a point. One more note. This change was planned and deployed in a single session with an AI agent, and the result was checked by an independent scanner with no stake in the outcome. The claims on this site are measurements anyone can reproduce. Either the next scan reads the same or higher, or it does not. Written contact only. Email info@turva.dev, Signal @turva.19. First reply within one business day. ## Related - [Prerendering and why agents see empty pages](/guides/prerendering-for-agents) - [Serving markdown to agents](/guides/markdown-for-agents) - [What an agent-readiness audit is](/guides/agent-readiness-audit) --- # Agent commerce discovery: A2A, AP2, and ACP Before an AI agent can transact with a site, it has to discover what the site supports and how to reach it. Three machine-readable surfaces carry that information: an A2A Agent Card, an AP2 declaration, and an ACP discovery document. Each answers a different question, and an agent reads them before it sends a single commerce request. ## The A2A Agent Card An A2A Agent Card is a JSON file, usually at /.well-known/agent-card.json, that describes an agent interface. It states the agent's name, version, and description, the interfaces it exposes, each with a service URL and a protocol binding, the capabilities it declares, and the skills it offers, each skill carrying an id, a name, and a description. The Agent2Agent protocol uses the card so one agent can discover another and know how to reach it. The card is most useful when its skills mirror surfaces an agent can already reach, such as a service catalog or contact information. A skill that points nowhere is worse than no skill at all. ## AP2 and the version that matters AP2 is the Agent Payments Protocol. Under the v0.1 specification, which is what deployed sites and scanners still validate against, a merchant declares support not as a separate file but as an extension entry inside the A2A Agent Card. The entry carries the extension URI, a role such as merchant, and a flag saying whether an agent has to understand the extension. The detail that trips people up is the URI. Some helper guides write it as github.com/google-agentic-commerce/AP2/tree/v0.1.0, with an uppercase name and a three-part version. The v0.1 specification uses github.com/google-agentic-commerce/ap2/tree/v0.1, lowercase, version v0.1. A scanner that validates against that specification rejects the uppercase form even when everything else is correct. Copy the URI from the spec, not from a fix message. Note that the current AP2 specification, v0.2 from April 2026, restructures the protocol around checkout and payment mandates and drops the Agent Card extension entirely. The deployed discovery convention and the scanners still follow v0.1, so publish the v0.1 declaration for discoverability today and expect this surface to change as v0.2 adoption arrives. ## ACP discovery and checkout ACP is the Agentic Commerce Protocol, and it has two parts that are easy to confuse. The first is a discovery document at /.well-known/acp.json, which started as a proposal-stage RFC and entered the released specification with the 2026-04-17 snapshot. The second is the checkout API the document points to. The discovery document is small and strict. It states the protocol name acp and a version, the api_base_url, a transports array, and a capabilities.services array. The services value is a closed set of strings such as checkout, not a list of product objects. Sending the wrong type is the most common reason an otherwise complete document fails validation. A discovery check usually reads only the document, not the checkout endpoint behind it. That makes it tempting to declare a service the site does not implement, because the check passes either way. An agent that trusts the document and calls the checkout URL would then reach nothing. ## A minimal honest checkout A checkout endpoint does not have to support instant payment to be real. The ACP checkout session carries a status field, and one of its values is not_ready_for_payment. A site that sells through a written quote can create a genuine session, return it in that state, and attach a message that the engagement is confirmed in writing first. The agent receives a well-formed session that reflects how the business actually works, and the discovery claim holds because the endpoint behind it answers. ## Publish what is true These surfaces exist so an agent can act without guessing, which only holds when every claim resolves to something real. A card whose skills lead nowhere breaks the same way a checkout that never responds does, because the agent follows the signal and finds nothing. Publish what is true, and back each declaration with a surface that answers. turva.dev publishes an A2A Agent Card, an AP2 merchant declaration, and an ACP discovery document, and an independent scanner verifies that those documents are published. The checkout endpoint behind the discovery document answers as well, which is the part the scanner does not read. For an audit of a site's agent commerce surface, contact info@turva.dev. ## Frequently asked **What is an A2A Agent Card?** An A2A Agent Card is a JSON file, usually at /.well-known/agent-card.json, that describes an agent interface, including its name, version, transport, and the skills it offers, so another agent can discover it and know how to reach it. **What is the correct AP2 extension URI?** AP2 support is declared as an extension inside the A2A Agent Card, using the URI https://github.com/google-agentic-commerce/ap2/tree/v0.1 (lowercase, version v0.1). Some fix texts show a V0.1.0 form with a capital V and an extra .0, which validators reject. ## Related - [x402 and agent payments](/guides/x402-agent-payments) - [The /.well-known directory for agents](/guides/well-known-for-agents) --- # Owning your fediverse identity 2026-06-21 turva.dev runs on one rule: own the surfaces that carry your value, do not rent them. That rule moved the homepage off a third-party renderer, and it applies to identity too. My fediverse handle is now [@erik@turva.dev](https://social.turva.dev/@erik), on infrastructure I control, not a username on someone else's server. ## Why the handle matters A platform handle is a dependency. If the server you joined changes its rules, slows down, or shuts off, your identity and your followers are stuck on it. The same logic that says frontier model access is not a moat says a platform username is not an identity. The address people use to find you should resolve to a domain you own. ## How the split works Mastodon lets the handle domain and the server domain differ. The account lives at social.turva.dev, but the handle is [@erik@turva.dev](https://social.turva.dev/@erik). For that to work, turva.dev has to answer the discovery requests a remote server makes before it can reach the account. The Cloudflare Worker that already fronts the apex does this. It redirects the well-known paths the fediverse asks for, host-meta and webfinger and nodeinfo, to the instance. Everything else the apex serves stays exactly as it was: the guides, the markdown, the agent manifests, the structured data. The same Worker that makes the site legible to agents now also carries the identity. ## Verified, not asserted The profile links to turva.dev, and turva.dev links back to the profile with a rel="me" relation. Mastodon checks both directions and marks the link verified. It is the same standard as the rest of the site. The claim is checkable rather than taken on trust. ## The principle Identity is infrastructure. If it lives on a domain you own, you can change servers, change hosts, or self-host later without changing your address or losing your followers. Renting the frontier is fine. Renting your name is not. Find me on the fediverse at [@erik@turva.dev](https://social.turva.dev/@erik). For an agent-readiness audit, contact info@turva.dev. ## Related - [The /.well-known directory for agents](/guides/well-known-for-agents) - [How agents authenticate](/guides/agent-authentication) - [What agents.json is](/guides/agents-json) --- # Audits and advisory for products that AI agents read and act on Agent-readiness is the measurable starting point, scored by an independent scanner. The wider work is the data those agents depend on and the decisions you let them make. Both are measured before they are promised. 100/100 and Level 5, Agent-Native, on isitagentready.com, Cloudflare's agent-readiness scanner. Business ID 3600281-7, registered in Finland. ## Audits, advisory, and implementation for product teams An AI agent does not browse a site the way a person does. It reads machine-readable surfaces and acts on the parts it can reach, once it trusts what it found. I measure how a site, an API or a product holds up to that, fix what the measurement names, and stay on as the product changes. The measurable core is agent-readiness, scored by an independent scanner and provable on the next scan. The wider work begins where readability ends. The data an agent acts on has to arrive intact, and the decisions it is allowed to make have to sit inside a boundary you set. The first makes an agent able to read you. The second makes it safe to let one act. ## Two fixed-scope ways to start Both diagnoses are bought at a fixed price against a written scope. Neither one requires the other. - [Shopify agent storefront check](/shopify-agent-storefront-check). €1,900. One live Shopify store, read across the three agent surfaces this check covers, delivered in 48 hours. - [Agent-readiness audit](/services). €6,500. A whole site or API, measured by an independent scanner, delivered in two to three weeks. What follows a diagnosis is scoped separately, and that work is listed on the [services page](/services). ## Independent agent-readiness scan of turva.dev Scanner: isitagentready.com (third party, Cloudflare). Discoverability, Content Accessibility, Bot Access Control, and API, Auth, MCP and A2A Discovery: 100/100. Commerce: 100/100. Verified 100/100, Level 5, Agent-Native. ## Where this applies The pattern is narrow, but where it fits is not. Anywhere data moves and a decision follows, an agent can be the thing that reads the data and makes the call, as long as the inputs are clean and the envelope is set. A few examples: - An agent reading a product catalog and completing a checkout for a buyer. - An agent watching an API and acting the moment a threshold is crossed, without waiting for a person. - An agent guiding a technician in the field, working from the same data the expert would. - An agent triaging incoming requests and resolving the routine ones on its own. - An agent operating a remote system over a link that drops, holding its last safe state until the data returns. These are examples. The same discipline carries from one case to the next, so the question is rarely whether an agent could do the work. It is whether the data reaching it and the limits set around it are good enough to trust. ## Evidence turva.dev is my own reference build. It reaches 100/100 and Level 5, Agent-Native, on isitagentready.com. Measured 2026-08-01. - isitagentready.com: 100/100, Level 5 (Agent-Native). https://isitagentready.com/ isitagentready.com is Cloudflare's agent-readiness scanner, and this site runs on Cloudflare Workers. Independent means independent of turva.dev: the scanner is not run or influenced by this business. Commerce here is quote-on-request. turva.dev declares its payable services in the 402 challenge, priced in USDC on Base via x402, and in the OpenAPI discovery, priced in euro as a card checkout link, and settlement is confirmed out of band rather than executed automatically, so the site serves a real payment surface and claims no capability it does not have. The agent-readiness scanner is public and can be run again at any time, by a person or by an agent. The scanner is the source. This page only reports what it returned. To check the number independently, run isitagentready.com against turva.dev. turva.dev publishes its own security scans too, on the same principle that the result should be measurable rather than asserted. Measured 2026-08-04. - Hardenize: all 13 categories passed. https://www.hardenize.com/report/turva.dev - Internet.nl website test: 98/100. IPv6, DNSSEC and RPKI pass in full. The single deduction is one HTTPS sub-test, the hash function for key exchange. https://internet.nl/site/turva.dev/ - Internet.nl email test: 95/100. IPv6, DNSSEC, and DMARC with DKIM and SPF pass in full, as does RPKI. The deduction is in the cipher configuration of the receiving mail servers, which my mail provider operates. https://internet.nl/mail/turva.dev/ The Cloudflare Worker that produces these results is open source: https://github.com/erekola/turva-worker. You can read every line before you hire me. Backed by a registered business, publicly verifiable: Business ID 3600281-7, registered in Finland. PRH/YTJ business register: https://tietopalvelu.ytj.fi/yritys/3600281-7 ## The process has three stages and no surprises First, measurement. For agent-readiness, an independent scanner reads the current state of the site or API and produces a numeric baseline with a categorized list of what is missing. For the wider work, the data path and the decision envelope are tested the way an agent would hit them, so the starting point is a fact rather than an opinion. Then a written report. Three to ten priority fixes in order of impact, with technical reasoning written so the reader does not need a background in any of this to follow it. Then the fixes. I implement them, or your engineering team does the work with the report as the spec. Both routes are supported and the choice is yours. All communication runs async. No calls and no calendar links. Live meetings are not part of how this work is done. Short questions go through Signal, longer documents through email. Everything stays in writing, which means the work and the trail are auditable end-to-end. Production credentials are not requested. Write access to repositories is not taken by default. Read access is enough for the audit, and write access is scoped per task if implementation is purchased separately. The result is checkable, not asserted. For agent-readiness that is the scanner number, higher on the next scan in the categories and by the dates the report named. For the wider work it is the same test, the data path holding under load and the envelope doing exactly what it claims. Either the next measurement confirms it or it does not. ## Services - Shopify agent storefront check. €1,900. Fixed scope. What an AI shopper receives from one live Shopify store, across browser WebMCP, remote MCP and Agentic channels. Four written deliverables in 48 hours, and a retest within 14 days. - Audit. Fixed scope. Two to three weeks. An independent scanner runs against the site or API. Written report with a prioritized fix list. You receive a measured baseline and a clear "do this first" plan. - Advisory. Monthly retainer, async-only. Ongoing review as the site, API or product evolves. Each scanner cycle reads higher than the last, or the report explains why a tradeoff was kept on purpose. - Implementation. €1,500 per day. Changes at the edge, well-known manifests, MCP server work, JSON-LD and Schema fixes. The improvement is verifiable against the audit baseline in the next scan. - Agent operations. On request. The work beyond readiness: the data an agent acts on, and the decision envelope of permissions and thresholds that bounds what it is allowed to do. - MCP server design. On request. Read-only discovery tools and streamable HTTP transport. For public, non-sensitive data, no auth surface and no logging by default. Auth and an audit trail follow the data and the misuse model. The endpoint stays readable for agents and does not turn into an abuse vector. ## Who I am The work is done by one person under a registered business. My background is engineering: measurement, testing, and reducing things to what actually matters. I have worked in international companies for years, and I keep only the tools and methods that hold up when the output is checked line by line. The work stays measurable on purpose. Agent-readiness is a property a scanner reads, higher next week than this week or not. The wider work holds to the same test. The data an agent acts on arrives intact or the test says where it broke, and the boundary you set holds to exactly what it claims. ## Contact Written contact only. Email for longer messages, Signal for short questions. The first reply is in writing within one business day. No calls and no calendar links at any stage of the engagement. - Email: - Signal: [@turva.19](https://signal.me/#eu/2qzayURnxbJ8wl7dmQOd5c3sAF7cW8xvDVUrNiG6Cl7rEsXfkSlIsYOS9FSjJixK) - LinkedIn: https://www.linkedin.com/in/erikrekola/ ## Frequently asked **What does agent-readiness mean?** Agent-readiness is a measurable property of a site, an API, or a product surface. It describes how well AI agents can discover, read, and operate it. **How much does it cost?** Prices (EUR, VAT not included): Shopify agent storefront check €1,900 fixed price, Audit €6,500 fixed price, Advisory €3,000/month (minimum 3 months), Implementation €1,500/day scoped per task. Final price is confirmed in writing after scope is agreed. **Do I need to share production credentials?** No. Production credentials are not requested. Read access is enough for the audit. **Will you sign an NDA?** Yes. Send your own and it is signed as it stands before any material moves, at no charge. Client material is deleted within thirty days of the engagement closing, unless retention is required by law. **Are there calls or video meetings?** No. Engagement is async-only. No calls and no calendar links at any stage. **How long does the audit take?** The audit is fixed scope, 2-3 weeks. **Can our engineering team implement the fixes?** Yes. The audit report is the spec. Either I implement or your team does the work with the report as the spec. **How is the result verified?** The result shows up in scanner numbers. The next scan reads higher than the previous one in the categories the report named. **How do I get in touch?** In writing: email info@turva.dev or Signal @turva.19. First reply within one business day. ## Markdown views You are reading the markdown view of this page, served with Accept: text/markdown content negotiation. Every page on this site has one, at the same URL, at a fraction of the token cost of the HTML. ## More - [Services](https://turva.dev/services) - [Free tools](https://turva.dev/tools) - [Company](https://turva.dev/company) - [Contact](https://turva.dev/contact) - [Legal](https://turva.dev/legal) - [Agent registration](https://turva.dev/auth.md) ## Guides - [Agent-readiness guides](https://turva.dev/guides) - [What an agent-readiness audit is](https://turva.dev/guides/agent-readiness-audit) - [How to get your site cited by AI assistants](https://turva.dev/guides/get-cited-by-ai-assistants) - [llms.txt explained](https://turva.dev/guides/llms-txt) - [MCP server cards explained](https://turva.dev/guides/mcp-server-card) - [What agents.json is](https://turva.dev/guides/agents-json) - [x402 and agent payments](https://turva.dev/guides/x402-agent-payments) - [Response headers that help agents](https://turva.dev/guides/response-headers-for-agents) - [SEO and agent-readiness are not the same](https://turva.dev/guides/seo-vs-agent-readiness) - [Agent-readiness, AEO and GEO: how they relate](https://turva.dev/guides/agent-readiness-aeo-geo) - [Letting agents act on data: the decision envelope](https://turva.dev/guides/letting-agents-act-on-data) - [AI agent use cases: where agents read data and make decisions](https://turva.dev/guides/ai-agent-use-cases) - [JSON-LD and structured data for agents](https://turva.dev/guides/json-ld-structured-data) - [The /.well-known directory for agents](https://turva.dev/guides/well-known-for-agents) - [Agentic Resource Discovery and ai-catalog.json](https://turva.dev/guides/agentic-resource-discovery) - [How agents authenticate](https://turva.dev/guides/agent-authentication) - [Why agent-readiness should be measured, not asserted](https://turva.dev/guides/measurement-led-agent-readiness) - [Prerendering and why agents see empty pages](https://turva.dev/guides/prerendering-for-agents) - [Sitemaps, robots.txt and agent access](https://turva.dev/guides/sitemaps-and-robots-for-agents) - [Serving markdown to agents](https://turva.dev/guides/markdown-for-agents) - [Open Knowledge Format (OKF) explained](https://turva.dev/guides/open-knowledge-format) - [Common agent-readiness gaps on marketing sites](https://turva.dev/guides/agent-readiness-gaps) - [Choosing an agent-readiness audit](https://turva.dev/guides/choosing-an-agent-readiness-audit) - [Agent commerce discovery: A2A, AP2, and ACP](https://turva.dev/guides/agent-commerce-discovery) - [Agentic commerce readiness: selling to AI shopping agents](https://turva.dev/guides/agentic-commerce-readiness) --- # Two fixed-scope diagnoses, and the work that follows Async-only. One business day response. All prices exclude VAT. Two of these are diagnoses you can buy on their own, each at a fixed price and a fixed scope. The Shopify agent storefront check reads one live Shopify store, the audit reads a whole site or API, and neither one requires the other. Everything after them is the work a diagnosis identifies, scoped separately. ## Shopify agent storefront check **€1,900. 48 hours. Fixed scope.** What an AI shopper actually receives from one live Shopify store, tested across the three agent surfaces this check covers and reported with the evidence attached. What you get: - A three-surface map of browser WebMCP, remote Storefront and UCP MCP, and Agentic channels - A product truth matrix comparing what each surface says about the tested products - Buyer-journey evidence with the tool, the input, the observed result and the exact stop before payment - A prioritised correction plan of up to five changes, each with an owner and an acceptance check - One retest of up to two corrected items within 14 days What you do not get: - Calls or meetings - Implementation of the corrections, which is a separate engagement - A penetration test, or any Shopify, MCP, WebMCP or UCP certification - A test order, because the cart lifecycle stops before payment The audit is not a prerequisite. The full scope, the exclusions and the preflight are on the [product page](/shopify-agent-storefront-check). Suited for D2C Shopify stores that want documented evidence of what an agent receives from them today. ## Audit **€6,500. Two to three weeks. Fixed scope.** A measurement of how agent-ready your site and APIs are today, with a prioritized list of what to fix first. What you get: - An independent scanner runs against the site or API - Manual review of /.well-known/ manifests, JSON-LD, head metadata and HTTP headers - Review of robots.txt, sitemap.xml, ai.txt and llms.txt against current agent norms - A live check of how AI assistants and agents retrieve and answer questions about the site or API today, across several AI platforms (answer engine optimization, AEO) - Written report with findings ranked by score impact and implementation cost - One round of written follow-up questions How it is measured: - Every agent-readiness check an independent scanner runs, recorded per check rather than as one headline number - A fixed question set put to several answer engines, recording whether they name your site when asked about your category rather than by name - Your published web security scans, so the report rests on measurements you can re-run yourself What you do not get: - Calls or meetings - Implementation of the fixes (separate engagement) - Ongoing monitoring (separate engagement) Levels move with the check set. The same site can read Level 1 on a full run and Level 2 on a narrower one, so the report names the checks that failed and what each one costs to fix, and leaves the headline number out of it. Large sites are covered in full. If a site is big enough that the live checks reach a tool quota, the quota is raised rather than the coverage reduced. Once the audit is complete, the fixes it lists are typically about a day of implementation work, whether your team does them or I do. The audit is what identifies that day of work and orders it by impact. Suited for teams that want a clear picture of where they stand before deciding what to do about it. ## Advisory **€3,000 per month. Monthly retainer. Minimum three months.** Ongoing input on agent-readiness as part of your product roadmap, with tracking of how the scores change over time. What you get: - Monthly re-scan and score delta report - Monthly AI-visibility delta from the same question set re-run across several AI platforms (answer engine optimization, AEO) - Written review of any agent-readiness related work your team ships, within one business day - Roadmap input on what to ship next and why - Async channel for questions (email or shared doc) - Quarterly summary of measurable progress What you do not get: - Calls or meetings - A promised score, because the check set changes when the standards do The monthly re-run uses the same measurement as the audit, so a delta means something. A number that moved for a reason nobody can name is not progress, and the review says which change moved it. Suited for teams treating agent-readiness as an ongoing product responsibility rather than a one-off cleanup. ## Implementation **€1,500 per day. Scoped per task.** Hands-on work on the fixes the audit identified, or new agent-ready infrastructure built from scratch. The audit comes first, because the day is spent building rather than diagnosing. Your traffic runs through an edge worker I deploy in front of your origin, and the access to do that exists before the day starts. Cloudflare Workers is the default, because that is what this site runs on. Any edge runtime that executes your code in front of the origin does the same job, Fastly Compute, Akamai EdgeWorkers, AWS Lambda@Edge and the edge functions on Netlify and Vercel included, so tell me which one you run when we scope the day. The worker adds agent surfaces beside your site, and it does not touch your application. Typical work: - Head metadata and /.well-known/ files served at the edge - robots.txt with AI crawler rules and Content Signals, and a Web Bot Auth directory - Markdown content negotiation, so a request asking for text/markdown gets markdown while a browser still gets HTML - An agent skills index, auth.md and an API catalog - JSON-LD generators for product, organization and article schemas - ai.txt and llms.txt authoring - Signed content and agent authentication patterns What a day does not cover: - DNS records for agent discovery, which need your DNS rather than an edge worker - Tool declarations inside your pages, which are application work - Agent commerce protocols, which need working payment flows behind them - MCP and agent-to-agent cards, which point at a running server and are priced as their own engagement You check the work yourself. Run the scanner before the day and after it, so the result is a number you produced. I do not promise a readiness level, because the level moves depending on which checks are run. Scoped repository write access per task. No retainer. ## Agent operations **Price on request. Scoped per engagement.** The work beyond readiness, for teams moving from "an agent can read us" to "an agent can act on a system that matters." Two things decide whether an agent acts correctly. The data it works from has to arrive intact, even over links that drop or lag. And the decisions it is allowed to make have to sit inside an envelope of permissions and thresholds you set deliberately. Typical work: - Review of the data path an agent depends on, and where it breaks under real network conditions - The permission and threshold envelope that bounds what an agent may decide and act on - Where a human stays in the loop, and how control passes between person and agent - Guardrails and verification so an agent's decisions can be checked after the fact What decides the price: - How many systems the agent touches, and whether any of them can move money or delete data - Whether a decision boundary exists already or has to be written from scratch - Whether the work ends at a written envelope or continues into building the guardrails What you do not get: - Calls or meetings - An agent built for you, because this is the envelope around one rather than the thing itself - Sign-off that your agent is safe, because a review cannot promise that Suited for teams letting agents act on data and decisions that matter, rather than only reading a marketing site. ## MCP server design **Price on request. Scoped per engagement.** An MCP server built for your product, exposing read-only data to agents over streamable HTTP transport. For public, non-sensitive data, no auth surface and no logging by default. Auth and an audit trail follow the data and the misuse model. Typical work: - Read-only discovery tools over your product data - An MCP server card at /.well-known/mcp/server-card.json so agents can discover the server - Registry publication so the server is findable in MCP directories What decides the price: - How many tools the server exposes, and whether they read one system or several - Whether your data is already reachable through an API, or the read path has to be built first - Whether read-only is enough, which is the default here, or the server has to accept writes Write tools are not included by default. A read-only server cannot modify the source through that interface. That is the property worth keeping. It does not settle exposure, bulk extraction or availability. Those are decided per tool. Suited for teams that want agents to read product data through a supported interface rather than scraping HTML. ## The agent-ready badge Sites that complete an audit, or score 100/100 on a public agent-readiness scanner, may display the [agent-ready badge](/badge). Criteria and embed code: https://turva.dev/badge ## Frequently asked **What is an agent readiness audit?** An agent readiness audit measures how well AI agents can discover, read, and act on your website or API. turva.dev runs an independent scanner, isitagentready.com, reviews the agent-facing surfaces manually, checks how AI assistants currently retrieve and answer about the site, and delivers a written report with fixes ranked by score impact and implementation cost. **What does an agent readiness audit cost?** The Shopify agent storefront check is €1,900, fixed scope, delivered in 48 hours. The audit is €6,500, fixed scope, delivered in two to three weeks. Ongoing advisory is €3,000 per month with a three month minimum, and implementation is €1,500 per day, scoped per task. All prices exclude VAT. Agent operations and MCP server design engagements are priced on request. **How is the audit delivered?** Everything is async. There are no calls or meetings, findings and answers move in writing, and questions get a response within one business day. The audit ends in a written report your team can act on directly, with one round of written follow-up questions included. **How is agent readiness measured?** With an independent public scanner rather than self-assessment. isitagentready.com grades sites on a Level 0 to 5 scale and scores agent readiness out of 100. The audit runs it against your site, so the result is reproducible and the same scan can verify every fix afterwards. **Do I need the audit before the Shopify agent storefront check?** No. The two are separate fixed-scope diagnoses and either can be bought on its own. The audit measures a whole site or API against agent-readiness norms. The Shopify check measures what an AI shopper receives from one live Shopify store, across the three agent surfaces this check covers. **How much work are the fixes after the audit?** In most cases, once the audit is complete, the fixes it lists are about a day of implementation work. Your team can do them with the report as the spec, or turva.dev implements them as a scoped engagement. **Will you sign an NDA, and how is our material handled?** Yes, your own NDA, signed as it stands before any material moves, at no charge. Production credentials are not requested at any stage, and repository write access is scoped per task and only if implementation is purchased. The workstation is encrypted at disk level, and credentials are held in an encrypted vault instead of in files. Backups are encrypted on the machine before they are uploaded anywhere. Client material is deleted within thirty days of the engagement closing, unless retention is required by law. **Do AI tools see our material?** I use AI tools in the work. They run on a local workspace holding the files a task needs, not against your systems. Those files are processed by the provider of the tool in use. No secret reaches a tool in the clear, because credentials are held in an encrypted vault that scripts read at runtime. Material you want kept out of AI tooling is named in the NDA and stays out. ## How to start Email with the site or API you want audited. I respond within one business day with a fixed quote and a start date. No calls or calendar links, and no discovery sessions. All prices exclude VAT. 25,5% for Finnish customers, reverse charge for EU B2B, 0% for non-EU. --- # Shopify agent storefront check For D2C Shopify stores that want evidence of what an AI shopper actually receives. €1,900 plus VAT, fixed scope, delivered in 48 hours from a written kickoff. Shopify stores now meet shopping agents through three separate interfaces. They are related, and an agent does not always get the same answer from each. This check tests one live store across all of them and reports what an agent receives on each, with the evidence attached. A general agent-readiness audit is not a prerequisite. This check stands on its own, and it is not a step inside the audit. ## The three surfaces Every one of these is tested in the same session, against the same products, so a difference between them is visible rather than inferred. - Browser WebMCP tools inside the shopper's live storefront tab. - Shopify-hosted Storefront and UCP MCP endpoints. - Shopify Catalog and Agentic storefront channels. ## What the check answers Within 48 hours you receive an evidence-backed status for each of the following, including anything restricted, unavailable or not testable. - Which agent tools were observed and functional in the tested session. - Whether product, variant, price, currency and availability data agree across the tested surfaces. - Whether an agent can build the intended anonymous cart. - Where the buyer is handed off to checkout. - Whether your Shopify Agentic channel settings match what your team intended. - Which product-data, theme, app or configuration changes should be made first. ## Fixed scope The scope is fixed before the clock starts, and it does not move during delivery. The check covers: - One Shopify store. - One market, language and currency. - Up to three named product and variant pairs. - Up to five real buyer searches. - One clean, supported Chromium browser session. - Browser WebMCP. - Storefront and UCP MCP. - Shopify Agentic settings and a Catalog search preview. - One anonymous browser cart with one permitted checkout navigation, plus one separate remote UCP Cart lifecycle that stops before Checkout MCP. - One retest of up to two corrected items within 14 days. No Shopify Admin password is requested. The check uses public storefront surfaces, an isolated shopper session, and settings evidence you provide as redacted screenshots or a short screen recording. No customer details are entered. No payment is submitted and no order is placed. ## What you receive Five written deliverables. The first four are sent as one package within 48 hours. The fifth is the retest, and it follows within 14 days. - Three-surface map. What is present, restricted, unavailable or not tested on browser WebMCP, remote MCP and Agentic channels. - Product truth matrix. The tested title, variant, price, currency, availability and policy facts across surfaces. - Buyer-journey evidence. The tool, the input, the observed result, the cart state and the exact stop before payment or order creation. - Prioritised correction plan. Up to five specific changes, their owner and a ready acceptance check. - Retest. One verification of up to two corrected items within 14 days. Implementation of the corrections is not included. Your team can act on the plan directly, or the corrections can be bought separately as implementation days. ## Price and timing **€1,900 plus VAT. Fixed scope. 48 hours.** The 48-hour clock starts at the agreed written kickoff, once the preflight, payment and merchant evidence are complete. No response is required from you during the delivery window. If the public preflight cannot establish an observable agent-commerce surface suitable for controlled testing, the engagement is not sold and nothing is invoiced. If the 48-hour package of four deliverables is not sent within 48 elapsed hours, the fee is refunded. The retest is the fifth deliverable. It runs on its own 14-day window. All work is asynchronous and delivered in writing. ## What this is not This is an operational storefront check. It is not a penetration test. It is not a Shopify, MCP, WebMCP or UCP certification either. A documented Shopify tool or public endpoint is not treated as a vulnerability. Browser WebMCP does not establish remote access. Checkout navigation is not reported as payment completion. Ranking or product placement in an external AI channel is not promised. This is an independent service, not affiliated with or endorsed by Shopify. ## What the public preflight measured Before this check was offered, 26 Shopify storefronts were read with a public read-only preflight on 2026-08-09. All 26 advertised the same ten-tool WebMCP inventory that Shopify documents as its platform-supplied surface. What that measurement does not establish, and the reason the paid check exists: - No tool was called on any of the 26 stores. - Cart, checkout, payment and order creation were not tested. - Remote MCP behaviour and Agentic Admin settings were not read. - The identical inventory is Shopify's platform surface rather than 26 separate merchant implementations, so it says nothing about any one store's product data. - Five of the 26 needed a repeat run before the scanner finished, so the reading is the latest available observation rather than one clean pass. - The 26 of 26 figure describes those stores at that hour under that scanner version, and it is not generalised to Shopify stores. ## Sample report A synthetic sample report is available on request. It uses invented store data. It shows the format of the three-surface map, the product truth matrix and the correction plan, and it is not a report on a real merchant. ## Frequently asked **Do I need an agent-readiness audit first?** No. The Shopify agent storefront check is a separate fixed-scope diagnosis with its own price and its own deliverables. The general audit measures a whole site or API against agent-readiness norms, this check measures what an AI shopper receives from one Shopify store. **What does it cost, and what is the delivery time?** €1,900 plus VAT, fixed scope. Four written deliverables arrive as one package within 48 elapsed hours of the agreed written kickoff. The fifth is a retest of up to two corrected items, within 14 days. **Do you need access to my Shopify Admin?** No. No Shopify Admin password is requested and no credentials are handled. Settings evidence comes from you as redacted screenshots or a short screen recording, and everything else is read from public storefront surfaces. **Will you place a test order?** No. The cart lifecycle stops before payment, one checkout navigation is permitted if you authorise it, and no customer details, payment or order are ever submitted. **What happens if the check finds nothing wrong?** You receive the same deliverables, with the surfaces recorded as matching. A documented match is the result you are paying to be able to show, and the correction plan then names what to keep stable instead. ## How to start Email with your storefront URL, your .myshopify.com domain, your primary market and up to three priority products. A preflight and a fixed quote follow within one business day. No calls, no calendar links, and no discovery sessions. All prices exclude VAT. 25,5% for Finnish customers, reverse charge for EU B2B, 0% for non-EU. --- # A one-person audit practice, registered in Finland turva.dev is operated by Erik Rekola. ## Business details - **Trade name:** turva.dev - **Business ID:** 3600281-7 - **Country of registration:** Finland - **Form:** Sole proprietorship ## About the operator Erik spent six years, 2015 to 2021, in hands-on machine roles: paper machinery at UPM, medical washer-disinfectors at Franke, a clinical LC-MS/MS analyzer at Thermo Fisher Scientific, and semiconductor production equipment at ASM International. The common thread was machine data that had to be trusted and interventions that had to stay inside strict limits. There was then a career break, from 2021 to early 2026. turva.dev was built when AI agents turned that same discipline into a web problem: data that has to arrive intact, and decisions that have to stay inside a boundary someone set on purpose. The proof of current skill is public rather than asserted. The site and its MCP server are open source, and every score published here comes from third-party scanners anyone can re-run. ## Location Tampere, Pirkanmaa, Finland. All work is delivered remotely. No on-site engagements. ## Why this service exists Agent-readiness is a measurable property of a site, an API, or a product surface. This service answers one question: whether an independent scanner reads it higher next week than this week. Most websites and APIs were built before AI agents were a meaningful class of clients. The protocols (MCP, well-known manifests, structured discovery, JSON-LD) exist, but few sites implement them correctly. The result is a measurable gap between what an agent can read and what a human can read. This service closes that gap on a per-project basis, with an independent scanner as the referee. ## Operating principles - Async-only engagement. No calls, no calendar links. - All work delivered remotely. - Production credentials are not requested. - Write access scoped per task and only if implementation is purchased. - Public readiness claims are verifiable by re-running the scanner. Engagement findings are tied to recorded inputs and observed results. ## Contact - **Email:** - **Signal:** [@turva.19](https://signal.me/#eu/2qzayURnxbJ8wl7dmQOd5c3sAF7cW8xvDVUrNiG6Cl7rEsXfkSlIsYOS9FSjJixK) - **LinkedIn:** https://www.linkedin.com/in/erikrekola/ ## Invoicing Payment terms are fourteen days net unless agreed otherwise in writing. VAT is added to invoices according to Finnish law. Reverse charge applies to EU B2B customers with a valid VAT ID. Non-EU customers are invoiced without VAT. turva.dev's own VAT ID is FI36002817. --- # Written contact only, first reply within one business day Email for longer messages, Signal for short questions. No calls and no calendar links at any stage of the engagement. ## Channels - **Email:** - **Signal:** [@turva.19](https://signal.me/#eu/2qzayURnxbJ8wl7dmQOd5c3sAF7cW8xvDVUrNiG6Cl7rEsXfkSlIsYOS9FSjJixK) - **LinkedIn:** https://www.linkedin.com/in/erikrekola/ Scan the code with a phone to open a Signal chat. The code image is at /signal-qr.png. Short questions go here, longer documents by email. Signal is end-to-end encrypted. Scanning shares no account of yours. ## Response times - Email and Signal: within one business day - Weekends: no guaranteed response time ## What to include in a first message A useful first message includes: - The site or API to be audited (URL) - Any current scanner results, if you have run them - The scope you have in mind (Shopify agent storefront check, audit, advisory, implementation, agent operations, MCP server design) If you do not have scanner results yet, that is fine. The audit starts with running them. ## Confidentiality An NDA is signed before any material moves. Send your own and it is signed as it stands, at no charge. Production credentials are not requested at any stage, and repository write access is scoped per task and only if implementation is purchased. ## Geographic service area Based in Tampere, Finland. Service delivered remotely worldwide. All work is asynchronous and written. ## Business details - Business ID: 3600281-7 - Register: https://tietopalvelu.ytj.fi/yritys/3600281-7 - Agent registration: https://turva.dev/auth.md --- # Terms of engagement, and how data is handled This page covers the terms under which turva.dev operates, the privacy practices of the site, and the default terms for engagements. ## Operator turva.dev is operated by Erik Rekola, Business ID 3600281-7, registered in Finland as a sole proprietorship. VAT-registered, VAT ID FI36002817. Contact: ## Terms of engagement The following terms apply to all engagements (Shopify agent storefront check, audit, advisory, implementation, agent operations and MCP server design) unless replaced by a written agreement. **Scope.** Each engagement has a defined scope agreed in writing before work starts. Scope changes require a new written agreement and may affect price and timeline. **Deliverables.** Audit deliverables are a written report. Advisory deliverables are written reviews and a monthly summary. Implementation deliverables are source code committed to the agreed repository. **Payment.** Payment terms are fourteen days net unless agreed otherwise in writing. Late payment interest follows Finnish law. **Confidentiality.** Information shared during an engagement is treated as confidential. Your own non-disclosure agreement is signed as it stands before any material moves, at no charge. Production credentials are not requested at any stage. **Liability.** Liability is limited to the value of the engagement. turva.dev is not liable for indirect or consequential damages. **Intellectual property.** The client owns the deliverables produced for them. Generic methods, templates and reusable code remain with turva.dev. **Governing law.** Finnish law applies. Disputes are resolved in the District Court of Pirkanmaa, Finland. ## Privacy This site does not use analytics cookies, tracking pixels or third-party scripts. **Server logs.** The hosting provider (Cloudflare) records standard request logs including IP address, user agent and requested path. Logs are retained according to Cloudflare's standard retention policy. **Email.** Email communication is stored in standard email infrastructure for as long as needed to deliver the work and meet accounting obligations under Finnish law (six years for invoice records). **Client data.** Data shared by a client during an engagement is stored only on systems necessary to deliver the work, and deleted within thirty days of engagement closure unless retention is required by law. The workstation holding it uses full disk encryption, credentials are held in an encrypted vault rather than in files, and backups are encrypted on the machine before they are uploaded anywhere. **AI tools.** AI tools are used in the work, on a local workspace holding the files a task needs. Those files are processed by the provider of the tool in use. No secret reaches a tool in the clear, because credentials are held in an encrypted vault that scripts read at runtime, and the tools have no access to client systems. Material a client wants excluded from AI tooling is named in the non-disclosure agreement and excluded. No data is sold. Data reaches a third party only through the providers needed to deliver the work: hosting, email, encrypted backup storage and the AI tool in use. ## Rights under GDPR You have the right to access, correct or request deletion of personal data held about you. Send the request to . The supervisory authority in Finland is the Data Protection Ombudsman (tietosuojavaltuutettu.fi). ## Cookies This site sets no cookies of its own. Cloudflare may set cookies required for bot management and security. These are technical cookies and do not require consent under EU law. ## Updates This page is updated when the terms change. The current version applies to engagements started after the date below. Terms last updated: 2026-08-11. --- # Open Knowledge Format (OKF) explained The Open Knowledge Format is an open specification from Google Cloud that represents a body of knowledge as a directory of plain markdown files. Each concept file carries a small block of YAML frontmatter and a free-form body. The goal is a portable way to hand an AI agent the context it needs, readable by a person and parseable by a machine, with no SDK and no catalog to lock into. Google Cloud published it in June 2026 as version 0.1. ## What an OKF bundle contains A bundle is a folder of markdown files, and the unit inside it is a concept. A concept is anything worth capturing for an agent: a table, a dataset, a metric, a runbook, an API. Every concept is one UTF-8 markdown document with two parts. A YAML frontmatter block at the top, fenced by a line of three dashes above and below, and a markdown body underneath. The format asks for exactly one field, type. Everything else is optional, including title, description, resource, tags and a timestamp. What types exist and what fields each carries is left to whoever produces the bundle. Concepts reference each other with ordinary markdown links, so the folder becomes a graph of related knowledge rather than a flat list of files. ## Structural interoperability, not yet semantic Version 0.1 fixes a small set of things and leaves the rest open. It fixes the shape of a bundle as a folder of markdown files, the YAML frontmatter, two reserved filenames and the single required field. That is structural interoperability: any tool can open a bundle and know where the pieces are. What it does not fix is meaning. The format does not say what a metric concept must contain, or how two producers should agree on the same field names. That is semantic interoperability, and version 0.1 leaves it to producers and to conventions that have not been written yet. This is the line to keep in mind when reading the announcements around OKF. It standardizes the shape of the files, not yet what the files mean. ## Where OKF fits with agent-readiness Agent-readiness, the kind measured by an independent scanner, is about whether an agent can reach and read your public site at all. OKF sits next to that, one layer in. It is a way to package the internal knowledge an agent works from once it is past the front door: the catalog, the metrics and the rules a decision depends on. So OKF is not a replacement for an llms.txt or a markdown surface on your site. It is the same instinct, plain text an agent can read without a special client, applied to the data and context behind the site rather than the pages in front of it. For a team thinking about what an agent acts on, not only what it can see, that is the part of the picture OKF addresses. ## What to do with it today OKF is new and small, version 0.1, and the semantic half is still open. That makes it worth understanding now and worth watching, but early to build an entire knowledge catalog on. If you already serve markdown to agents and keep an llms.txt, you have the instinct OKF formalizes, and adopting it later will be a short step rather than a rebuild. For an audit of how legibly AI agents can read your site and the data behind it, contact info@turva.dev. ## Related - [llms.txt explained](/guides/llms-txt) - [Serving markdown to agents](/guides/markdown-for-agents) - [Letting agents act on data: the decision envelope](/guides/letting-agents-act-on-data) --- # Agent-readiness guides These short guides explain, in plain language, what makes a website or an API easy for AI agents to read and use. Each one covers a single topic and takes a few minutes to read. They are free, and they cover the same surfaces an [agent-readiness audit](/services) measures. The first guide explains what an agent-readiness audit is. ## Discovery and content How an agent finds your site and reads it without getting lost. - [What an agent-readiness audit is](https://turva.dev/guides/agent-readiness-audit) - [How to get your site cited by AI assistants](https://turva.dev/guides/get-cited-by-ai-assistants) - [llms.txt explained](https://turva.dev/guides/llms-txt) - [Serving markdown to agents](https://turva.dev/guides/markdown-for-agents) - [Open Knowledge Format (OKF) explained](https://turva.dev/guides/open-knowledge-format) - [Sitemaps, robots.txt and agent access](https://turva.dev/guides/sitemaps-and-robots-for-agents) - [Response headers that help agents](https://turva.dev/guides/response-headers-for-agents) - [Prerendering and why agents see empty pages](https://turva.dev/guides/prerendering-for-agents) ## Capability and trust How a site tells an agent what it is allowed to do, and shows it is safe to use. - [MCP server cards explained](https://turva.dev/guides/mcp-server-card) - [What agents.json is](https://turva.dev/guides/agents-json) - [The /.well-known directory for agents](https://turva.dev/guides/well-known-for-agents) - [Agentic Resource Discovery and ai-catalog.json](https://turva.dev/guides/agentic-resource-discovery) - [How agents authenticate](https://turva.dev/guides/agent-authentication) - [JSON-LD and structured data for agents](https://turva.dev/guides/json-ld-structured-data) ## Commerce and strategy Paying agents, how this differs from SEO, and how to choose and measure an audit. - [x402 and agent payments](https://turva.dev/guides/x402-agent-payments) - [Agent commerce discovery: A2A, AP2, and ACP](https://turva.dev/guides/agent-commerce-discovery) - [Agentic commerce readiness: selling to AI shopping agents](https://turva.dev/guides/agentic-commerce-readiness) - [SEO and agent-readiness are not the same](https://turva.dev/guides/seo-vs-agent-readiness) - [Agent-readiness, AEO and GEO: how they relate](https://turva.dev/guides/agent-readiness-aeo-geo) - [Letting agents act on data: the decision envelope](https://turva.dev/guides/letting-agents-act-on-data) - [AI agent use cases: where agents read data and make decisions](https://turva.dev/guides/ai-agent-use-cases) - [Why agent-readiness should be measured, not asserted](https://turva.dev/guides/measurement-led-agent-readiness) - [Common agent-readiness gaps on marketing sites](https://turva.dev/guides/agent-readiness-gaps) - [Choosing an agent-readiness audit](https://turva.dev/guides/choosing-an-agent-readiness-audit) ## Frequently asked **What is an agent-readiness audit?** An agent-readiness audit measures how well an AI agent can discover, read, and act on a website or an API, scored against current standards by an independent scanner rather than a self-assessment. **Do I need llms.txt on my site?** If you want models and agents to read your real content rather than guess from a cached snippet, llms.txt gives them a curated map of what matters. It does not replace robots.txt or a sitemap, it complements them. **How do I get my site cited by AI assistants?** A model cites content it can read cleanly and corroborate. That means machine-readable surfaces such as llms.txt and structured data, a markdown form that does not exhaust the token budget, and being indexed where the assistant searches. **What is an MCP server card?** An MCP server card is a JSON file, usually at /.well-known/mcp/server-card.json, that lets an agent discover a site's Model Context Protocol server and the tools it exposes, so the agent can call them without a human wiring up the connection. **Is agent-readiness the same as SEO?** No. SEO makes a site rank for a person to click. Agent-readiness makes a site legible and usable by an agent that reads and acts. A site can rank well and still be opaque to agents. **How is agent-readiness measured?** By an independent scanner that reads the live site and reports a score with a category breakdown. The categories that get fixed read higher on the next scan, so the claim is the number rather than an assertion. For an audit, contact info@turva.dev. --- # What an agent-readiness audit is An agent-readiness audit measures how well an AI agent can discover, read, and act on a website or an API. It is a technical review of the surfaces that automated clients actually use, scored against current standards rather than opinion. Most sites are built for human readers and search crawlers. AI agents read differently. They look for machine-readable entry points such as llms.txt, a sitemap, response headers, structured data, and well-known manifests. When those are missing, the agent either guesses or gives up, and the site becomes invisible to that class of client even when the underlying product is strong. The audit checks the parts an agent reaches first. Discoverability covers robots.txt, the sitemap, the response headers, and the DNS records that let an agent find resources without parsing a full HTML page. Content accessibility covers llms.txt, markdown content negotiation, and whether the site can return a clean text version that saves an agent most of the tokens an HTML page would cost. Bot access control covers the AI-bot rules, the content signals, and the bot-authentication directory that tell an agent how it is allowed to behave. API, auth, MCP and A2A discovery covers an MCP server card, an agent card, an OpenAPI description, an API catalog, and OAuth discovery, so an agent can enumerate what the site offers and authenticate safely. Commerce covers payment surfaces such as x402 and structured pricing, so an agent can transact. The result is a list. Each check passes or fails, and each failure comes with a concrete fix. The point is that the outcome is verifiable. An independent scanner reads the site before and after, and the categories that were fixed read higher on the next scan. The claim is the number, not an assertion. turva.dev applies the same standard to its own site. Measured by an independent scanner, turva.dev reaches 100/100 and Level 5, Agent-Native, on isitagentready.com. Measured 2026-08-01. The audit a client receives runs the same checks against their site. For an audit, contact info@turva.dev. Engagement is async and evidence-based, and production credentials are not requested. ## Frequently asked **What is an agent-readiness audit?** An agent-readiness audit measures how well an AI agent can discover, read, and act on a website or an API. It is a technical review of the surfaces automated clients use, scored against current standards rather than opinion. **What does an agent-readiness audit check?** It checks the surfaces an agent reaches first, covering discoverability, content accessibility, bot access control, API/auth/MCP and A2A discovery, and commerce. Each check passes or fails, and each failure comes with a concrete fix an independent scanner can verify before and after. ## Related - [Choosing an agent-readiness audit](/guides/choosing-an-agent-readiness-audit) - [Why agent-readiness should be measured, not asserted](/guides/measurement-led-agent-readiness) - [Common agent-readiness gaps on marketing sites](/guides/agent-readiness-gaps) - [AI agent use cases](/guides/ai-agent-use-cases) --- # llms.txt explained llms.txt is a plain text file at the root of a site that tells AI agents and language models what the site contains and where the important content lives. It works like a guide written for machines. A human reads the rendered page, an agent reads llms.txt and follows the links it lists. The format is simple. The file opens with the site name and a short summary, then lists the key pages and resources as markdown links, often grouped under headings. Some sites also publish llms-full.txt, a single file that bundles the full text of the site so an agent can read everything in one request instead of crawling many pages. The reason it matters is cost and clarity. A normal HTML page carries navigation, scripts, and styling that an agent has to wade through, and that spends tokens and invites mistakes. An llms.txt file, paired with markdown content negotiation, lets an agent fetch a clean text version and skip the noise. On turva.dev the markdown version of a page costs a fraction of the HTML, which is the difference between an agent reading the page reliably and an agent truncating it. llms.txt is not a ranking trick and it does not replace a sitemap or robots.txt. A sitemap lists every URL for crawlers. robots.txt sets crawl rules. llms.txt is a curated, human-written map of what matters, aimed at models. The three work together. Whether a site needs one depends on whether it wants to be legible to agents. If buyers, researchers, or assistants will ever ask a model about what the site does, a clear llms.txt raises the odds that the model reads the real content rather than guessing from a cached snippet. Check any site's llms.txt structure with the free validator at https://turva.dev/llms-txt-validator. turva.dev publishes llms.txt and llms-full.txt and serves markdown on request. For an audit of how legible a site is to agents, contact info@turva.dev. ## Frequently asked **What is llms.txt?** llms.txt is a plain text file at the root of a site that tells AI agents and language models what the site contains and where the important content lives. It does not replace robots.txt or a sitemap, it complements them. **Does llms.txt help with search ranking?** No. llms.txt is not a ranking trick. It gives models a curated map of the content so they read the real page rather than guessing from a cached snippet. ## Related - [Serving markdown to agents](/guides/markdown-for-agents) - [How to get your site cited by AI assistants](/guides/get-cited-by-ai-assistants) - [Agent-readiness, AEO and GEO: how they relate](/guides/agent-readiness-aeo-geo) --- # MCP server cards explained An MCP server card is a small JSON file that describes a site's Model Context Protocol server so an agent can find it and learn what it offers. It usually lives at /.well-known/mcp/server-card.json, though the path is not yet standardized. SEP-2127, the open proposal behind the card, now develops it as an experimental MCP extension. As of July 2026 its draft recommends serving the card at the MCP endpoint URL followed by /server-card, with a site-level catalog at /.well-known/mcp/catalog.json, so the convention may still move. An agent reads the card, finds the endpoint, and can then connect without a human wiring up the connection first. The Model Context Protocol is a standard way for agents to use external tools and data. A server implements the protocol and exposes a set of tools, and the card is how that server announces itself. Without a card or a registry listing, an agent has no reliable way to discover that the server exists or what it can do, so the capability stays hidden even when it is live. A useful card states the server name, the endpoint, and the transport, in a shape an agent can parse deterministically. Many published cards, including turva.dev's, also list the tools. The newer draft leaves tool listing to the MCP connection itself, since a live tools/list answer cannot go stale the way a static list can. turva.dev publishes a server card that points to a read-only MCP server, which exposes the same agent-readiness data that the site shows to people. That means an agent can query the data directly rather than scraping a page. A server card sits in the same family as other well-known manifests an agent looks for, such as an API catalog, an OpenAPI description, and OAuth discovery. Each one removes a guess. The card answers what tools exist, the API catalog answers what endpoints exist, and OAuth discovery answers how to authenticate. Together they let an agent move from finding a site to operating it. For sites that want to expose a capability to agents, the card is the cheapest high-value step, because it turns an invisible server into a discoverable one. For an audit of a site's capability surface, contact info@turva.dev. ## Frequently asked **What is an MCP server card?** An MCP server card is a small JSON file, usually at /.well-known/mcp/server-card.json, that describes a site's Model Context Protocol server so an agent can find it, learn which tools it exposes, and call them without a human wiring up the connection. **Why publish an MCP server card?** Without a card or a registry listing an agent has no reliable way to discover that the server exists or what it can do, so the capability stays hidden even when it is live. The card turns an invisible server into a discoverable one. ## Related - [What agents.json is](/guides/agents-json) - [The /.well-known directory for agents](/guides/well-known-for-agents) - [How agents authenticate](/guides/agent-authentication) --- # What agents.json is agents.json is a machine-readable file that declares what an AI agent can do on a site and how. Where llms.txt tells an agent what the site contains, agents.json describes the actions and endpoints an agent is allowed to use, so an automated client can move from reading to doing without a human wiring it up. The file lists the operations a site exposes to agents, often pointing at an OpenAPI description or specific endpoints, along with the authentication an agent needs. An agent reads it, learns which actions exist, and calls them within the rules the site sets. The reason it matters is that most sites expose actions only through a human interface, a form or a checkout flow that a person clicks through. An agent cannot reliably reverse-engineer that. A declared action surface removes the guesswork and turns a site from something an agent can read into something an agent can operate. agents.json sits beside the other declarations an agent looks for. An MCP server card describes a site's MCP server, an API catalog lists endpoints, and OAuth discovery describes how to authenticate. Each one removes a guess, and together they let an agent act on a user's behalf safely. A site does not need agents.json to be readable, but it needs something like it to be operable. The specification itself has stayed at version 0.1.0 since early 2025 and the ecosystem's momentum has moved to MCP and newer discovery surfaces, so treat agents.json as one declaration pattern rather than a settled standard. If the goal is for agents to complete tasks rather than just summarize the page, declaring the action surface is the step that makes that possible. For an audit of a site's capability and action surface, contact info@turva.dev. ## Frequently asked **What is agents.json?** agents.json is a machine-readable file that declares what an AI agent can do on a site and how. It describes the actions and endpoints an agent is allowed to use, often pointing at an OpenAPI description, along with the authentication an agent needs. **How is agents.json different from llms.txt?** llms.txt tells an agent what the site contains. agents.json describes the actions an agent can take, so a site moves from something an agent can read to something an agent can operate. ## Related - [MCP server cards explained](/guides/mcp-server-card) - [How agents authenticate](/guides/agent-authentication) - [The /.well-known directory for agents](/guides/well-known-for-agents) --- # x402 and agent payments x402 is a way for a site to ask an agent to pay before it returns a resource, using the long-reserved HTTP 402 Payment Required status. It lets an automated client discover a price, pay, and continue, without a human stepping in to enter card details. When an agent requests a paid resource, the server responds with 402 and a manifest that states what is being sold and how to pay. The agent reads the terms, signs a payment payload for a supported method, and retries the request with the payload attached; the server or its facilitator settles the payment. The transaction happens in the protocol, not in a checkout page built for human eyes. This matters because agent commerce is held back by payment, not by capability. An agent can find a product and compare options, then stall at a checkout flow designed for a person with a browser. A declared payment surface such as x402, paired with structured pricing in the page data, lets the agent complete the purchase the same way it completed the search. x402 belongs to a small family of agent payment standards, and its relationship to AP2 is specific rather than parallel. As of July 2026 x402 is the stablecoin settlement path inside AP2, carried by a separate A2A settlement extension built with Coinbase, so an AP2 mandate can authorize an onchain settlement that leaves the same audit trail a card payment does. A site that publishes these signals tells agents that it is open for automated business, and in the case of the open peer pricelist model, it can be shown alongside other options at the moment an agent decides where to spend. turva.dev publishes an x402 endpoint and manifest. For an audit of a site's commerce surface for agents, contact info@turva.dev. ## Frequently asked **What is x402?** x402 is a way for a site to ask an agent to pay before it returns a resource, using the HTTP 402 Payment Required status. It lets an automated client discover a price, pay, and continue without a human entering card details. **Why does agent commerce need a payment surface like x402?** Agent commerce is held back by payment, not by capability. An agent can find a product and compare options, then stall at a checkout flow built for a person. A declared payment surface lets the agent complete the purchase the same way it completed the search. ## Related - [Agent commerce discovery: A2A, AP2, and ACP](/guides/agent-commerce-discovery) - [The /.well-known directory for agents](/guides/well-known-for-agents) --- # Response headers that help agents Response headers are the metadata a server sends with every page, and the right ones let an AI agent work without parsing the full HTML. They are the cheapest place to make a site more legible to automated clients, because an agent reads them before it reads the body. A Link header can point an agent straight at a site's machine-readable resources, such as an API catalog or a markdown version of the page, so the agent finds them without crawling. A Vary header that includes Accept tells caches and agents that the site can return different formats for the same URL, which is what makes markdown content negotiation reliable. RateLimit and RateLimit-Policy headers let a well-behaved agent throttle itself instead of guessing, though as of July 2026 their IETF draft, revision 11 from May 2026, remains active without yet becoming a standard. Content-Language and a clean content type remove ambiguity about what the agent is reading. The reason headers matter is order. An agent fetches the response, reads the status and headers first, and decides what to do next from them. If the headers already say where the structured data is and what formats are available, the agent can skip the expensive step of parsing a page built for human display. Headers are easy to get wrong in ways that hurt agents. A missing Vary header breaks content negotiation. A Cache-Control immutable directive set on the wrong response can stop an agent from seeing an update. The fix is usually small and lives at the edge, which on turva.dev is a Cloudflare Worker that sets these headers on every response. For an audit of a site's response and discovery surface, contact info@turva.dev. ## Frequently asked **Which response headers help AI agents?** A Link header points an agent at machine-readable resources such as an API catalog or a markdown version of the page. A Vary header that includes Accept makes markdown content negotiation reliable. RateLimit headers let a well-behaved agent throttle itself, and Content-Language with a clean content type removes ambiguity. **Why do response headers matter to agents?** An agent reads the status and headers before the body and decides what to do from them. If the headers already say where the structured data is and what formats are available, the agent can skip parsing a page built for human display. ## Related - [Serving markdown to agents](/guides/markdown-for-agents) - [Prerendering and why agents see empty pages](/guides/prerendering-for-agents) - [The /.well-known directory for agents](/guides/well-known-for-agents) --- # SEO and agent-readiness are not the same Search engine optimization makes a site rank in a list of links for a person to click. Agent-readiness makes a site legible and usable by an AI agent that reads, decides, and sometimes acts on the user's behalf. The two overlap, but optimizing for one does not deliver the other. SEO is built around keywords, backlinks, and a results page where a human chooses. The page is the destination. Agent-readiness is built around machine-readable surfaces such as llms.txt, structured data, response headers, and well-known manifests, where the agent is the reader and the page may never be seen by a person at all. A site can rank well on Google and still be opaque to an agent, and a site can be highly legible to agents while ranking modestly in classic search. The gap is widening as people ask assistants instead of typing queries. When an answer comes from a model rather than a list of links, the question is not where a site ranks but whether the model can read the site cleanly and is willing to cite it. That depends on the discovery and content surface, not on the usual ranking signals. This is why ranking on a search engine does not guarantee presence in an AI answer. They are scored on different things. A site that wants both has to do both, and the agent-readiness side is the one most teams have not started. turva.dev measures the agent-readiness side and reports exactly which checks pass or fail. For an audit, contact info@turva.dev. ## Frequently asked **Is agent-readiness the same as SEO?** No. SEO makes a site rank in a list of links for a person to click. Agent-readiness makes a site legible and usable by an AI agent that reads, decides, and sometimes acts. A site can rank well and still be opaque to agents. **Why does search ranking not guarantee presence in AI answers?** They are scored on different things. A search engine ranks pages by keywords and backlinks. An assistant cites a site when it can read the content cleanly and corroborate it, which depends on the discovery and content surface rather than ranking signals. ## Related - [Agent-readiness, AEO and GEO: how they relate](/guides/agent-readiness-aeo-geo) - [How to get your site cited by AI assistants](/guides/get-cited-by-ai-assistants) - [Why agent-readiness should be measured, not asserted](/guides/measurement-led-agent-readiness) --- # JSON-LD and structured data for agents JSON-LD is a block of structured data in a page that states facts in a form a machine can read without interpreting prose. It tells an agent what the page is about, who runs it, what it sells, and at what price, as data rather than as sentences an agent has to parse and might misread. A human reads a price from a layout and a currency symbol. An agent reading raw HTML has to guess which number is the price and which is a shipping estimate. A JSON-LD Offer with a price and a currency removes the guess. The same applies to the organization behind a site, the services it offers, and the questions it answers, each expressed as a typed object an agent can rely on. Structured data also connects a page to the wider graph an agent builds. Declared types such as Organization, Service, FAQPage, and Article let an agent place a page in context and decide whether to trust and cite it. A page that states its facts as data is easier for a model to summarize correctly and to attribute. The cost of getting it wrong is silent. An agent does not report that it failed to parse a price, it just acts on a worse guess. Clean JSON-LD is one of the cheapest ways to make a page legible, and it sits in the same family as the response headers and well-known manifests an agent reads first. turva.dev declares JSON-LD for its organization, the person behind it, its services, and its guides, and the next scan reads the structured data as present. For an audit of a site's structured data, contact info@turva.dev. ## Frequently asked **What is JSON-LD?** JSON-LD is a block of structured data in a page that states facts in a form a machine can read without interpreting prose. It tells an agent what the page is about, who runs it, what it sells, and at what price, as data rather than sentences. **Why does structured data matter for agents?** An agent reading raw HTML has to guess which number is a price and which is a shipping estimate. A JSON-LD Offer with a price and a currency removes the guess, and declared types let an agent place a page in context and decide whether to trust and cite it. ## Related - [How to get your site cited by AI assistants](/guides/get-cited-by-ai-assistants) - [llms.txt explained](/guides/llms-txt) - [The /.well-known directory for agents](/guides/well-known-for-agents) --- # The /.well-known directory for agents The /.well-known directory is a standard place at the root of a site where agents look for machine-readable descriptions of what the site offers. Instead of crawling pages and guessing, an agent fetches a predictable path and reads a manifest that points it to everything else. The idea comes from a long-standing web convention and now carries the files agents care about. An API catalog at a well-known path, defined by RFC 9727, lets an agent enumerate a site's public APIs from a single URL. A server card describes an MCP server and how to reach it. OAuth metadata describes how to authenticate. Payment and agent-payment manifests describe how to transact. security.txt says where to report a problem. The value is that discovery becomes a lookup rather than a search. An agent that knows the convention can ask one predictable question and get a map, which is faster and far more reliable than inferring structure from rendered HTML. A site that publishes a complete well-known surface is announcing its capabilities in the language agents already speak. A missing or thin well-known directory does not break a site for people, but it leaves an agent to guess, and most agents will simply move on. Publishing the manifests an agent expects is the difference between a capability that exists and a capability an agent can find. turva.dev publishes an API catalog, a server card, OAuth metadata, payment manifests, and a security contact under /.well-known. For an audit of a site's discovery surface, contact info@turva.dev. ## Frequently asked **What is the /.well-known directory?** The /.well-known directory is a standard place at the root of a site where agents look for machine-readable descriptions of what the site offers. An agent fetches a predictable path and reads a manifest that points it to everything else. **What files do agents look for under /.well-known?** An API catalog defined by RFC 9727, an MCP server card, OAuth metadata, payment and agent-payment manifests, and a security contact. Each one turns discovery into a lookup rather than a search. ## Related - [MCP server cards explained](/guides/mcp-server-card) - [How agents authenticate](/guides/agent-authentication) - [Sitemaps, robots.txt and agent access](/guides/sitemaps-and-robots-for-agents) --- # Agentic Resource Discovery and ai-catalog.json Agentic Resource Discovery, or ARD, is an open specification for telling AI agents what a site offers, in one machine-readable file. Instead of inferring from pages whether a site has an MCP server, an agent interface, or an API, the site publishes a single index that names each resource and where to reach it. The specification appeared in 2026, is licensed under Apache 2.0, and builds on the AI Catalog data model maintained by a working group under the Linux Foundation. ## What it is A site advertises its agentic resources by serving a static JSON manifest at /.well-known/ai-catalog.json. The manifest is a small envelope with a specVersion (turva.dev publishes 1.0), a host block that names the operator, and an entries array. Each entry describes one resource with a stable identifier, a display name, a type, a url, and a short description. A resource can be an MCP server, an A2A agent, an API, or a skill set. A registry can crawl published catalogs and answer a capability query by pointing an agent at the right resource. ## Where it sits ARD is a discovery layer, not a transport. It helps an agent find the right resource, which the agent then calls through that resource's own protocol, whether MCP, A2A, or a plain API. Discovery comes first and invocation second. The catalog does not replace the manifests it points to, it indexes them, so a site keeps its server card, its agent card, and its OpenAPI description, and adds one file that ties them together. ## How it relates to llms.txt An ai-catalog.json is not a ranking trick and it is not a content map. llms.txt tells an agent where a site's content lives. An ai-catalog tells an agent which agentic resources the site exposes and how to reach them. The two are complementary, and neither is about search ranking. Google has said publicly that llms.txt does not affect its search results, which is the same point agent-readiness has always made. These files are for agents that read and act. ## Why it matters Adoption is early. In a June 2026 check I ran against their public well-known paths, none of the companies named as contributors to the specification yet served a discoverable ai-catalog.json, so publishing one now is a forward move rather than table stakes. The value is the same as every other discovery surface. A capability an agent cannot find is a capability that does not exist for that agent, and one predictable file turns a set of separate manifests into a single answer. turva.dev serves an ai-catalog.json at /.well-known/ai-catalog.json that indexes its MCP server, its A2A agent, its API, and its agent skills, each of which already resolves on its own. For an audit of a site's discovery surface, contact info@turva.dev. ## Frequently asked **What is an ai-catalog.json?** An ai-catalog.json is a static JSON manifest at /.well-known/ai-catalog.json that lists the agentic resources a site offers, such as its MCP server, A2A agent, and API, each with an identifier, type, url, and description, so agents and registries can discover them from one file. **Does Agentic Resource Discovery affect search ranking?** No. ARD is a discovery layer for AI agents, not a search file. It indexes the resources an agent can call through their own protocols. Google has said publicly that llms.txt does not affect its search results, and the same applies to an ai-catalog. ## Related - [The /.well-known directory for agents](/guides/well-known-for-agents) - [MCP server cards explained](/guides/mcp-server-card) - [Agent commerce discovery: A2A, AP2, and ACP](/guides/agent-commerce-discovery) --- # How agents authenticate Agent authentication is how an automated client proves who it is and gains scoped access to a site, without a human logging in first. It is the step that turns a read-only agent into one that can act on a user's behalf, and it has to be discoverable or the agent cannot begin. The pattern follows existing standards. OAuth discovery at a well-known path tells an agent where to request access and what scopes exist. An authorization server and a protected resource description let the agent ask for a token tied to a specific permission rather than a blanket login. When a site also advertises an agent registration flow, an agent can register and claim access on a user's behalf without someone provisioning credentials by hand. The reason this matters is trust and blast radius. A site that exposes capability without scoped, discoverable auth either stays closed to agents or invites unsafe workarounds. Proper discovery lets an agent request the least access it needs, and lets the site grant capability without handing over a password the agent should never see. A short auth description, sometimes published as an auth.md, gives an agent a human-readable entry point to the same flow. Together with OAuth discovery it answers the agent's first question about any action, which is how do I get permission to do this safely. turva.dev publishes OAuth discovery, a protected resource description, and an agent registration entry point, and it never requests production credentials in an engagement. For an audit of a site's authentication surface, contact info@turva.dev. ## Frequently asked **How do AI agents authenticate?** An agent proves who it is through discoverable standards such as OAuth discovery at a well-known path, which tells it where to request access and what scopes exist. It can then request a token tied to a specific permission rather than a blanket login. **Why does scoped, discoverable auth matter?** A site that exposes capability without scoped auth either stays closed to agents or invites unsafe workarounds. Proper discovery lets an agent request the least access it needs without handling a password it should never see. ## Related - [The /.well-known directory for agents](/guides/well-known-for-agents) - [MCP server cards explained](/guides/mcp-server-card) - [What agents.json is](/guides/agents-json) - [Letting agents act on data: the decision envelope](/guides/letting-agents-act-on-data) --- # Why agent-readiness should be measured, not asserted Agent-readiness is a property you can measure, so it should be measured rather than claimed. A checklist that a team fills in by hand records intentions. An independent scanner records what an agent actually finds when it reads the site, and those two often disagree. The difference shows up the moment something changes. A header gets dropped in a deploy, or a manifest starts returning the wrong content type. A self-assessment still reads as done, because nobody re-ticked the box. A scan reads the live site and the category drops, which is the only signal that matches what an agent experiences. Measurement also makes a result legible to a buyer. A claim that a site is agent-ready is an assertion. A score from an independent scanner, with a category breakdown and a date, is evidence that can be checked. The honest version of the claim is the number, and the number can be re-run by anyone. This is the standard turva.dev applies to its own site and to client sites. An audit reports the exact checks that pass or fail, each failure comes with a concrete fix, and the next scan reads higher in the categories the report named. Measured by an independent scanner, turva.dev reaches 100/100 and Level 5, Agent-Native, on isitagentready.com. Measured 2026-08-01. For an audit that reports measured results rather than a checklist, contact info@turva.dev. ## Frequently asked **Why should agent-readiness be measured rather than asserted?** A checklist filled in by hand records intentions. An independent scanner records what an agent actually finds when it reads the site, and the two often disagree, especially after a deploy drops a header or changes a content type. **What makes a measured result more credible to a buyer?** A claim that a site is agent-ready is an assertion. A score from an independent scanner, with a category breakdown and a date, is evidence anyone can re-run. The honest version of the claim is the number. ## Related - [What an agent-readiness audit is](/guides/agent-readiness-audit) - [Choosing an agent-readiness audit](/guides/choosing-an-agent-readiness-audit) - [Common agent-readiness gaps on marketing sites](/guides/agent-readiness-gaps) - [Letting agents act on data: the decision envelope](/guides/letting-agents-act-on-data) --- # Prerendering and why agents see empty pages Many sites render their content with JavaScript in the browser, which means the first response an agent receives is an almost empty shell. A person waits a moment and the page fills in. An agent that reads the raw response sees a loading state and little else, and it judges the site on that. In the audits I have run, this is the most common reason a capable site is invisible to agents. The content exists, but it arrives after the agent has already read and moved on. Search crawlers have partly adapted to this over years. Many AI agents and fetchers have not, and they take the first response at face value. The fix is to serve the real content in the first response for clients that need it. Prerendering renders the page on the server or at the edge and returns finished HTML, so an agent reads the content immediately. A cleaner option for agents is to serve a markdown version of the page on request, which skips the rendering question entirely and costs a fraction of the tokens. The decision is not all or nothing. A site can keep its interactive experience for people and serve prerendered or markdown content to agents and bots, deciding by the request. On turva.dev that decision lives in a Cloudflare Worker that reads the request's Accept header and returns the right form. For an audit of how a site renders for agents, contact info@turva.dev. ## Frequently asked **Why do AI agents see empty pages?** Many sites render content with JavaScript in the browser, so the first response is an almost empty shell. A person waits and the page fills in, but an agent reads the raw response, sees a loading state, and judges the site on that. **How do you fix empty pages for agents?** Serve the real content in the first response for clients that need it, through prerendering at the server or edge, or serve a markdown version of the page on request, which skips rendering and costs a fraction of the tokens. ## Related - [Serving markdown to agents](/guides/markdown-for-agents) - [Response headers that help agents](/guides/response-headers-for-agents) - [Common agent-readiness gaps on marketing sites](/guides/agent-readiness-gaps) --- # Sitemaps, robots.txt and agent access robots.txt and the sitemap are the oldest machine-readable files on the web, and they still decide whether an agent is allowed in and what it can find. An agent reads robots.txt to learn the rules and the sitemap to learn the map, before it reads any page. robots.txt does two jobs for agents. It sets crawl rules, and it can name AI crawlers explicitly, so a site states whether it welcomes GPTBot and similar clients rather than leaving them to guess. A Content-Signal directive can go further and declare how content may be used, separating ordinary search from AI input and training, which gives a site granular control instead of an all-or-nothing block. The sitemap answers the other question, which is what exists. A complete sitemap lists every canonical URL with a last-modified date, so an agent can find the real pages without inferring them from navigation. A page that is not in the sitemap is a page an agent may never reach. Getting these wrong is quietly expensive. A robots.txt that blocks an AI crawler by accident removes a site from that assistant's answers. A stale sitemap hides new pages. The files are small and the fix is fast, which is why they are the first thing a readiness review checks. turva.dev declares AI bot rules and Content Signals in robots.txt and keeps a complete sitemap. For an audit of a site's crawl and access surface, contact info@turva.dev. ## Frequently asked **How do robots.txt and the sitemap affect AI agents?** An agent reads robots.txt to learn the rules and the sitemap to learn the map before it reads any page. robots.txt can name AI crawlers explicitly, and the sitemap lists every canonical URL so an agent finds the real pages without inferring them from navigation. **What is a Content-Signal directive in robots.txt?** A Content-Signal directive declares how content may be used, separating ordinary search from AI input and training. It gives a site granular control instead of an all-or-nothing block. ## Related - [The /.well-known directory for agents](/guides/well-known-for-agents) - [Response headers that help agents](/guides/response-headers-for-agents) - [How to get your site cited by AI assistants](/guides/get-cited-by-ai-assistants) --- # Serving markdown to agents An HTML page is built for a browser, and an agent that reads it pays for all the markup, scripts, and layout it does not need. Serving a markdown version of the same page gives an agent the content without the wrapper, which is both cheaper and less error-prone. The mechanism is content negotiation. An agent sends an Accept header asking for text/markdown, and the server returns the markdown form of the page at the same URL. A site can also publish llms-full.txt, a single file that bundles the whole site as text, so an agent can read everything in one request instead of fetching many pages. The saving is large. On turva.dev the markdown form of a page costs a fraction of the tokens the HTML would, and the difference decides whether an agent reads a page in full or truncates it halfway. A model that runs out of budget on markup is a model that answers from a partial reading. Markdown delivery is not a separate site, it is the same content offered in a second form. The page stays as it is for people, and an agent that asks for text gets text. Paired with a clear llms.txt that lists where the content lives, it makes a site fast and reliable to read at machine speed. turva.dev serves markdown on request and publishes llms.txt and llms-full.txt. For an audit of a site's content surface for agents, contact info@turva.dev. ## Frequently asked **Why serve markdown to AI agents?** An HTML page is built for a browser, and an agent that reads it pays for all the markup, scripts, and layout it does not need. A markdown version gives the content without the wrapper, which is cheaper and less error-prone. **How does an agent request the markdown version?** Through content negotiation. An agent sends an Accept header asking for text/markdown and the server returns the markdown form at the same URL. A site can also publish llms-full.txt to bundle the whole site as text in one request. ## Related - [llms.txt explained](/guides/llms-txt) - [Response headers that help agents](/guides/response-headers-for-agents) - [Prerendering and why agents see empty pages](/guides/prerendering-for-agents) --- # Common agent-readiness gaps on marketing sites Most marketing sites are strong for people and weak for agents, and the gaps are predictable. A readiness review tends to find the same handful of misses, each of which quietly removes the site from an agent's view. The first is rendering. A site that builds its content with JavaScript returns an empty shell to any agent that does not run a browser, so for those clients the content never arrives in the first response. The second is discovery. No llms.txt and a thin or missing sitemap, so an agent has nothing to read but rendered pages. The third is cost. Only HTML is offered, with no markdown form, so an agent spends its budget on markup and truncates the page. Beyond those, capability is usually undeclared. The site may have an API or a useful action, but with no server card or OAuth discovery, an agent cannot find or use it. Structured data is often missing too, so prices and facts are left for the agent to infer from layout. None of these are hard to fix, and that is the point. The work is mostly at the edge and in a few small files, and the result shows up immediately in a scanner. A site does not have to rebuild to become legible to agents, it has to publish what agents already look for. turva.dev runs this exact review and reports each gap with a concrete fix. For an audit, contact info@turva.dev. ## Frequently asked **What are the most common agent-readiness gaps on marketing sites?** Client-side rendering that returns an empty shell to non-browser agents, no llms.txt and a thin or missing sitemap, and HTML-only delivery with no markdown form. Capability is usually undeclared and structured data is often missing, so prices and facts are left for the agent to infer. **Are agent-readiness gaps hard to fix?** No. The work is mostly at the edge and in a few small files, and the result shows up immediately in a scanner. A site does not have to rebuild to become legible to agents, it has to publish what agents already look for. ## Related - [What an agent-readiness audit is](/guides/agent-readiness-audit) - [Prerendering and why agents see empty pages](/guides/prerendering-for-agents) - [Choosing an agent-readiness audit](/guides/choosing-an-agent-readiness-audit) --- # Choosing an agent-readiness audit This page answers the practical questions a buyer asks before commissioning an agent-readiness audit: who runs them, what they cost, how long they take, and what you get. The conceptual guides cover the surfaces themselves. This one covers the engagement. ## Frequently asked **Who provides agent-readiness audits?** turva.dev provides independent agent-readiness audits and advisory for product teams. It is a registered business in Tampere, Finland (Business ID 3600281-7), run by Erik Rekola. The audit measures a site or API against current standards using an independent public scanner plus published security scans, then returns a written report with prioritized fixes. **What does an agent-readiness audit cost?** turva.dev prices an audit at a fixed €6,500 for a two to three week engagement. The Shopify agent storefront check is a separate fixed-scope diagnosis at €1,900, delivered within 48 hours of the agreed written kickoff. Advisory is €3,000 per month with a three month minimum, and implementation is €1,500 per day, scoped per task. Prices exclude VAT, and the scope is written before any payment. **How long does an agent-readiness audit take?** A fixed-scope audit takes two to three weeks. The Shopify agent storefront check is delivered within 48 hours of the agreed written kickoff, with a retest of up to two corrected items within 14 days. Advisory and implementation run on the cadence the engagement sets. **What do you get from an agent-readiness audit?** A written report that lists each check, what the scanner found, and a concrete fix for each gap, ordered by priority. The result is verifiable. An independent scanner reads the site before and after, and the categories that were fixed read higher on the next scan. **How do I make my site agent-ready?** Publish the surfaces agents read, then measure the result. That means llms.txt, a markdown form of each page, a complete robots.txt and sitemap, JSON-LD for the facts on a page, the /.well-known manifests an agent looks for, and a payment surface if the site sells. Each of these has its own guide in the index. **How does the engagement work?** Async only. No calls, no calendar links, no discovery meetings. Replies within one business day. Fixed scope per engagement, written before payment, and an open-source reference implementation you can read before deciding. For an audit, contact info@turva.dev. ## Related - [What an agent-readiness audit is](/guides/agent-readiness-audit) - [Why agent-readiness should be measured, not asserted](/guides/measurement-led-agent-readiness) - [Common agent-readiness gaps on marketing sites](/guides/agent-readiness-gaps) --- # Agent-readiness, AEO and GEO: how they relate Three terms describe overlapping work, and the difference matters when you decide what to fix. Answer engine optimization (AEO) is about the pages, so an AI engine can quote them as the answer to a question. Generative engine optimization (GEO) is about the signal around the pages, so an engine trusts the source enough to cite it. Agent-readiness is wider than both, because it also covers whether an agent can act on the site, not only read and cite it. ## At a glance | Discipline | What it optimizes | Who consumes it | A typical fix | | --- | --- | --- | --- | | SEO | Ranking on a results page | A person choosing a link | Keywords, backlinks, page speed | | AEO | A page an engine can quote | An AI answer engine | Schema, quotable passages, clear facts | | GEO | The trust signal around the page | An engine deciding what to cite | Citations, directories, a resolved entity | | Agent-readiness | What an agent can read and act on | An AI agent that acts | llms.txt, MCP, APIs, commerce endpoints | ## Answer engine optimization AEO engineers the page itself. Structure, schema, source density, and passages an engine can lift cleanly. The practical test is whether the first sentence under a heading stands alone as a quotable answer, and whether the facts on the page are stated as data rather than buried in prose. Most of what makes a page AEO-ready also makes it agent-readable, because both depend on a machine reading the content without guessing. ## Generative engine optimization GEO engineers the trust signal. Directories, citations across independent sources, a consistent description of who you are, and a knowledge-graph entity an engine can resolve. An engine cites a source when several places agree on the same thing. AEO gives the engine something to quote. GEO gives it a reason to trust the quote. One without the other underperforms. ## Where agent-readiness goes further AEO and GEO stop at being read and cited. Agent-readiness adds the surfaces an agent needs to do something. An MCP server it can call, an API catalog it can enumerate, authentication it can pass, and commerce endpoints it can transact against. A site can be perfectly quotable and still give an agent nothing to act on. The reverse is also common, an API an agent could use that no engine can find. ## How to sequence the work Measure first, because the three overlap and you do not want to pay for the same fix twice. A scan shows which AEO and agent surfaces are present and which are missing. The page-level gaps are usually AEO and agent-readiness work, fixable on the site itself. The trust gaps are GEO work, earned offsite over time. The point of measuring is to spend effort where an engine or an agent actually changes its behavior, not where a checklist says you should. For a measured audit across agent-readiness, AEO and the agent surfaces an engine cannot see, contact info@turva.dev. ## Related - [SEO and agent-readiness are not the same](/guides/seo-vs-agent-readiness) - [How to get your site cited by AI assistants](/guides/get-cited-by-ai-assistants) - [llms.txt explained](/guides/llms-txt) --- # Agentic commerce readiness: selling to AI shopping agents An AI shopping agent buys on a person's behalf. It reads a catalog, compares options, and completes a checkout without a human filling in a form. Agentic commerce readiness is the work of making a site one of those agents can actually transact with, rather than one it skips because the path is unclear or blocked. ## What an agent needs to buy An agent needs three things in machine-readable form. It needs to find the offer, with a price and currency it can parse rather than infer from a layout. It needs a checkout it can drive through a protocol, not a page built for a mouse. And it needs the purchase to behave predictably, so the same call produces the same result every time. A catalog that looks perfect to a person can still be opaque to an agent on all three counts. ## The protocols in play Checkout is becoming a protocol rather than a page. Stripe and OpenAI shipped Instant Checkout inside ChatGPT in 2025. Google and Shopify introduced the Universal Commerce Protocol in early 2026, and it now carries its own discovery manifest at /.well-known/ucp. The discovery layer is settling on a small set of standards. An A2A Agent Card describes the interface, AP2 authorizes agent payments, ACP carries the checkout, and x402 lets an agent meet a price with HTTP 402 and continue. A site does not need all of them, but it needs the ones its buyers' agents speak, declared where an agent looks. ## Where the protocol draws the line UCP writes down the boundary between what an agent may finish alone and what a person has to approve. Its checkout capability is a state machine, and one of its states, requires_escalation, means programmatic execution is blocked by something like age verification or a regulatory step. Escalation is not failure. As of July 2026 the specification defines an Embedded Checkout Protocol for that state, a bidirectional JSON-RPC 2.0 channel between the agent's host and the merchant's checkout interface, so a person completes the blocking step without the session being thrown away. The cart carries a signals object for abuse prevention, and the specification is explicit that its values must not be buyer-asserted claims. A site that treats escalation as a dead end loses the sale at the exact point where a human was willing to finish it. ## Where sites fail the agent Most catalogs lose the agent before checkout. A price that lives only in rendered HTML, a CAPTCHA wall, a maintenance interstitial, or a discovery file that claims a capability the endpoint does not answer. Each one ends the purchase silently. The agent does not complain, it moves to a competitor whose path resolves. The failure looks like no traffic rather than a broken page, which is why it goes unmeasured. ## Readiness is testable Whether an agent can buy is observable, the same way agent-readiness is. Declare the offer as structured data, expose a checkout an agent can call, publish the discovery files the protocols define, and back every claim with an endpoint that answers. Then test it the way an agent would, by driving the path end to end and watching where it stops. turva.dev built and verified its own agent commerce surface this way, across A2A, AP2, ACP and x402, checked by an independent scanner. For an audit of whether AI shopping agents can discover and complete a purchase on your site, contact info@turva.dev. ## Related - [Agent commerce discovery: A2A, AP2, and ACP](/guides/agent-commerce-discovery) - [x402 and agent payments](/guides/x402-agent-payments) - [The /.well-known directory for agents](/guides/well-known-for-agents) --- # Letting agents act on data: the decision envelope Reading a site is the first step. The harder one is letting an agent act on a system that matters, where a wrong move has a cost. That depends on two things the model does not provide on its own. The data the agent works from has to arrive intact, and the decisions it is allowed to make have to sit inside a boundary you set. ## A decision is only as good as its inputs An agent's decision is bounded by the data that reaches it. In a clean environment that is invisible. Where the work happens it is the whole problem, because a dropped link, a delayed hop, or a lost packet can leave the agent working from stale input. The model did not get worse, its inputs did. Reliability lives in the layer below the model, where data either arrives in order and on time or it does not. ## The envelope is the real control A correct decision is not an agent doing whatever it infers. It is an agent acting inside an envelope defined for it, the permissions, the thresholds, and the explicit list of what it may touch and what it may not. The judgment is front-loaded into that boundary by a person who knew the stakes. Draw it loosely and a capable agent still does something, just not what you wanted. Draw it well and the same agent is one you can leave alone. ## The envelope is starting to appear in protocols Commerce is the first place the boundary got written down. As of July 2026 the Universal Commerce Protocol carries a checkout state called requires_escalation, which means the agent has reached the edge of what it may finish alone and a person has to complete the step. AP2 does the same on the payment side, where a mandate records the limits the user agreed to before the agent acted. Both encode a decision somebody made in advance. Neither decides for you where the line sits, and that is a judgment about which actions are reversible and who carries the cost when one is not. ## Keep a person where judgment belongs Letting agents act is not removing people. The stronger pattern carries a human expert's judgment to where the work is and lets the agent handle the parts that have to be instant or exact, with a clear point where control passes back. The hardest version is where no person can step in fast enough, so the decision has to be made locally under rules agreed in advance. The fields that work under that constraint learned the discipline first. ## Make it checkable An agent that acts has to be auditable. Log what it decided and why, keep the envelope explicit rather than implied, and verify after the fact that it stayed inside the boundary. Guardrails have to be checkable to count. That separates an agent that is impressive in a demo from one you would let touch a real operation. This is the work behind the Agent operations engagement. For a review of the data path, the decision envelope, and where a human stays in the loop, contact info@turva.dev. ## Related - [How agents authenticate](/guides/agent-authentication) - [Agentic commerce readiness](/guides/agentic-commerce-readiness) - [Why agent-readiness should be measured, not asserted](/guides/measurement-led-agent-readiness) - [AI agent use cases](/guides/ai-agent-use-cases) --- # AI agent use cases An AI agent is useful wherever data moves and a decision follows. It reads a machine-readable surface, decides inside the limits it was given, and acts on what it finds. The cases below are grouped by what the agent does, not by industry, because the same pattern repeats across all of them. ## Commerce and transactions An agent reads a product catalog, weighs the options against a buyer's constraints, and completes a checkout through a protocol rather than a form. The work is making the offer, the price, and the checkout legible and reliable enough for the agent to finish without a human in the loop. ## Monitoring and response An agent watches an API, a feed, or a system and acts the moment a threshold is crossed, with no one having to be watching. The work is a clean data path so the signal arrives in time, and a tight envelope so the agent takes only the actions it is allowed to. ## Field and frontline support An agent guides a person doing physical work, drawing on the same data an expert would and answering from it in the moment. The agent extends the expert's reach instead of standing in for the person at the far end. ## Operations under bad connectivity An agent runs a remote system over a link that drops, holding its last safe state and resuming cleanly when data returns. This is where the data path matters most, because one lost packet can stall every decision queued behind it. ## Back-office and data work An agent reconciles records across systems, flags only what does not match, and routes the rest. The value is consistency, a decision the agent makes the same way every time, with a trail you can audit afterwards. ## Autonomy at the edge An agent makes a time-critical call locally, where the round trip to a human is too slow to matter. The decision has to sit inside rules agreed in advance, because there is no one to ask. The fields that already live with hard time limits learned that discipline early. ## The common thread These are examples. The same discipline carries from one case to the next, and the question is rarely whether an agent could do the work. What decides the outcome is whether the data reaching it is clean and the envelope around it is set. If you want an agent to do one of these reliably, or to measure how ready your site or API is for agents in the first place, contact info@turva.dev. ## Related - [Agentic commerce readiness](/guides/agentic-commerce-readiness) - [Letting agents act on data: the decision envelope](/guides/letting-agents-act-on-data) - [What an agent-readiness audit is](/guides/agent-readiness-audit) --- # How to get your site cited by AI assistants When a person asks ChatGPT, Perplexity, Claude, or Gemini a question, the assistant answers from sources it can read and trust. Getting cited means being one of those sources. A site is cited when the assistant can reach its content, read it cheaply, confirm the facts, and find corroboration elsewhere. This guide covers what that takes. ## Be readable, not just rendered An assistant that does not run JavaScript sees an empty shell where a client-rendered page should be. The first requirement is that the content arrives in the response: a prerendered or static page, a markdown form served through content negotiation, and an llms.txt that maps the site. A page an assistant cannot read is a page it cannot cite. ## State your facts as data Prose can be summarized wrongly. JSON-LD states the facts of a page, such as the organization, the service, and the price, as data an assistant reads without inference. Structured data also ties a page to an entity an assistant already knows, which is why a Wikidata item and consistent sameAs links raise the odds that the assistant attributes the content to the right source. ## Be corroborated An assistant is more likely to cite a claim it can confirm in more than one place. A site that only references itself is weaker than one that independent sources also describe. Open-source code, a public company record, listings in directories an assistant trusts, and genuine third-party mentions all raise confidence. The signal is consistency across sources, not volume. ## Be indexed where the assistant searches Several assistants retrieve through a search index before they answer. If a site is not indexed where the assistant looks, it cannot be cited regardless of quality. Submitting URLs through the index protocols a site supports, and keeping the sitemap and llms.txt current, is how new content reaches that layer. ## Measure it Whether a site is cited is observable. Ask the assistants the questions a buyer would ask and record which sources they name. Repeat on a schedule. The sources that appear, and the ones that do not, tell you where the work is. turva.dev runs this check against its own queries. For an audit of how legible and citable a site is to assistants, contact info@turva.dev. ## Frequently asked **How do you get a site cited by AI assistants?** A site is cited when the assistant can reach its content, read it cheaply, confirm the facts, and find corroboration elsewhere. That means readable content in the first response, facts stated as data, independent corroboration, and being indexed where the assistant searches. **Why does corroboration matter for citation?** An assistant is more likely to cite a claim it can confirm in more than one place. Open-source code, a public company record, trusted directory listings, and genuine third-party mentions raise confidence. The signal is consistency across sources, not volume. ## Related - [Agent-readiness, AEO and GEO: how they relate](/guides/agent-readiness-aeo-geo) - [SEO and agent-readiness are not the same](/guides/seo-vs-agent-readiness) - [llms.txt explained](/guides/llms-txt) --- # Auth.md > Agent registration metadata for turva.dev. > Public read-only. No accounts. Credentials are optional and > only attribute correspondence. > Operator contact: . ## Agent registration turva.dev publishes public read-only metadata for AI agents. No endpoint requires a credential and there are no user accounts. This domain does publish OAuth protected resource metadata at /.well-known/oauth-protected-resource, which names an authorization server, three scope names and bearer tokens in the Authorization header. Read that document as discovery, not as protection: every declared resource answers an anonymous request exactly as it answers one carrying a token, and no scope grants access that anonymous does not already have. It is published so an OAuth-aware agent can discover the identity surface without guessing, not because a 401 is waiting. The only credential this domain issues is an optional api_key, provided out-of-band on request; it attributes correspondence and grants no additional access. This document describes how an operator can register an agent identity, request metadata corrections, and revoke prior correspondence. ## Identity - Operator: Erik Rekola (sole proprietorship, Finland) - Trade name: turva.dev - Business ID: 3600281-7 - Register: https://tietopalvelu.ytj.fi/yritys/3600281-7 - Verified contact: - Public profile: https://www.linkedin.com/in/erikrekola/ - Source code: https://github.com/erekola ## Supported identity types - anonymous: no registration, every resource is public read-only; an api_key can be issued out-of-band on request - identity_assertion: a registered operator identity, backed by a verified email or a signed assertion; the same api_key applies A credential only attributes correspondence. Every resource is public, none requires a credential, and no credential grants additional access. ## Registration Registration is handled by email; https://turva.dev/agent/auth/register returns the same pathway as JSON. Email with: - Agent identifier and software name - Operator name and legal entity - Purpose of access (research, integration, monitoring) - Expected request rate (per hour) and concurrency - Public contact for the operator A written acknowledgement is sent within one business day. ## Claim To claim an existing identifier, use https://turva.dev/agent/auth/claim or email . Include proof of operator control (DNS TXT, signed message from a known code hosting account, or a verified company email). ## Revocation To revoke prior correspondence or request deletion of stored metadata, use https://turva.dev/agent/auth/revoke or email . Records held to meet Finnish accounting obligations (invoices) cannot be deleted until the statutory retention period ends. ## Engagement principles - Async-only. No calls, no calendar links. - First reply in writing within one business day. - Production credentials are not requested. - No tracking, no analytics, no third-party scripts on this site. ## Related discovery - OAuth Authorization Server: https://turva.dev/.well-known/oauth-authorization-server - OAuth Protected Resource: https://turva.dev/.well-known/oauth-protected-resource - API catalog: https://turva.dev/.well-known/api-catalog - Security contact: https://turva.dev/.well-known/security.txt - Legal: https://turva.dev/legal