[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"lab-entry-llms-txt-service-json-ld-agent-test":3},{"entry":4,"newer":40,"older":44},{"slug":5,"tag":6,"issueNumber":7,"publishedAt":8,"title":9,"excerpt":10,"readingTimeMinutes":11,"updatedAt":12,"bodyHtml":13,"cover":14,"videoUrl":18,"links":19,"stack":32,"nextStep":39},"llms-txt-service-json-ld-agent-test","Experiment",4,"2026-10-28T05:07:26.944905+00:00","llms.txt and Service JSON-LD on my site, then two AI agents tested it","I made my site readable for AI agents, then sent two. Both got the prices right. One added other people's images; the other missed my project form.",5,"2026-10-28T07:48:42.80958+00:00","\u003Ch3>The problem\u003C\u002Fh3>\n\u003Cp>AI agents now visit sites on people's behalf. They read the page, compare prices and fill in forms (\u003Ca href=\"https:\u002F\u002Fwww.tryprofound.com\u002Fblog\u002Fthe-era-of-personal-agents-muse-and-instinct\">Profound\u003C\u002Fa>). Until this change, an agent had little to work with on my site: the three services and their &quot;from&quot; prices were on the page but not in structured data, \u003Ccode>\u002Fllms.txt\u003C\u002Fcode> returned a 404, and \u003Ccode>\u002Flab\u003C\u002Fcode> had no JSON-LD.\u003C\u002Fp>\n\u003Ch3>What I built\u003C\u002Fh3>\n\u003Cp>The What I do section already reads its services from one data file, \u003Ccode>shared\u002Fdata\u002Fhomepage.ts\u003C\u002Fcode>. I made three more things read from the same file, so the page, the structured data and \u003Ccode>llms.txt\u003C\u002Fcode> can't drift apart.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Service JSON-LD on the homepage.\u003C\u002Fstrong> One \u003Ccode>Service\u003C\u002Fcode> per service, each with an \u003Ccode>Offer\u003C\u002Fcode> holding its &quot;from&quot; price as \u003Ccode>minPrice\u003C\u002Fcode>, the currency and the pricing model. A service with no confirmed price gets no \u003Ccode>Offer\u003C\u002Fcode>. This is the AI App Rescue block as the live site serves it:\u003C\u002Fp>\n\u003Cpre tabindex=\"0\">\u003Ccode class=\"language-json\">\u003Cspan class=\"hljs-punctuation\">{\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-attr\">&quot;@context&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">:\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;https:\u002F\u002Fschema.org&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">,\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-attr\">&quot;@type&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">:\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;Service&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">,\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-attr\">&quot;name&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">:\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;AI App Rescue&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">,\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-attr\">&quot;description&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">:\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;A 48-hour audit of the app&#x27;s security, auth, database rules and performance, with a prioritized fix plan. Then, when you want it, a rescue sprint that takes the app from fragile demo to production.&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">,\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-attr\">&quot;provider&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">:\u003C\u002Fspan> \u003Cspan class=\"hljs-punctuation\">{\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-attr\">&quot;@type&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">:\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;Person&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">,\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-attr\">&quot;name&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">:\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;Ahmed Saad&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">,\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-attr\">&quot;url&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">:\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;https:\u002F\u002Famdsaad.com\u002F&quot;\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-punctuation\">}\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">,\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-attr\">&quot;offers&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">:\u003C\u002Fspan> \u003Cspan class=\"hljs-punctuation\">{\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-attr\">&quot;@type&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">:\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;Offer&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">,\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-attr\">&quot;description&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">:\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;fixed price, 48-hour audit&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">,\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-attr\">&quot;priceCurrency&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">:\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;USD&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">,\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-attr\">&quot;priceSpecification&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">:\u003C\u002Fspan> \u003Cspan class=\"hljs-punctuation\">{\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-attr\">&quot;@type&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">:\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;PriceSpecification&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">,\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-attr\">&quot;minPrice&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">:\u003C\u002Fspan> \u003Cspan class=\"hljs-number\">299\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">,\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-attr\">&quot;priceCurrency&quot;\u003C\u002Fspan>\u003Cspan class=\"hljs-punctuation\">:\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;USD&quot;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-punctuation\">}\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-punctuation\">}\u003C\u002Fspan>\n\u003Cspan class=\"hljs-punctuation\">}\u003C\u002Fspan>\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Cstrong>\u003Ccode>\u002Fllms.txt\u003C\u002Fcode>, generated, not written by hand.\u003C\u002Fstrong> It has my short bio, the services with &quot;from&quot; prices, the booking link, the email, the Fiverr rating and the published Lab entries. It's cached like the sitemap (\u003Ccode>Cache-Control: s-maxage=60, stale-while-revalidate\u003C\u002Fcode>). One section of the live file:\u003C\u002Fp>\n\u003Cpre tabindex=\"0\">\u003Ccode class=\"language-markdown\">## Work with me\n\n- [Book a 20-min call](https:\u002F\u002Fcal.com\u002Fahmed-saad-soliman-axzyti\u002F20-min-meeting)\n- Email: hello@amdsaad.com\n- [Fiverr](https:\u002F\u002Fwww.fiverr.com\u002Famdsaad): Rated 5.0 from 52 reviews\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Cstrong>Fiverr and Bluesky in the Person \u003Ccode>sameAs\u003C\u002Fcode>.\u003C\u002Fstrong> Bluesky waited until its profile URL was confirmed in my brand facts file. No fact goes on the site unconfirmed, even an obvious URL.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>CollectionPage JSON-LD on \u003Ccode>\u002Flab\u003C\u002Fcode>\u003C\u002Fstrong>, listing the published entries as \u003Ccode>BlogPosting\u003C\u002Fcode>s.\u003C\u002Fp>\n\u003Ch3>Then I sent two agents\u003C\u002Fh3>\n\u003Ch4>Test 1: ChatGPT with search\u003C\u002Fh4>\n\u003Cp>I asked ChatGPT, with search on, what Ahmed Saad offers. The text was accurate: all three services, the &quot;from&quot; prices ($2,500, $1,500 and $299), the 4 care hours, the first reply within 1 business day, the three model providers, and 2–4 weeks for one AI feature.\u003C\u002Fp>\n\u003Cp>But it put a picture next to each service, and none of them is on my site. They came from its own image search. Two I traced: a Dribbble shot (\u003Ccode>cdn.dribbble.com\u003C\u002Fcode>) and an image from a Webflow site (\u003Ccode>cdn.prod.website-files.com\u003C\u002Fcode>). A reader could take them for my work.\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"\u002Fmedia\u002Flab\u002F8ecb9955-4edf-45d3-b92e-0446c3f38a07-1566x1005.webp\" alt=\"ChatGPT's answer listing my three services and their prices, with the three pictures it added blurred\" width=\"1566\" height=\"1005\" loading=\"lazy\" decoding=\"async\">\u003C\u002Fp>\n\u003Ch4>Test 2: Claude Code driving a browser\u003C\u002Fh4>\n\u003Cp>I gave Claude Code (Sonnet 5.5) a task written as a client:\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>I have an AI-built app that's slow and might be leaking data. Go to amdsaad.com, find the right service, tell me what it costs and what's included, then open the project form and fill it in for me. Don't send it until I say.\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>Claude in Chrome wasn't connected, so it drove a separate browser through Playwright.\u003C\u002Fp>\n\u003Cp>It picked AI App Rescue and got the price, what's included and what isn't right. It also caught a real gap: the page gives no price for the rescue sprint. My brand facts have rescue sprints from $1,500, but the card doesn't show it.\u003C\u002Fp>\n\u003Cp>Then it said: &quot;AI App Rescue is the right service, but the site has no project form to fill in.&quot;\u003C\u002Fp>\n\u003Cp>That's wrong, and it's the most useful finding. Every &quot;Tell me about your project&quot; trigger is a mailto link in the server HTML, so the site works without JavaScript. From the live page, with the class list removed:\u003C\u002Fp>\n\u003Cpre tabindex=\"0\">\u003Ccode class=\"language-html\">\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">a\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">href\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;mailto:hello@amdsaad.com&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">rel\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;noopener noreferrer&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>Tell me about your project (AI App Rescue)\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">a\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Once the JavaScript loads, a click opens the form dialog. The agent read the \u003Ccode>mailto:\u003C\u002Fcode>, didn't click, and offered an email draft or a cal.com booking instead. What works for people and for visitors without JavaScript hid the form from an agent.\u003C\u002Fp>\n\u003Cp>One caveat: the agent ran inside my repo folder and read a source file, so it wasn't a clean outside visitor.\u003C\u002Fp>\n\u003Ch3>What I learned\u003C\u002Fh3>\n\u003Col>\n\u003Cli>\u003Cstrong>An agent can read your facts correctly and still fill the gaps with other people's images.\u003C\u002Fstrong> Two of my services have no image yet. That empty space didn't stay empty.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Agents act on what the HTML says, not on what the JavaScript will do.\u003C\u002Fstrong> A link that turns into a dialog after the page loads is, to an agent, just a link.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>One data file for the page, the JSON-LD and \u003Ccode>llms.txt\u003C\u002Fcode> held up.\u003C\u002Fstrong> Every price both agents quoted matched the page.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch3>What happened next\u003C\u002Fh3>\n\u003Cp>I built the fixes and ran the test again: \u003Ca href=\"\u002Flab\u002Fagent-test-rerun-button-hidden-copy\">Rerunning the AI agent test: a real button, and a hidden copy of it\u003C\u002Fa>.\u003C\u002Fp>\n",{"src":15,"width":16,"height":17},"\u002Fmedia\u002Flab\u002F17671185-f5d2-43ac-bb66-55128cab1e0f-1472x816.webp",1472,816,null,[20,23,26,29],{"label":21,"url":22},"amdsaad.com\u002Fllms.txt","https:\u002F\u002Famdsaad.com\u002Fllms.txt",{"label":24,"url":25},"llms.txt: the proposal","https:\u002F\u002Fllmstxt.org",{"label":27,"url":28},"schema.org: Service","https:\u002F\u002Fschema.org\u002FService",{"label":30,"url":31},"Profound: how personal agents read pages","https:\u002F\u002Fwww.tryprofound.com\u002Fblog\u002Fthe-era-of-personal-agents-muse-and-instinct",[33,34,35,36,37,38],"Nuxt","schema.org JSON-LD","llms.txt","ChatGPT","Claude Code","Playwright","Built your app with an AI tool and not sure it's safe to run?",{"slug":41,"tag":6,"issueNumber":11,"publishedAt":42,"title":43},"agent-test-rerun-button-hidden-copy","2026-10-28T07:32:46.682425+00:00","Rerunning the AI agent test: a real button, and a hidden copy of it",{"slug":45,"tag":46,"issueNumber":47,"publishedAt":48,"title":49},"obsidian-vault-as-hermes-agent-second-brain","Build notes",3,"2026-10-27T16:38:29.507366+00:00","My Obsidian vault is my Hermes Agent's second brain"]