Skip to content

Skills: standard operating procedures

This document owns what a Skill is, how one is written, pinned, kept up to date, delivered to each harness and traced. Other documents link here and keep only their own part: the worker Skill at launch, the Skill loader, learned Skills, Skills from extensions and the swarm Skills catalog.

Status:

  • Source candidate: local maia agent loads Project Skills pinned by digest from .maia/maia.json; the maia-worker Skill, injected into every coding Session at launch (D-087, D-105); the maia-orchestration Skill in the maia plugin, whose command claims a bundle check keeps true.
  • Planned: the rest of this page. Mainly S13 (install, status, check and update through the skills CLI, D-170), AI0–AI3 (Maia's own Skills, installed into each detected harness, D-190), S22 (the catalog), FV4 (Project Skills at launch), S49 and S50 (Agents and Routines name their Skills), R11 (the typed Skill loader), R4 (learned Skills) and S73 (Skills from extensions).

What a Skill is

A Skill is a standard operating procedure (SOP) for agents: the steps to do one kind of work with Maia's primitives, and how to prove the work is done. Maia's operations are the verbs (create, send, wait, confirm); a Skill strings them into a procedure (D-026). People write and review Skills like code. Agents follow them, attended or unattended.

Example: a release-prepare Skill says when it applies (before a release branch is cut), lists the steps (check that the Run's tasks settled, run the acceptance tests, open the pull request, ask the release owner to confirm), says how to prove each step, when to stop and ask a person, and what to report.

PrimitiveHoldsAppliesEnforced by
Rule (AGENTS.md, Workspace rules (S54))constraints and preferenceson every taskthe agent; the Node for every rule about safety
Skillthe procedure for one kind of taskwhen that task comes upnothing: it guides
Operation or toolone typed action with its schema, risk and authorizationwhen calledthe Node
Agent (S49)who does the work: harness, model, instruction, limits and the Skills it may useat launchthe Node
Routine (S50)when work runs and in what order: a trigger and steps, each naming an Agent and Skillson its triggerthe Node
  • A Skill grants nothing. It cannot add a tool, widen a grant, choose a Connection, raise a budget or confirm a mutation. What must hold is enforced by the Node, because agents skip rules written only in prompts.
  • A Skill never runs. Maia never executes a Skill's files. The agent reads the procedure and calls typed tools, each under its own policy.
  • Skill text is untrusted procedure text (instruction sources). It guides an agent and never becomes configuration or authority.

Writing a Skill

A Skill is a folder <skill-id>/ holding SKILL.md, in the common format the supported harnesses read: front matter with name (kebab-case, equal to the folder name) and description, then the body, plus optional references one level deep (portable formats).

The body follows the shape of an SOP:

  1. When to use, and when not to.
  2. Inputs the agent needs before it starts.
  3. Steps, numbered, with exact commands or tool calls for fragile sequences.
  4. Checks that prove each step and the whole task.
  5. Escalation: when to stop and ask a person, and whom.
  6. Report: what to return, in what shape.

Rules:

  • The description is the trigger: third person, what and when, at most 1,024 characters.
  • One kind of task per Skill, named verb-noun (release-prepare, pr-review).
  • At least three evaluation scenarios, written before the Skill (S22).
  • Maia's own Skill bundles carry a registry-lock.json (maia.skill/v1) listing every command they claim. The bundle check (scripts/quality/hps0-skill-bundle-contract.mjs) fails on a claim the registry does not have.

Limits apply at four layers, each on its own:

LayerLimitOwner
Authoringdescription at most 1,024 characters; SKILL.md under 500 lines; references one level deepthis page
Packageat most 32 files, 256 KiB per bundle and 64 KiB per Skill filethe bundle check
Activationone loaded body warns at 6 KiB and fails at 12 KiB; all loaded bodies 12 and 24 KiBinitial budgets
Bootstrapthe maia-worker Skill at most 2 KiB, injected whole at launch: the one Skill that does not load progressively, because a worker needs it before its first turnworker Skill at launch

Where Skills live

ScopeLocationPinned byStatus
Built-inshipped with Maia: plugins/maia/worker-skills/maia-worker, plugins/maia/skills/maia-orchestrationthe release's package digestSource candidate
Projectwhere the skills CLI installs them (.agents/skills/<id>, .claude/skills/<id>), with skills-lock.jsonthe lock's folder hashPlanned (S13)
Machineeach harness's global folder, with the CLI's global lockthe global lockPlanned (S13)
Extensioninside the extensionthe extension's digest (S73)Planned
LearnedNode-generated resources (R4)their version recordPlanned
  • Qualified identities, no shadowing. Each admitted Skill has one qualified identity (builtin:<id>, user:<id>, project:<project-id>/<id>), resolved in the fixed order of resolution and admission. A Project names a user Skill explicitly, a duplicate identity is an error, and a Project Skill cannot redefine a built-in or user one. maia- names are reserved for built-ins.
  • Discovery is not admission. A Skill found on disk is a candidate. Project and machine Skills load only from a lock entry whose folder hash matches; built-in, extension and learned Skills load under the pin the table above names. Admission records each one in the Project's admitted snapshot. An unpinned Skill stays a candidate until the CLI adds it to the lock (config.import); this replaces D-040's trusted-Project fallback (D-170).
  • Two built-ins share the name maia-orchestration today: the plugin Skill for vendor workers and the CLI guidance Skill (apps/cli/guidance/maia-orchestration) that voice pins for local-v1 Runs. S22 renames the guidance Skill and updates its digest pin, descriptor references and tests together.
  • Until R11 AG1 moves it to the lock, local maia agent keeps reading its pins from .maia/maia.json (agent.resources.skills).

Install, pin and update with the skills CLI

Maia has no Skill installer, lock or update checker of its own (D-040, D-170). It runs the skills CLI (vercel-labs/skills) at an exact pinned version, with telemetry off and copies only. The Node carries that version as an exact-pinned runtime dependency and runs it with its own runtime (D-193); the commands below show the arguments:

DISABLE_TELEMETRY=1 DO_NOT_TRACK=1 \
  skills add <source> --skill <name> -a <agent>... --copy -y
  • One pin. The CLI writes skills-lock.json at the Project root: each Skill's source, ref, path in the source and a SHA-256 of its folder. The file has no timestamps and sorted entries, so branches merge cleanly, and it is committed with the Skill folders. It is the Project's only Skill pin. Machine Skills use the CLI's global lock (~/.agents/.skill-lock.json, or $XDG_STATE_HOME/skills/.skill-lock.json).
  • Every harness from one source. The CLI copies each Skill to where each harness reads it: .claude/skills for Claude Code, .agents/skills for Codex, Pi, Cursor and most others. config.apply passes -a for exactly the harnesses the Project's Agents use on that Node.
  • Structured reads only. Maia reads skills list --json and the lock files, and recomputes folder hashes with the CLI's algorithm. It never parses the CLI's text output. A test pins the lock formats and the hash against the pinned CLI version.
  • Detection reads the same list. maia agents detect reports Skills folders from skills list --json and nothing else, so a folder with no installed Skill is absent (D-190). Detection does not use npx: a Project could plant the binary it runs. The Node resolves the package from its own install, checks the exact version and that the entry file sits inside the package, and runs it with its own runtime under the resource manager (Linux hard containment; macOS and Windows report the scope unsupported). The manager rechecks the package files before every start. Nothing is downloaded at run time.
  • The pin moves by review. The CLI version moves only through a reviewed change to a release that meets the minimum dependency age (release). The recorded pin is 1.7.0.

Is every Skill up to date?

maia skills status answers for each Project, Node and harness. Each Skill has one state:

StateMeansNext step
currentthe installed copy matches the lock, and the last check found nothing newernone
outdatedthe source has a newer version than the lockmaia skills update
modifiedthe installed copy differs from the lock: someone edited it in placereinstall it, or keep the edit as a reviewed change
missingin the lock, but absent for a harness that should have itmaia config apply
unpinnedinstalled, but not in the lockadd it with the CLI, or remove it
uncheckedthe source cannot be checked (a local path, a private or deleted repository, no network); the reason is shownnone

Each state carries the time of the last check. Status also lists the Sessions still running an older digest: a Session keeps the Skills resolved at its launch, and its next launch takes the new ones.

  • Check. maia skills check runs the CLI's update in a scratch copy (a scratch worktree for Project Skills, a scratch state directory for machine Skills) and compares the scratch lock with the real one. Each changed hash is outdated, and a Skill gone from its source is reported. Nothing outside the scratch copy changes. It needs the network, so it never runs at launch; a Routine (S50) can run it on a schedule.
  • Update. maia skills update [<name>...] previews first: the Skills that change, old and new digests, a summary of each change, and the Agents and Routines that use them. After a person confirms, it runs the CLI's update in a worktree of the Project, checks that the new hashes equal the previewed ones (else it fails with a conflict and asks for a new preview), and leaves the change (the lock and the Skill folders) for review through the Project's normal flow, with a receipt. Machine Skills update in place after confirmation. Running Sessions are never changed.

How each harness gets its Skills

HarnessRouteStatus
Codex workerthe worktree's .agents/skills; Codex workers launch with Codex's own Skills list off (D-105), so the maia-worker body arrives as developer instructions, and a resumed thread keeps its first turn'smaia-worker: Source candidate. Project Skills: Planned (FV4), route to qualify
Claude Code workerthe worker profile reads no Skills folder (D-087), so the Node passes a launch plugin, one folder per set of digestsmaia-worker: Source candidate. Project Skills: Planned (FV4)
Pi and Maia agentthe typed Skill loader: a metadata index, loads by exact ID, budgets and a context manifest; the managed worker's restricted projection has no Skills and refuses /skill: todaylocal pins: Source candidate. Loader: Planned (R11)
The user's own harnessthe maia plugin: maia-orchestration and maia mcpSource candidate

A Session gets exactly the Skills it is eligible for, pinned by digest at launch: those its Agent names (S49), plus those a Routine step names (S50). Without an Agent, a coding Session gets only the built-in maia-worker Skill; .maia/worktree.json with "workerSkills": false turns that off for a Project.

Using a Skill

  • By the agent. The agent sees each eligible Skill's name and description and loads a body when one fits the task. Picking a Skill never grants eligibility.
  • By a person. In maia agent, /skills lists eligible Skills and /skill load <skill-ref> loads one (Planned, R11). A vendor harness keeps its own command for a Skill.
  • By a Routine. A step names its Agent and instruction and may request Skills (requestedSkillRefs), which only narrow what its Agent may use. Each tick resolves them against the snapshot that planned it, so a run uses fixed versions and records their digests; a requested Skill that is missing or not eligible blocks the tick with its reason. An unattended run follows the same procedure a person would.

Tracing Skill use

  • session show lists what the latest coding launch injected as { name, digest } (worktree.skills, at most 8, Source candidate). It is a projection of that launch, replaced at the next one, not a history.
  • Injected is not effective: a resumed Codex thread keeps its first turn's developer instructions. The trace (S12t, D-168) records the Skills each launch staged, and the selected, loaded and effective digests where the harness reports them; where it cannot, the trace says so.
  • Each activation's context manifest records every Skill selected and loaded, with its digest and size, and a context.skill-selected event (Planned, R11).
  • In a vendor harness, a Skill shows up as that harness's tool call where it reports one (Claude Code's Skill tool), kept as trace metadata (D-168).
  • S22's evaluation scenarios and S62's evals measure a Skill's outcomes; Runs record wall time, tokens, retries and escalations.

Improving a Skill

  • A Skill changes like code: a change in a worktree, its evaluation scenarios run, a person reviews and merges, and the lock records the new hash. No Skill changes under running agents.
  • An evaluation or a coordinator may propose a change to a Skill. It arrives as a change for review, never applied directly.
  • Learned Skills (R4) stay in their own eligibility class. Exporting one into the Project's Skills is an explicit, reviewed change (coordinator learning).

Skill tools at a glance

The plural skills.* operations manage installed Skills on a Node; the singular skill.* tools act inside one agent activation, as agents and agent do (D-120).

SurfaceForDoesStatus
maia skills status, check, update (skills.status, skills.check, skills.update.preview, .confirm)people and coordinators; a person confirms updatesinventory and state, upstream check, reviewed updatePlanned (S13, D-170)
maia config plan, apply, drift, importpeopleinstall pinned Skills for each harness on a Node; report drift; adopt an unpinned Skill through the CLIPlanned (S13)
session show (worktree.skills); .maia/worktree.json workerSkillsanyone who may read the Sessionwhat a launch injected; the per-Project opt-outSource candidate
maia agent --skill <path>a personload a Skill for a local runPlanned (R11 AG1)
/skills, /skill loada person in maia agentlist eligible Skills; load onePlanned (R11)
list_skills, maia__skill, show_skill_status (operations skill.list, skill.load, skill.status, D-172)the Maia agenteligible metadata; load a body; eligibility and digestPlanned (R11 AG2–AG3)
maia context inspect, lintpeoplewhat loaded; duplicates, oversize and undiscoverable SkillsPlanned (R11)
Agent Skill references; Routine step Skillspeople, through preview and confirmationeligibilityPlanned (S49, S50, FV4)
maia.agent-definition/v1 skillRefsthe managed worker's definitionsup to 32 references; the one shipped definition has none, and activation does not apply themSource candidate schema
Voice orchestrator promptvoicepins the CLI guidance Skill by digest and injects a restricted projection of itSource candidate
Skill views in clientspeoplecatalog, state and usePlanned (T3)

Imported from Maia OS docs at 3dc3e07