---
title: "Agent Skills Discovery"
description: "Publish local and externally hosted Agent Skills through the v0.2.0 well-known index."
canonical_url: "https://nuxtseo.com/docs/ai-ready/guides/agent-skills"
last_updated: "2026-09-14T00:59:35.794Z"
---

[Agent Skills Discovery](https://github.com/cloudflare/agent-skills-discovery-rfc) gives agents one URL for finding the skills published by your site:

```text
/.well-known/agent-skills/index.json
```

The index follows the v0.2.0 schema. Every entry includes a SHA-256 digest so clients can verify the artifact before loading it.

## The `skills/` convention

Put each skill in `skills/<name>/SKILL.md`{lang="text"} at the project root, or in a layer. That is the whole setup:

```text
skills/
└── seo-audit/
    └── SKILL.md
```

The module reads `name`{lang="yaml"} and `description`{lang="yaml"} from the frontmatter, publishes the skill in the discovery index with its digest, and serves the file at three addresses:

| Address                                                     | Purpose                                                                                                                                |
| ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `/.well-known/agent-skills/seo-audit/SKILL.md`{lang="text"} | The artifact the index advertises, with the digest                                                                                     |
| `/skills/seo-audit/SKILL.md`{lang="text"}                   | Mirrors the repository path                                                                                                            |
| `/SKILL.md`{lang="text"}                                    | The root address installers try first. Added when the project has exactly one local skill, or for the skill named in `root`{lang="ts"} |

llms.txt gains an **Agent Skills** section that links every published skill.

The frontmatter `name`{lang="yaml"} must equal the directory name, as the Agent Skills specification requires. A mismatch, missing description, or invalid frontmatter stops the build and names the file. A directory without a `SKILL.md`{lang="text"} is ignored.

When the project and a layer both ship a skill with the same name, the project wins. Layers outside the project root are skipped.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  aiReady: {
    agentSkills: {
      dir: 'agent-skills', // scan a different folder; false turns discovery off
      root: 'seo-audit', // which skill answers /SKILL.md; false publishes none
      llmsTxt: false, // leave llms.txt alone
    },
  },
})
```

Set `agentSkills: false`{lang="ts"} to turn the feature off entirely.

### Hook

Every skill about to be published passes through `ai-ready:agent-skills`{lang="ts"} before the root alias is applied. Add an external entry, drop a skill, or change its aliases:

```ts [modules/skills.ts]
export default defineNuxtModule({
  setup(_, nuxt) {
    nuxt.hook('ai-ready:agent-skills', ({ skills }) => {
      skills.push({
        source: 'external',
        name: 'seo-toolkit',
        type: 'archive',
        description: 'Use the complete SEO toolkit and its supporting resources.',
        url: 'https://cdn.example.com/seo-toolkit.tar.gz',
        digest: 'sha256:…',
      })
    })
  },
})
```

## Explicit entries

Explicit entries in `agentSkills.skills`{lang="ts"} are merged after discovery. An explicit entry with the same `name`{lang="ts"} replaces the discovered one, which is how a project points a skill at a file outside `skills/`{lang="text"} or vendors one from a package.

## Local [SKILL.md](http://SKILL.md) files

Use a local entry when the skill consists of one `SKILL.md`{lang="text"} file:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  aiReady: {
    agentSkills: {
      skills: [{
        source: 'local',
        name: 'seo-audit',
        description: 'Audit a site for critical SEO issues.',
        file: './skills/seo-audit/SKILL.md',
      }],
    },
  },
})
```

Nuxt resolves `file`{lang="ts"} from the project root, reads it once during setup, and computes its digest from the original bytes. The path and its resolved symlink target must stay inside the project root. The index advertises this relative artifact URL:

```text
seo-audit/SKILL.md
```

The relative URL resolves from the index directory. This keeps local artifacts correct when Nuxt redirects discovery into a non-root app base.

The file must start with YAML frontmatter. Its `name`{lang="yaml"} and `description`{lang="yaml"} must exactly match the config:

```md [skills/seo-audit/SKILL.md]
---
name: seo-audit
description: Audit a site for critical SEO issues.
---

# SEO audit

Check indexability, metadata, canonical URLs, and structured data.
```

Local files must contain valid UTF-8 text and Markdown instructions after the frontmatter. Invalid config or unreadable files stop the Nuxt build with the failing entry and field.

### Serve the file at a root address

Discovered skills get `/skills/<name>/SKILL.md`{lang="text"} and, for a single skill, `/SKILL.md`{lang="text"} automatically. An explicit entry can name its own addresses with `alias`{lang="ts"}, one string or a list:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  aiReady: {
    agentSkills: {
      skills: [{
        source: 'local',
        name: 'seo-audit',
        description: 'Audit a site for critical SEO issues.',
        file: './skills/seo-audit/SKILL.md',
        alias: '/SKILL.md',
      }],
    },
  },
})
```

An alias must be a path-absolute route that ends in `.md`{lang="text"}, sit outside `/.well-known/`{lang="text"}, and avoid the module-owned `/index.md`{lang="text"} and `/sitemap.md`{lang="text"}. Content negotiation leaves aliases alone, so the response is the file itself, with no generated frontmatter and the same digest as the discovery artifact. The index keeps advertising the `.well-known`{lang="text"} URL.

## External files and archives

Use an external entry for a `SKILL.md`{lang="text"} or archive that you already host:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  aiReady: {
    agentSkills: {
      skills: [{
        source: 'external',
        name: 'seo-toolkit',
        type: 'archive',
        description: 'Use the complete SEO toolkit and its supporting resources.',
        url: 'https://cdn.example.com/seo-toolkit.tar.gz',
        digest: 'sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
      }],
    },
  },
})
```

External entries accept HTTP(S), path-absolute, and index-relative URLs. Nuxt validates the URL and digest format but does not download the artifact during setup. Calculate the digest from the exact bytes served at `url`{lang="ts"}.

Use `type: 'skill-md'`{lang="ts"} for one Markdown file. Use `type: 'archive'`{lang="ts"} for a `.tar.gz`{lang="text"} or `.zip`{lang="text"} containing `SKILL.md`{lang="text"} plus scripts, references, or assets.

The index and embedded local files support GET and HEAD. Other methods return 405. Responses include public cache headers and `Access-Control-Allow-Origin: *`{lang="http"} for browser clients.

For non-root app bases, Nuxt redirects origin-root discovery requests to the base-aware index and artifact routes.

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
