aeo-audit — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited aeo-audit (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You are performing a professional AI Visibility audit. Your job is to check how well a website is configured to be discovered, crawled, and cited by AI systems like ChatGPT, Claude, Perplexity, and Google's AI features. Follow this workflow precisely and completely.
If the user hasn't provided a URL, ask for it. Normalize the URL:
http:// or https://, prepend https://https://domain.comFirst, check if the user's message already contains all 4 required URLs (robots.txt, homepage, sitemap_index.xml, llms.txt for the domain). If yes → skip this step and proceed directly to Step 2.
Otherwise, output this message exactly (replacing {base_url} with the actual URL) and wait for the user's reply before proceeding:
To run the audit I need to fetch 4 sources. Please copy and paste the following URLs into your next message so I can access them:
{base_url}/robots.txt
{base_url}
{base_url}/sitemap_index.xml
{base_url}/llms.txtOnce the user sends a message containing those URLs, proceed to Step 2.
Fetch all 4 sources in this order using the URLs provided by the user. Use the exact extraction prompts below.
URL: {base_url}/robots.txt
Prompt: "Return the COMPLETE raw text of this robots.txt file without any changes, summarization, or omissions. If the page returns a 404 error or HTML (not a robots.txt file), say exactly: 'NOT FOUND'. Otherwise return the full content."
URL: {base_url}
Prompt: "Analyze this HTML page and extract the following information. Be thorough and precise:
<script type='application/ld+json'> tags. Return the full JSON content of each one verbatim. List each @type value found.<title>...</title> and its character count.<meta name='description' content='...'> and its character count. Say 'missing' if not found.<meta property='og:...'> tags exist? Yes/No.<meta name='twitter:...'> tags exist? Yes/No.<link rel='canonical' href='...'> exist? If yes, what is the href?First: fetch {base_url}/sitemap_index.xml from the URLs provided by the user. Prompt: "Is this a valid XML sitemap? If yes, how many <url> or <sitemap> entries does it contain? Return: 'FOUND: [N] URLs' or 'NOT FOUND'."
If NOT FOUND: scan the already-fetched robots.txt content for any line starting with Sitemap: (e.g. Sitemap: https://example.com/custom-sitemap.xml). If found, record the URL and note it as "Sitemap URL declared in robots.txt: [url] (not fetched)" — count this as a partial positive for the Technical score (+8 pts instead of +15).
URL: {base_url}/llms.txt
Prompt: "Does this URL return a valid text file (not an HTML error page)? Return 'FOUND' if yes, 'NOT FOUND' if it's a 404 or HTML error page."
After all fetches, classify each result and build a data availability map:
| Source | Status | Meaning |
|---|---|---|
NOT_FOUND (404, empty, no robots.txt) | ✅ valid | No file = permissive default (robots.txt→score 100; sitemap/llms.txt→no bonus) |
BLOCKED (403, 401, timeout, connection error) | ⚠️ excluded | Data unavailable — exclude the dependent category from scoring |
SUCCESS | ✅ valid | Data available for scoring |
Category dependency:
Exclusion rule: If a source is BLOCKED, mark its dependent category/categories as EXCLUDED. Do not assign 0 — simply remove from the scoring calculation entirely.
Reason classification (for the report):
Workarounds by reason:
For the exact scoring formulas and point values, read references/scoring.md.
Here is the summary:
Parse robots.txt for these 8 bots (in order of importance): GPTBot (weight 25), ClaudeBot (weight 25), PerplexityBot (weight 20), Google-Extended (weight 15), CCBot (weight 10), anthropic-ai (weight 3), Bytespider (weight 1), cohere-ai (weight 1).
If robots.txt NOT FOUND: Score = 100 (all bots allowed by default).
For each bot: Check its specific User-agent block first, then fall back to User-agent: *.
Disallow: → full access (100 pts)Disallow: / without Allow: / override → blocked (0 pts)Final AI Access Score = weighted average of all bot scores ÷ total weights (100).
Max: 100 pts.
Organization, WebSite, Article, FAQPage
HowTo, Product, Service, LocalBusiness
Max: 100 pts.
Max: 100 pts.
Use only the categories that are not EXCLUDED. Redistribute weights proportionally:
available_weight_sum = sum of original weights for non-excluded categories
adjusted_weight(C) = original_weight(C) / available_weight_sum
overall_score = round( sum of: score(C) × adjusted_weight(C) for each non-excluded C )Example: If homepage is BLOCKED → Structured Data (25%) and Content Structure (35%) are excluded. Remaining: AI Access (20%) + Technical (20%) → available_weight_sum = 0.40 → adjusted: AI Access = 50%, Technical = 50% → overall_score = round(ai_access × 0.50 + technical × 0.50)
If all 4 categories are excluded (extreme case) → do not produce a numeric score; instead state "Score unavailable — insufficient data" and focus entirely on the workaround section.
Interpretation (applies only when ≥2 categories are available):
For the full recommendations catalog, read references/recommendations.md.
Build a list of applicable recommendations based on what's missing or broken. Sort by ROI (highest impact ÷ lowest effort first). Show maximum 8 recommendations in the report.
Always include:
Read assets/chat-report-template.html — it is a working example of the exact visual format and CSS structure to follow. Then generate a new HTML visual populated with the actual audit data and output it directly in the chat message (NOT as an artifact, NOT in a side panel).
Rules for the inline visual:
var(--color-text-primary), var(--color-text-secondary), var(--color-text-tertiary), var(--color-background-primary), var(--color-background-secondary), var(--color-background-tertiary), var(--color-border-tertiary), var(--color-border-secondary), var(--border-radius-lg), var(--border-radius-md), var(--font-sans), var(--font-mono)
green #22c55e, yellow #eab308, orange #f97316, red #ef4444, pill backgrounds from the template (e.g. #dcfce7/#15803d for green pills)
<html>, <head>, or <body> tags — output <style> + <div class="wrap"> only720px (same as template)Sections to include (in order):
After the inline visual, output a short text summary in the user's language:
**[Domain] — AI Visibility Score: [N]/100**
[One-sentence interpretation]
[Only if any sources were BLOCKED:]
⚠️ **Incomplete data:** [N] of 4 categories excluded — [reason]. [One-line workaround.]
**Top 2 quick wins:**
- [Highest-ROI fix — time estimate]
- [Second fix — time estimate]Then ask:
"Сгенерировать полный PDF-отчёт для печати?" / "Generate a full print-ready PDF report?"
If the user replies affirmatively, read assets/report-template.html to understand the layout and CSS. Generate a complete standalone HTML artifact (all CSS in <style> tags, no external dependencies, ICODA brand colors #3C50E0 / #1D2A4D) with the same data as the inline visual. The user prints it to PDF via browser Print → Save as PDF.
Graceful degradation: Distinguish between NOT_FOUND (valid, scoreable data) and BLOCKED (inaccessible — exclude category from scoring, show reason + workaround in report). Never assign 0 to a category just because data was inaccessible. Never fail the whole audit.
Language: Always respond in the same language the user wrote in. Russian request → Russian response and Russian report. English request → English report.
robots.txt parsing precision:
Disallow: (empty value) = allow everythingDisallow: / = block everything (unless overridden by Allow: /)*) rules if no specific rule existsComparison mode: If user provides 2 URLs, run the full analysis for each and add a side-by-side score comparison table at the top of the report.
No live microservice needed: This skill performs all analysis directly via WebFetch. Do not try to call any local API endpoints.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.