Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/modiqo/skillspec/llms.txt

Use this file to discover all available pages before exploring further.

The grammar is the normative description of every construct in skill.spec.yml. YAML is the interchange format; the grammar describes the conceptual tree independent of YAML spelling. v0 is deliberately not a programming language — it is a structured skill contract that expresses routes, rules, elicitations, states, commands, imports, resources, code, artifacts, recipes, snippets, closures, tests, and proof hooks without becoming an execution engine.

Document Structure

Every skill.spec.yml follows the top-level skillspec production:
skillspec       = header ,
                  [ activation ] ,
                  [ applies-when ] ,
                  [ entry ] ,
                  [ routes ] ,
                  [ rules ] ,
                  [ elicitations ] ,
                  [ trace ] ,
                  [ dependencies ] ,
                  [ imports ] ,
                  [ resources ] ,
                  [ code ] ,
                  [ artifacts ] ,
                  [ recipes ] ,
                  [ states ] ,
                  [ commands ] ,
                  [ snippets ] ,
                  [ closures ] ,
                  [ proof ] ,
                  [ tests ] ,
                  [ review-required ] ,
                  [ metadata ] ;
The header is the only mandatory section. Every valid spec must include all four fields.
header      = schema , id , title , description ;
schema      = "schema" ":" "skillspec/v0" ;
id          = "id" ":" identifier ;
title       = "title" ":" string ;
description = "description" ":" string ;
activation provides hints a harness uses to decide whether to load the skill before reading the full spec. It does not execute routing.
Routes are named strategies. Lower rank means earlier default preference unless a rule overrides it.
Rules match task signals and adjust route, forbids, elicitations, and post-success actions. Rules are evaluated in file order.
Elicitations ask a specific bounded question instead of an open-ended one. Choices may set facts, steer a route, or advance to a state.
trace declares which decision events should be persisted by an evaluator or harness.
Declare required tools, runtime-loadable guidance, provenance material, executable knowledge, data products, and structured procedures respectively.
States are named lifecycle positions. Commands are instruction templates. Snippets are user-facing prose. Closures describe post-task behavior.
proof.metrics names the measures the policy is improving. tests are scenario contracts. review_required lists items that need human review. metadata is an open mapping.

Identifiers

All named constructs in a spec use the identifier production:
identifier      = lowercase-letter , { lowercase-letter | digit | "_" | "-" | "." } ;
Valid examples: browser, local_cli, check-auth, task.router Identifiers are stable API. They are what tests, compilers, and importing tools refer to. Human labels (like route.label or rule.reason) can change freely; identifiers should not churn because renaming one breaks every test, import, and cross-reference that names it.
Identifiers must start with a lowercase letter. Digits, underscores, hyphens, and dots are allowed after the first character. Uppercase, spaces, and other punctuation are not valid.
The header section is mandatory. A spec is invalid without all four fields:
schema: skillspec/v0
id: my.skill
title: My Skill
description: A one-line description of what this skill does.
FieldRequiredTypeNotes
schema"skillspec/v0"Literal constant. No other value is valid in v0.
ididentifierStable name for this skill. Used in imports, cross-references, and trace events.
titlestringShort human name. May change without breaking references.
descriptionstringOne-line summary. Compiler targets may use it as frontmatter.

Activation

activation and applies_when are harness-selection hints. A harness may use them to decide whether to load the skill, but they are not part of route decision logic.
activation          = "activation" ":" mapping ;
activation.summary  = "summary" ":" string ;
activation.keywords = "keywords" ":" sequence-of string ;
activation.priority = "priority" ":" string ;
applies-when        = "applies_when" ":" sequence-of activation-hint ;
activation-hint     = mapping ;
activation:
  summary: Universal durable-work router with trace and alignment benefits.
  keywords:
    - remember this workflow
    - route through durable executor
applies_when:
  - user_intent:
      - recurring task
      - browser and CLI work
activation.summary should be placed at the start of generated frontmatter descriptions so a harness can choose the skill before loading the full spec. activation.keywords widens the selection surface without changing route decision. activation.priority is advisory metadata for humans and harnesses.

Routes

Routes are candidate ways to satisfy work. They do not execute anything by themselves.
routes  = "routes" ":" sequence-of route ;
route   = "id" ":" route-id ,
          "label" ":" string ,
          [ "rank" ":" number ] ,
          [ "description" ":" string ] ,
          [ "checks" ":" sequence-of command-id ] ,
          [ tool-boundary ] ;
FieldRequiredNotes
idStable identifier. Referenced by rules, tests, and elicitation choices.
labelHuman-readable name. Shown in reports and generated skill docs.
rankInteger. Lower = earlier default preference. Rules can override.
checksList of command ids to run as readiness checks before this route is activated.
tool_boundaryPhase-scoped permission contract. Inherited entry → route → phase.

Rules

Rules are the steering layer. They are evaluated in file order; effects are additive except prefer (which replaces the selected route) and route_order (which replaces the current order).
rule  = "id" ":" rule-id ,
        [ "when" ":" predicate ] ,
        [ "prefer" ":" route-id ] ,
        [ "route_order" ":" sequence-of route-id ] ,
        [ "forbid" ":" sequence-of identifier ] ,
        [ "allow" ":" mapping ] ,
        [ "elicit" ":" sequence-of elicitation-id ] ,
        [ "after_success" ":" sequence-of command-id-or-closure-id ] ,
        [ "reason" ":" string ] ;
Predicate fields (all compose with logical AND; values within user_says_any compose with logical OR):
FieldTypeMeaning
user_says_anylist of stringsMatches when any listed phrase appears in the input
task_recurrence_likelybooleanTask is likely to recur
domain_object_taskbooleanTask involves a structured domain object
interactive_prompt_likelybooleanTask will likely present interactive prompts
command_likely_long_runningbooleanThe primary command will run for a long time
Rule effect algebra — for each matching rule:
apply(rule) = if rule.prefer      → route := rule.prefer
              if rule.route_order → route-order := rule.route_order
              forbid-set          := forbid-set ∪ rule.forbid
              allow-map           := allow-map merge rule.allow
              elicitation-list    := append elicitation-list rule.elicit
              after-success-list  := append after-success-list rule.after_success
              matched-rule-list   := append matched-rule-list rule.id
              reason              := rule.reason or reason
Every route-changing, forbid-heavy, or elicitation-producing rule should have at least one scenario test. A rule without a test is only structured prose.

Elicitations

Elicitations are bounded questions — used when the skill should ask for a specific missing decision rather than guessing or asking an open-ended question.
elicitation  = "question" ":" string ,
               [ "required_when" ":" sequence-of elicitation-condition ] ,
               "choices" ":" sequence-of elicitation-choice ,
               [ "default" ":" choice-id ] ,
               [ "max_choices" ":" number ] ;

elicitation-choice
             = "id" ":" choice-id ,
               "label" ":" string ,
               [ "description" ":" string ] ,
               [ "sets" ":" mapping ] ,
               [ "route" ":" route-id ] ,
               [ "next" ":" state-id ] ,
               [ "safety" ":" safety-class ] ;
Choices may set facts (sets), steer a route (route), or advance to a state (next). They do not execute commands by themselves. required_when conditions fire when a specific route is selected, a fact is missing, or a predicate matches. default must reference one of the declared choice ids.
When authoring YAML by hand, quote question strings that contain : or use a block scalar (|). An unquoted string like question: What are we reviewing: a dependency list? will be parsed as a broken mapping before SkillSpec validation runs.

Trace

trace declares which decision events should be persisted by an evaluator or harness. The spec describes the contract; the evaluator writes the events.
trace       = "trace" ":" mapping ;
trace.mode  = "mode" ":" "event_log" ;
trace.required = [ "required" ":" boolean ] ;
trace.record   = [ "record" ":" sequence-of trace-event-kind ] ;
Only one mode exists in v0: event_log. If record is empty or absent, a conforming evaluator may record every v0 event kind.
Event kindMeaning
input_receivedThe evaluator received the user input
spec_loadedThe evaluator loaded a specific SkillSpec
rule_evaluatedA rule was checked (matched or not)
rule_matchedA rule matched and its effects are about to apply
route_selectedA route was selected or replaced
route_order_setA rule replaced the route order
forbid_addedA rule added forbidden substitutions
allow_addedA rule added narrow allowed fallbacks
elicitation_requestedA rule required a bounded user choice
after_success_scheduledA rule scheduled a post-success action
outcome_recordedThe evaluator recorded the final decision outcome
If required is true, a conforming harness should either write the trace or state that tracing is unavailable before relying on the decision.

Tests

Tests are scenario contracts. Every meaningful route rule should have at least one scenario.
scenario-test = "name" ":" string ,
                "input" ":" string ,
                "expect" ":" expectation ;
An expectation must contain at least one assertion. The three assertion families are:
FamilySemantics
Plain list (e.g. route, forbid, elicit, matched_rules)Assert inclusion — the listed items must appear in the result
*_exact (e.g. forbid_exact, elicit_exact, matched_rules_exact)Assert the exact set — no more, no fewer
not_* (e.g. not_forbid, not_elicit, not_matched_rules)Assert absence — the listed items must not appear
tests:
  - name: browse task uses browser
    input: browse https://example.com and take a snapshot
    expect:
      route: browser
      forbid_exact:
        - native_search_as_answer
      elicit_exact:
        - target_url
      matched_rules_exact:
        - browser_tasks_use_browser

Proof

proof.metrics names the measures the policy is trying to improve:
proof         = "proof" ":" mapping ;
proof.metrics = "metrics" ":" sequence-of metric-id ;
proof:
  metrics:
    - steering_accuracy
    - token_reduction
    - failed_branches_avoided
    - remembered_route_savings
Proof metrics are identifiers, not computed values. They give harnesses, CI pipelines, and reviewers a stable vocabulary for what the spec is optimizing.

Validation

skillspec validate <path> performs structural and cross-reference checks on a spec. The key rules enforced:
  • Every Rule.prefer references an existing Route.id
  • Every Rule.elicit item references an existing elicitation
  • Every Elicitation.default references one of its choices
  • Every Test.expect.route references an existing Route.id
  • Every Command.requires.dependencies item references an existing dependency
  • The import dependency graph is acyclic
  • Every on-demand import is connected to the runtime graph
  • Every scenario test declares at least one concrete expectation
Typed v0 objects are strict: unknown fields are invalid. A misspelled field name like prefr: browser or forbit: [native_search] will cause a validation error rather than silently disappearing. This strictness is intentional — behavior that is misspelled is behavior that does not execute.

Minimal Valid Spec

The following is the smallest valid skill.spec.yml, taken from the conformance suite:
schema: skillspec/v0
id: conformance.minimal
title: minimal conformance spec
description: Small valid SkillSpec fixture for CLI conformance checks.

routes:
  - id: local
    label: Local

rules:
  - id: local_request
    when:
      user_says_any:
        - local
    prefer: local

tests:
  - name: local request selects local
    input: run this local task
    expect:
      route: local
      matched_rules_exact:
        - local_request
This spec defines one route, one rule that selects it, and one scenario test that proves the rule fires. Everything else — activation, trace, commands, dependencies, imports — is optional.

Build docs developers (and LLMs) love