Block reference
Every block type, its properties and their allowed values. The tables are generated from the osf validator, so they match what osf lint checks.
Syntax: @name { property: value; … }. Values are strings ("…"), numbers, booleans, bare identifiers and dates (corporate, 2026-06-15), arrays ([a, b]), objects ({ k: v; }) and references (@ref("id")). In @doc, @slide and semantic blocks, lines that are not properties are Markdown. Comments are // and /* */. Compose files with @include { path: "./part.osf"; }.
Jump to: @meta · @doc · @slide · @sheet · @table · @chart · @diagram · @code · @finding · @decision · @requirement · @action · @hypothesis · @data_source · @agent_card · @task · @artifact
Structural blocks
The content people read. Any block may have an id; sheets, tables and charts can be filled from a data source.
@meta
| Property | Type | Required | Meaning |
|---|---|---|---|
title | text | Document title | |
author | text | Author | |
date | date | Document date | |
theme | text | Theme name | |
version | text | Document version | |
language | text | BCP 47 language tag | |
osf | text | OSF version the document targets, e.g. "2.0" | |
license | text | SPDX license expression | |
tags | array of text | Free-form tags | |
schemas | array of text | JSON Schemas for extension blocks |
Every block may also carry id. Other properties are kept and passed through; osf lint warns about them.
@doc
| Property | Type | Required | Meaning |
|---|---|---|---|
tags | array of text | Free-form tags | |
class | text | Style class | |
lang | text | Language of this block |
Every block may also carry id.
@slide
| Property | Type | Required | Meaning |
|---|---|---|---|
title | text | Slide title | |
layout | text | Layout, e.g. TitleAndContent | |
notes | text | Speaker notes |
Every block may also carry id. Other properties are kept and passed through; osf lint warns about them.
@sheet
| Property | Type | Required | Meaning |
|---|---|---|---|
name | text | Sheet name | |
cols | array | Column headers | |
formats | object | Number formats: { "B:D": "#,##0.00"; "E7": "0.0%"; } | |
source | @ref | Fill from a @data_source |
Every block may also carry id. Other properties are kept and passed through; osf lint warns about them.
@sheet {
id: "budget";
name: "Budget";
A1 = "Item"; B1 = "Q1"; C1 = "Q2"; D1 = "Total";
A2 = "Grants"; B2 = 120; C2 = 135; D2 = =SUM(B2:C2);
}@table
| Property | Type | Required | Meaning |
|---|---|---|---|
caption | text | Caption | |
style | bordered | striped | minimal | bordered, striped or minimal | |
alignment | array of left | center | right | Per-column alignment | |
source | @ref | Fill from a @data_source | |
sort | any | Column to sort by |
Every block may also carry id. Other properties are kept and passed through; osf lint warns about them.
@table {
id: "regions";
caption: "Active programmes by region";
style: striped;
alignment: [left, right];
| Programme | Budget (M€) |
|---|---|
| Horizon Clean Energy | 1200 |
}@chart
| Property | Type | Required | Meaning |
|---|---|---|---|
type | bar | line | pie | scatter | area | Chart type | |
title | text | Chart title | |
data | array or object | Series: [{ label: "..."; values: [1, 2]; }], or { labels: [...]; datasets: [...]; } | |
options | object | xAxis, yAxis, legend, colors | |
source | @ref | Fill from a @data_source |
Every block may also carry id. Other properties are kept and passed through; osf lint warns about them.
@chart {
id: "chart-funding";
type: bar;
title: "Funding by quarter";
labels: ["Q1", "Q2", "Q3", "Q4"];
data: [
{ label: "2025"; values: [80, 92, 88, 101]; },
{ label: "2026"; values: [95, 104, 110, 121]; }
];
}@diagram
| Property | Type | Required | Meaning |
|---|---|---|---|
type | flowchart | sequence | gantt | mindmap | graph | class | state | Diagram type | |
engine | mermaid | graphviz | dot | mermaid or dot | |
code | text | Diagram source | |
title | text | Diagram title |
Every block may also carry id. Other properties are kept and passed through; osf lint warns about them.
@diagram {
engine: dot;
title: "Approval flow";
code: "digraph { rankdir=LR; Draft -> Review -> Approved; }";
}@code
| Property | Type | Required | Meaning |
|---|---|---|---|
language | text | Language for highlighting | |
code | text | The code | |
caption | text | Caption | |
lineNumbers | true/false | Show line numbers | |
highlight | array of numbers | Lines to highlight |
Every block may also carry id. Other properties are kept and passed through; osf lint warns about them.
Semantic blocks
Typed knowledge. Each needs an id. Enumerated values are closed: anything else is a lint error. A Markdown body is allowed.
@findingneeds id
| Property | Type | Required | Meaning |
|---|---|---|---|
claim | text | yes | One-sentence claim |
confidence | number 0..1 | Confidence 0..1 | |
evidence | @ref or [@ref, ...] | Supporting blocks | |
status | proposed | confirmed | retracted | proposed, confirmed or retracted | |
tags | array of text | Free-form tags | |
source | text or @ref | Where this came from | |
created | date | Creation date | |
updated | date | Last update |
Every block may also carry id.
@finding {
id: "F-001";
claim: "Nordic countries allocate 3.2x more per capita to clean-energy R&D.";
confidence: 0.91;
status: confirmed;
evidence: [@ref("regions")];
tags: ["nordic"];
The ratio holds for 2024 and 2025; 2026 data is partial.
}@decisionneeds id
| Property | Type | Required | Meaning |
|---|---|---|---|
question | text | yes | The question being decided |
options | array | yes | Options: strings or { label; rationale; } |
criteria | @ref or [@ref, ...] | Blocks that inform the decision | |
status | pending | decided | superseded | pending, decided or superseded | |
outcome | text | Chosen option label | |
decided_by | text | Who decided | |
deadline | date | Decide by | |
decided_on | date | Date decided | |
tags | array of text | Free-form tags | |
source | text or @ref | Where this came from | |
created | date | Creation date | |
updated | date | Last update |
Every block may also carry id.
@decision {
id: "D-001";
question: "Prioritise Horizon Europe or national programmes?";
options: ["Horizon Europe", "National mix", "Hybrid"];
criteria: [@ref("F-001")];
status: decided;
outcome: "Hybrid";
decided_on: 2026-11-02;
}@requirementneeds id
| Property | Type | Required | Meaning |
|---|---|---|---|
level | must | should | could | wont | yes | must, should, could or wont |
statement | text | yes | The requirement |
rationale | text | Why | |
verify | text | How it is tested | |
status | draft | approved | implemented | verified | dropped | Lifecycle status | |
depends_on | @ref or [@ref, ...] | Other requirements | |
tags | array of text | Free-form tags | |
source | text or @ref | Where this came from | |
created | date | Creation date | |
updated | date | Last update |
Every block may also carry id.
@requirement {
id: "R-1";
level: must;
statement: "Exports work without network access.";
verify: "Run osf render with networking disabled.";
}@actionneeds id
| Property | Type | Required | Meaning |
|---|---|---|---|
title | text | yes | What to do |
assignee | text | Person or agent | |
due | date | Due date | |
status | todo | doing | blocked | done | cancelled | todo, doing, blocked, done or cancelled | |
depends_on | @ref or [@ref, ...] | Actions or decisions | |
produces | @ref or [@ref, ...] | Artifacts | |
tags | array of text | Free-form tags | |
source | text or @ref | Where this came from | |
created | date | Creation date | |
updated | date | Last update |
Every block may also carry id.
@action {
id: "A-1";
title: "Draft the Q1 rollout plan";
assignee: "Ops";
due: 2026-12-15;
depends_on: @ref("D-001");
}@hypothesisneeds id
| Property | Type | Required | Meaning |
|---|---|---|---|
statement | text | yes | Testable statement |
confidence | number 0..1 | Confidence 0..1 | |
supports | @ref or [@ref, ...] | Evidence for | |
contradicts | @ref or [@ref, ...] | Evidence against | |
test | text | How to falsify | |
status | open | supported | refuted | open, supported or refuted | |
tags | array of text | Free-form tags | |
source | text or @ref | Where this came from | |
created | date | Creation date | |
updated | date | Last update |
Every block may also carry id.
Agent blocks
They connect a document to MCP tools and A2A agents.
@data_sourceneeds id
| Property | Type | Required | Meaning |
|---|---|---|---|
mcp | text or object | yes | MCP server name or { url; auth; } |
tool | text | yes | MCP tool name |
arguments | object | Tool arguments | |
refresh | text | manual, on-render or a duration such as "1h" or "daily" | |
shape | rows | object | text | rows, object or text | |
cache | text | Cache file path |
Every block may also carry id.
@data_source {
id: "funding-live";
mcp: "funding-db";
tool: "search_programmes";
arguments: { query: "energy transition"; };
refresh: "daily";
}
@table { id: "live"; source: @ref("funding-live"); caption: "Live programmes"; }@agent_card
| Property | Type | Required | Meaning |
|---|---|---|---|
name | text | yes | Agent name |
description | text | yes | What the agent does |
url | text | yes | Where the agent is served |
version | text | Agent version | |
skills | array | yes | Skills: [{ id; name; description; }] |
security | array | A2A security schemes | |
capabilities | object | streaming, pushNotifications | |
provider | object | { organization; url; } |
Every block may also carry id.
@agent_card {
name: "Funding report";
description: "Queryable report with live programme data";
url: "http://127.0.0.1:8090";
skills: [
{ id: "osf.query"; name: "Query"; description: "Selectors over the report"; },
{ id: "osf.resolve_decision"; name: "Decide"; description: "Record an outcome"; }
];
security: [{ type: "bearer"; }];
}@taskneeds id
| Property | Type | Required | Meaning |
|---|---|---|---|
skill | text | yes | Skill id |
input | object | Skill input | |
state | submitted | working | input-required | completed | canceled | failed | rejected | auth-required | A2A task state | |
assignee | text | Agent name or URL | |
produces | @ref or [@ref, ...] | Artifacts | |
history | array | State history |
Every block may also carry id.
@artifactneeds id
| Property | Type | Required | Meaning |
|---|---|---|---|
task | @ref | Producing task | |
kind | text | file | data | document | yes | text, file, data or document |
media_type | text | MIME type | |
path | text | File path for file artifacts |
Every block may also carry id.
Extension blocks
A block whose name starts with x- (@x-experiment { … }) is kept by the parser and the formatter, skipped by renderers, carried in JSON as "type": "x-experiment", and reported once by osf lint. Give extensions a JSON Schema with @meta { schemas: ["./experiment.schema.json"]; }.