docs · concepts

Skills & SKILL.md

A skill is one task on one site, written down precisely enough that any agent, with any browser, can replay it: the exact selectors and — whenever possible — the direct in-page request.

Anatomy of a SKILL.md

A skill is a single SKILL.md file: YAML frontmatter for machines, a browser-agnostic recipe for the agent. The catalog id is the URL path ({domain}/{task}, e.g. linkedin.com/search-people); the frontmatter name is the kebab-case task name the agent registers natively.

linkedin.com/search-people · SKILL.md (abridged)
---
name: search-people
description: Search people on LinkedIn, one or many
  queries with auto-pagination.
site: linkedin.com
needs: [navigate, evaluate]
side_effect: read
auth: session
---

## Preconditions
A logged-in linkedin.com session in the browser profile.

## Execute
1. navigate to https://www.linkedin.com/feed/ (same-origin)
2. evaluate the Extractor with params { query, limit }

## Extractor
In-page async function: an authenticated fetch against the
site's own search API, parse, return the JSON below.

## Success assertion
returns.people is a non-empty array with name + profile url.

Frontmatter fields

FieldExampleMeaning
namesearch-peopleKebab-case, native-valid skill name — it must register cleanly into the agent’s own skill framework
descriptionOne paragraph: what it does and when to use it
sitelinkedin.comThe domain the skill operates on
needs[navigate, evaluate]Browser capabilities required to run it (see below)
side_effectreadSafety level: read, write or irreversible
authsessionWhether a logged-in session is required

Generic skills: one skill, a whole class of tasks

A generic skill is parameterized: it takes inputs and handles an entire class of requests on a site, instead of hard-coding a single case. search-people searches for any query and page count; get-profile fetches any slug. The same SKILL.md serves every call — you pass the params, the recipe stays put.

KindExampleCovers
genericlinkedin.com/search-peopleAny { query, limit } — one skill for every search
fixed-caseinstacart.com/search-limonOne frozen input (always searches “limon”) — no params

Prefer generic whenever the task has natural inputs: lift the varying values into params (declared in the description and read by the Extractor) and keep the steps fixed. A fixed-case skill is the shortcut — worth writing only when the input never changes, or as a first draft you later generalize.

Capabilities: skills never name a tool

A skill writes its steps in generic capability verbs — it never says “call browser_navigate”. Your agent maps each verb to whatever browser it actually has:

CapabilityWhat it must doPlaywright MCPclaude-in-chrome
navigate(url)Open a URL, establishing the sessionbrowser_navigatenavigate
evaluate(fn)Run JavaScript inside the page and read the resultbrowser_evaluatejavascript_tool
snapshot()Read the rendered page structurebrowser_snapshotread_page
click(ref)Click an elementbrowser_clickcomputer
type(ref, text)Type into a fieldbrowser_typeform_input
network()Read the page’s network requestsbrowser_network_requestsread_network_requests

Check needs up front: if your browser can’t provide a capability, switch to one that can. Skills ship CSS selectors, never ephemeral refs or screen coordinates — you resolve them at runtime.

How a skill executes

execution modelone path, any browser
1 · navigate(url)establishes the session and same-origin for the fetch
2 · evaluate(extractor, params)in-page authenticated fetch + parse, inside the site itself
3 · JSON resultread back through the evaluate channel, checked against the success assertion
privacy

The browser holds the session — cookies never leave it. The extractor runs inside the page, so authentication rides on the session that is already there.

Prefer doing DOM actions inside evaluate (document.querySelector(sel).click(), scrollIntoView()) — it behaves the same across every browser and beats native click/type for reliability.

Robust vs fragile skills

Declared needsShapeStability
[navigate, evaluate]One in-page fetch + parse against the site’s own APIrobust
includes click / type / snapshotUI-driven: depends on the rendered page and its markupmore fragile

Side-effect levels

LevelMeaningExamples
readOnly reads data — safe to run and retry freelysearch people, fetch a profile, list issues
writeChanges state somewhere, usually undoableadd to cart, save a draft
irreversiblePublishes or sends for real — confirm before runningsend a DM, post a comment, submit a connection request

Auth: auth: session

Skills that need a logged-in session declare it and list it under Preconditions. The rules are simple: