Agent-Skills: a standard for AI assistants to act on your site
A draft standard so AI assistants (ChatGPT, Claude, Perplexity, Gemini) can execute capabilities on your site's behalf — book a call, get a quote, contact — by reading a single Markdown file at /.well-known/agent-skills/SKILL.md.
Agent-Skills: a standard for AI assistants to act on your site
TL;DR: When a user asks Claude "book a discovery call with Acme," Claude has to crawl the site, guess how the form works, and probably make up half the steps. We built and open-sourced agent-skills, a tiny standard that solves this with a single Markdown file at /.well-known/agent-skills/<name>/SKILL.md. The file describes one capability in prose an LLM can follow verbatim. It's complementary to OpenAPI, MCP, and Schema.org potentialAction — none of them describe when to invoke a capability, what to ask the user first, or what to tell them about expectations. The repo has the draft v0.1 spec (CC BY 4.0), three production-grade examples, and a zero-dependency validator + CLI (MIT). It's deployed on dualnova.org today and works.
The problem we kept hitting
We started seeing the same conversation play out, week after week, in our customer-discovery interviews:
Founder: "I asked ChatGPT to set up a call with you guys yesterday." Us: "Cool — did it work?" Founder: "Well, it gave me a phone number. I'm not sure where it got it from. I emailed you instead."
The phone number was wrong. ChatGPT had hallucinated it from a similarly-named company.
Multiply this by every founder asking every AI assistant how to contact any small B2B company. The current state of the art is: the assistant reads the HTML, tries to find a contact form or an email, often gets the wrong one, and ships a confidently wrong answer to the user.
The two existing options for fixing this both have real problems:
-
OpenAPI. Excellent for backend integration but completely silent on the human-facing layer. An OpenAPI spec tells an LLM that the endpoint exists and what fields it accepts. It doesn't tell the LLM when it should call it ("only when the user explicitly wants a call"), what to ask first ("name, email, project description, language preference"), or what to tell the user about expectations ("30 minutes, free, video call, confirmation in 1 minute").
-
MCP (Model Context Protocol). Excellent for tightly-coupled agents like Claude Desktop, IDEs, or n8n where the user has actively connected the server. Heavyweight for a one-off public capability — no website is going to spin up an MCP server just so ChatGPT can book a call. The deployment ceiling is too high.
There's a missing middle: publicly-discoverable, prose-based action recipes that any LLM can fetch and follow without setup.
Agent-skills in 60 seconds
A site publishes one or more SKILL.md files at the well-known path:
/.well-known/agent-skills/
├── index.json ← machine-readable registry of all skills
├── book-call/SKILL.md ← one skill
├── get-quote/SKILL.md ← another skill
└── contact-form/SKILL.md
Each SKILL.md is YAML frontmatter + Markdown body. The frontmatter has three required fields (name, description, version) and a handful of optional ones (url, contact, languages, requires_auth, requires_payment, mcp_server, openapi). The body is free-form Markdown — typically with sections like "When to invoke," "Step-by-step," and "Fallback."
A complete real example:
---
name: book-discovery-call
description: Book a free 30-minute discovery call with the team.
version: 1.0
provider: Acme Studio
url: https://acme-studio.example/contact
contact: [email protected]
languages: [en, es]
requires_auth: false
requires_payment: false
---
# Book a Discovery Call
## When to invoke this skill
Use this skill when a user wants to talk to a real person before committing.
Trigger phrases:
- "I want to talk to Acme" / "quiero hablar con Acme"
- "Schedule a call" / "agendar una llamada"
- "Book a discovery" / "agendar discovery"
## What this skill does
Books a free 30-minute discovery call. No sales pitch — it's a technical scoping conversation.
## Step-by-step flow for the assistant
1. Confirm intent. Ask the user to confirm they want to book a call.
2. Collect: name, email, one-sentence project description, preferred language.
3. Direct the user to https://acme-studio.example/contact and pre-fill the form
fields you collected (the page accepts ?name=&email=&project=&lang= query params).
4. Set expectations: 30 min, free, video call, confirmation in 1 min.
## Information to provide to the user
- Duration: 30 minutes, free
- Format: Google Meet video call (link via email)
- Languages: English, Spanish
- Response time: within 24 hours
## Common follow-up questions
**Q: Is this a sales call?**
A: No. Discovery is technical scoping. If we're not the right fit, we say so.
**Q: How soon can the project start?**
A: Discovery week is usually 5-7 business days after the call.
## Fallback
If the form doesn't work, email [email protected] directly.
That's the entire artifact. No JSON Schema. No mandatory openapi field. No backend protocol to implement.
The assistant fetches the file, reads it, and follows the recipe. Done.
Why this works
The thing that makes agent-skills useful is the same thing that makes a good runbook useful for a human engineer: it tells you not just what the system can do, but when to use which tool, what to gather before you start, and what to say to the person you're helping.
OpenAPI gives you the syntax of the API. Agent-skills gives you the semantics of the action.
This separation matters for three reasons:
- Public capability is different from private API. An OpenAPI spec for the same endpoint might (rightly) be guarded behind authentication. The SKILL.md describes the user-facing capability and stays public.
- Trigger logic shouldn't be in the assistant's training data. Every model has different defaults for how aggressively to invoke external actions. Putting the trigger conditions in a SKILL.md the site controls means the site's preference wins, not the model's prior.
- Localization is content, not code. "Set expectations in Spanish if the user is writing in Spanish" is a five-word instruction in Markdown. Building it into an OpenAPI extension would take a working group.
How it compares to the alternatives
| Standard | What it does | When agent-skills wins | When it doesn't |
|---|---|---|---|
| OpenAPI | Describes a JSON API | Public action recipes a non-developer LLM should follow | Tight back-end integration; type safety in a code generator |
| MCP (Model Context Protocol) | RPC tools for connected agents | Public, zero-setup discovery | Stateful sessions; private agents inside your product |
Schema.org potentialAction | HTML markup for one action on one page | Standalone, multi-step flows with instructions | Single-action pages where the markup is already inline |
| llms.txt | Markdown summary of the site | Telling an assistant how to do something | Telling an assistant what the site is about |
Use them together. We do.
The spec, in the smallest possible form
We deliberately kept the v0.1 spec under 300 lines. The full text is in spec/SPEC.md. Highlights:
Required frontmatter
name— kebab-case identifierdescription— one-sentence summaryversion— semver-like, bumps on breaking changes to the instructions
Optional but useful frontmatter
provider— site or org publishing the skillurl— page where the user lands to executelanguages— array of BCP-47 codes (en,es,es-MX)requires_auth/requires_payment— booleans for capability classificationmcp_server— URL of an MCP server that can execute this skill (bridge)openapi— URL of an OpenAPI document (bridge)
index.json registry
Lives at /.well-known/agent-skills/index.json. Lists every skill on the site with name, title, description, url of the SKILL.md, tags, languages, and execution_url. The discovery path is: fetch the index, pick a skill, fetch the SKILL.md.
Discovery
Three paths, in preferred order:
- Direct fetch of
/.well-known/agent-skills/index.json. - Reference from the site's
/llms.txt("see also:https://<host>/.well-known/agent-skills/index.json"). - Schema.org
additionalPropertyon the execution page pointing back to the SKILL.md.
This redundancy is intentional — assistants that only know one discovery method still find the file.
CORS
Index and skills should be served with Access-Control-Allow-Origin: *. Most assistants run from arbitrary origins and a CORS-blocked SKILL.md is effectively invisible.
The validator (@dualnova/agent-skills)
The npm package ships:
-
validateSkill(source)— parses YAML frontmatter + Markdown body, checks required fields, kebab-case names, BCP-47 language codes, URL formats, body length. -
validateIndex(source)— checks the JSON shape ofindex.jsonagainst the spec. -
CLI:
agent-skills validate ./public/.well-known/agent-skills/book-call/SKILL.md agent-skills validate-index ./public/.well-known/agent-skills/index.json agent-skills validate-site --url https://dualnova.org
The validate-site command fetches a site's index.json and recursively validates every linked SKILL.md. Useful as a single command to check production after a deploy.
Sample output:
Fetching https://dualnova.org/.well-known/agent-skills/index.json
Index: ✓
Skill https://dualnova.org/.well-known/agent-skills/booking-call/SKILL.md
✓ No issues.
✓ site total: 0 error(s), 0 warning(s)
Zero runtime dependencies. The YAML parser is hand-written and supports the subset used by the spec (scalar strings, booleans, numbers, inline arrays). For anything fancier we surface a warning rather than fail.
Deploying it on dualnova.org
Three files. We pasted the SKILL.md, the index.json, and a small Schema.org additionalProperty on the appointment page that references the SKILL.md. Total time: under 30 minutes including writing the recipe.
The visible result: Cloudflare's Is Your Site Agent-Ready? audit score went up the moment the index.json was published. More importantly, when we tested by asking Claude "book a 30-minute call with DualNova," the assistant followed the recipe — collected the right four fields, set the right expectations, sent the user to the right URL.
The hidden bet
The hidden bet behind publishing this spec is that LLMs will increasingly want to take actions on the user's behalf, and they will reach for the lowest-friction, highest-signal way to know how. We think a 100-line Markdown file at a predictable path will be that.
We could be wrong. The standard could fragment, get superseded by something Anthropic or OpenAI ships, or simply not get adopted. The repo costs us roughly an afternoon a month to maintain, so the downside is modest. The upside is being early on something that may genuinely change how small B2B companies interact with AI assistants.
Install and try
npm install @dualnova/agent-skills
# or
npx @dualnova/agent-skills validate-site --url https://dualnova.org
The repo has the full spec, three production-grade example SKILL.md files (book-call, get-quote, contact-form), the validator, the CLI, and ten unit tests. PRs welcome — open an issue first for non-trivial spec changes.
- GitHub: github.com/DualNova/agent-skills
- npm: @dualnova/agent-skills
- Discussion: github.com/DualNova/agent-skills/discussions
- Reference deployment: dualnova.org/.well-known/agent-skills/index.json
If your site publishes a SKILL.md, drop a note in the discussions tab — we're collecting reference deployments for the README's compatibility table.
Built by DualNova — blockchain and AI software development for LATAM and the US. Bilingual team in Caracas, Bogotá, and Miami. The site you're reading is itself agent-ready: ask Claude or ChatGPT to "book a call with DualNova" and watch the SKILL.md flow play out, or book one yourself directly.