Sigil
Semantic document format for LLM-native context
- AI Research
- Language Design
- Open Source
Where it started
Sigil came out of a problem I kept hitting while building multi-stage document-processing pipelines: context degraded every time information moved between models. A warning became indistinguishable from a suggestion. A procedural step looked like a fact. The words survived, but their meaning did not.
We were passing a lot of Markdown around because it was convenient and every model already understood it. But Markdown mostly describes presentation. A human can infer that bold text is important or that a paragraph beneath a heading is rationale; a parser only sees decorated text. Once that text is split for retrieval or handed to another model, those relationships become even easier to lose.
The idea
My core bet was simple: in machine-primary documents, meaning should be part of the syntax. Sigil gives every block an explicit type from a small, fixed vocabulary. A ! warn is always a warning, a * fact is always an asserted truth, and a ^ context block always explains its parent.
Always wait for networkidle before
inspecting the DOM.
This matters because JavaScript may
still be loading.! warn: always wait for networkidle
before inspecting the DOM
^ context: JavaScript may still be
loadingI don’t see Sigil as a replacement for Markdown. Markdown is still better when the reader is primarily a person. Sigil is for the awkward layer between models, agents, retrieval systems, and people—the places where content needs to stay readable but also carry enough structure to be dependable.
Designing the format
I wanted the language to remain easy to inspect in a text editor, so I resisted turning it into verbose JSON or XML. The markers are compact, nesting is controlled by indentation, and there are no closing tags. The format looks lightweight, but the choices underneath it are intentionally restrictive.
- Closed vocabulary
- Models get a finite set of valid concepts instead of inventing new labels.
- Two-space indentation
- Scope stays obvious to a person and deterministic to a parser.
- Context as a child block
- A rule and its rationale remain connected when a document is chunked.
- Strict and lenient modes
- Authored files can be exact; generated files can still be recovered.
The closed vocabulary matters most. Open-ended labels feel flexible, but they drift quickly when models generate them. A fixed set gives the parser predictable input and gives a model a bounded decision: is this a fact, warning, step, example, uncertainty, or something else the specification already understands?
Building the implementation
I treated the specification as the product and the TypeScript package as its reference implementation. That changed the order in which I built things:
- Define the document header, block vocabulary, nesting rules, annotations, and typed references in the specification.
- Encode the grammar with Peggy, then produce a typed AST rather than a loose object tree.
- Add validation, serialization, and Markdown conversion around the parser.
- Write conformance fixtures so another implementation can prove it reads the same valid and invalid documents.
The parser has two modes because generated text is never perfectly clean. Strict mode stops on a specification violation and is useful for authoring or CI. Lenient mode returns the best document it can plus line-level warnings. In an agent pipeline, recovering most of a generated document is often more useful than rejecting all of it.
A Sigil document
This is a shortened skill file. The header can be queried before loading the body, the trigger and skip rules are explicit, and the reason for the warning stays attached to it.
%% skill
name: webapp-testing
version: 1.0.0
@ trigger: user asks to test a web application
@ skip: user is testing a CLI tool
# Setup
! warn: wait for networkidle before inspecting the DOM
^ context: JavaScript may still be loading
$ step: start the development server
$ step: navigate to the application
$ step: run assertionsThe npm package exposes the parser, validator, serializer, converters, and a small CLI. It can turn a .sgl file into JSON, validate it against the spec, round-trip it back to Sigil, or convert it to and from Markdown.
Where it fits
- Agent skills: triggers, exclusions, steps, and constraints have explicit types.
- RAG pipelines: retrieved chunks retain whether they are facts, warnings, examples, or uncertain claims.
- Agent memory: facts can carry confidence, provenance, and temporal annotations.
- LLM-to-LLM handoffs: downstream models receive structured meaning without giving up human readability.
Current status
Sigil is open source and still deliberately early. The language specification is an active 0.1.0 draft, and the sigil-lang reference package is currently at 0.3.2. I’m keeping the vocabulary conservative while real usage exposes weak spots; I would rather make a small semantic system dependable than grow it before the core ideas hold up.
The next direction I’m interested in is querying: asking a document for every high-confidence fact, every critical warning, or every step activated by a particular trigger. At that point, the document stops being a flat text file and starts behaving like a compact knowledge layer.