K2F File Operations Guide for AI Agents
Agent entry point: Prefer the repo skill
skills/k2f/(workflows: writing, converting-markdown, exporting-pdf, embedding-viewer, publishing). Loose JSON editing is fine for authoring; the product format is a packaged.K2FZIP with embedded fonts and lock.
This guide enables AI agents to read, write, and modify K2F document files efficiently. K2F is a semantic document format that separates content (semantic meaning) from presentation (visual styling).
Quick Reference: .K2F ZIP Package
Canonical paths (see k2f-v0.1.md):
| Path | Required | Purpose |
|---|---|---|
manifest.json | yes | Package metadata (canvas_mode: "paged", page_config, optional running_blocks) |
content/root.json | yes | State A semantic tree entry |
content/**/*.json | when referenced | Subtree fragments via explicit { "include": "content/...." } stubs |
styles/theme.json | yes | Role-based appearance (single file; do not split theme) |
styles/tokens.json | no | Design tokens |
changelog.json | yes | Edit history |
document.K2F.lock | after compile | State C geometry + render plan |
schema/*.json | yes | Five format schemas only |
assets/fonts/* | yes | Embedded fonts |
assets/images/* / assets/data/* | no | Images / table data |
CLI workflow:
k2f pack <source_dir> -o doc.K2F
k2f compile doc.K2F
k2f verify doc.K2F
k2f export-pdf doc.K2F -o doc.pdf
Agent writing dialect (narrower than the format): engine/k2f_sdk/profiles/agent_v0.schema.json — not embedded in the package.
Loose JSON during authoring
While editing, you may work with unpacked files:
content/root.json— Semantic content tree with hierarchical IDs (may{ "include": "content/...." }subtrees)content/*.json— Optional referenced fragments (oneSemanticNodeper file; must be referenced from root)styles/theme.json— Visual styling (roles, variants, primitives, palette)manifest.json— Document metadata and page configuration (norootfield)
Unreferenced files under content/ cause UNEXPECTED_PATH at pack time. Do not glob or auto-load all JSON in content/.
The final deliverable must be a packed .K2F.
Core Concepts (95% of Tasks)
1. Reading Content
K2F content is a tree of semantic nodes. Each node has:
id: Hierarchical identifier (e.g.,"root.section1.heading")role: Semantic role (e.g.,"h1","body","card","code_block","math")variant: Optional visual variant (e.g.,"glass","warning")content: Node content (text,image,container,table,table_reference,code_block,math)modifiers: Array of text modifiers. Struct:{"type": "<closed enum>", "intent": "str", "range": [start, end]}.layout: Optional layout hint (stack,grid,overlay,columns)- Optional:
break_inside,keep_with_next,column_span, list fields (list_id,depth,marker_type)
Example:
{
"id": "root",
"role": "body",
"content": {
"type": "text",
"value": "Hello World"
},
"modifiers": []
}
To read a node by ID path:
- Navigate the tree using dot-separated IDs:
root.section1.heading - For containers, traverse
content.value.childrenarray
2. Writing/Updating Content
Updating text content:
{
"id": "root",
"role": "body",
"content": {
"type": "text",
"value": "Updated text"
}
}
Adding a new node:
- Add to parent's
content.value.childrenarray - Assign unique hierarchical ID:
parent_id.child_name - Set required fields:
id,role,content
Updating node attributes:
- Modify any property directly (id, role, variant, layout)
- Preserve structure: keep
content.typeconsistent
3. Reading Styles
Styles are defined in theme.json under:
roles: Role → base style mappingprimitives: Named visual atoms (surfaces, gradients, corners, borders, shadows, blurs)palette: Sole color table (palette keys or#RRGGBB/#RRGGBBAA)modifiers: Modifier type → intent → style patches
Example:
{
"palette": {
"black": "#000000"
},
"roles": {
"body": {
"font_family": "default",
"font_size": 12000,
"line_height_mult": 1200,
"color": "black"
}
}
}
4. Updating Styles
Update role style:
- Modify properties in
theme.json→roles[role_name] - Top-level properties:
font_family,font_size,line_height_mult,color,text_align,letter_spacing_pt,self_align - Decoration properties (MUST be nested in
box_decoration):padding_pt,background,border,shadow,blur,corner_radius(all visual atoms are named string refs)
Add new role:
- Add entry to
rolesobject - Must include:
font_family,font_size,line_height_mult,color
Update/add variant:
- Add to
roles[role_name].variants[variant_name] - Can override
box_decorationortext_overrides
Add primitive:
- Add to
primitives.surfaces,primitives.gradients,primitives.corners,primitives.borders,primitives.shadows, orprimitives.blurs(neverprimitives.colors— colors live only inpalette)
Font aliases (important)
If using custom font names (e.g. "Roboto") in roles, you must map them to loaded font families (usually "default") in theme.json:
{
"font_aliases": {
"Roboto": "default",
"Helvetica": "default"
}
}
5. Adding New Attributes
To add a new attribute to a node:
- Check if attribute is supported in schema:
schema/nodes.schema.json - If supported, add directly to node JSON
- If not supported, you cannot add it (schema enforces structure)
Common attributes you can add:
variant: String (must exist in theme for that role)layout: Object (stack/grid/overlay/columns)break_inside,keep_with_next,column_span- Properties within
layoutobject (gap, direction, align_items, count, etc.)
Important: K2F uses strict schema validation. Only attributes defined in the schema are allowed.
Fixed-Point Units
All size values use fixed-point Pt in 1/1000 pt units:
12000= 12.0 pt595000= 595.0 pt (A4 width)- Always use integers, never decimals
Common Patterns
Pattern 1: Update Text Content
// Find node by ID path, update content.value
{
"id": "root.section1.paragraph1",
"content": {
"type": "text",
"value": "New text here"
}
}
Pattern 2: Add Child Node
// Add to parent's children array
{
"id": "root.section1.new_heading",
"role": "h2",
"content": {
"type": "text",
"value": "New Heading"
},
"modifiers": []
}
Pattern 3: Change Role/Variant
// Update role or variant to change visual appearance
{
"id": "root.card1",
"role": "card",
"variant": "glass" // Must exist in theme.roles.card.variants
}
Pattern 4: Update Style
// In theme.json
{
"roles": {
"body": {
"font_size": 14000, // Changed from 12000 to 14pt
"color": "gray" // Changed color
}
}
}
Schema Validation
Always validate against schemas:
- Content nodes:
schema/nodes.schema.json - Theme/styles:
schema/styles.schema.json - Visual primitives:
schema/visual_primitives.schema.json - Manifest:
schema/manifest.schema.json
Key constraints:
- Max 50 modifiers per node
- All Pt values must be integers (1/1000 pt units)
- Required fields must be present
rolemust exist in themevariantmust exist in theme for that role
Detailed Guides
For advanced operations, see:
- Content Operations Details - Deep dive on reading/writing content nodes
- Style Operations Details - Advanced styling, primitives, variants
- Attribute Reference - Complete attribute reference
Schema Files (Read These for Full Details)
schema/nodes.schema.json- Complete node structure and validation rulesschema/styles.schema.json- Complete theme structure and validation rulesschema/visual_primitives.schema.json- Visual primitive definitionsschema/manifest.schema.json- Manifest structureschema/signatures.schema.json- Signature recordengine/k2f_sdk/profiles/agent_v0.schema.json- Agent authoring dialect (not packed)
Architecture Reference
For understanding the K2F system architecture:
- docs/architecture/ — design, codebase map, layout engine
- layout-engine.md — compile pipeline and paint plan
Elegant Styling Principles
Use primitives: Reference named primitives ("shadow": "elevation.1", "corner_radius": "medium") — never inline fill/shadow/blur/border objects in theme box_decoration. Define reusable atoms in theme.json → primitives.
Use variants, not roles: Create visual variations via variants on existing roles. Only create new roles for semantic differences.
Use palette: Reference palette keys ("color": "gray_800") instead of hex strings. Define colors in palette for consistency.
Nest box_decoration: Decoration properties (padding, background, border, shadow, blur, corner_radius) must be inside box_decoration, not top-level in roles.
Technical Constraints
Borders: Define named entries under primitives.borders. By default a border applies to all four sides. Optional edges (top | right | bottom | left) limits which sides receive the stroke; optional style is solid | dashed | dotted. Reference by name from box_decoration.border — do not inline border objects on roles.
Elegant Styling Requirements
Card structure: Cards can be containers ("content": {"type": "container", "value": {"children": [...]}}) with box_decoration on the card role, or leaf nodes with text content. For multi-child cards, add layout.type="stack" with gap to space children.
Page backgrounds: Use document role variant with box_decoration.background referencing a gradient/solid primitive. Apply variant to root: "role": "document", "variant": "material".
Box decoration essentials: Prefer named refs: background, corner_radius, padding_pt. Add shadow / blur only when you intentionally accept raster paint (e.g. card + raised / glass). Example: "shadow": "elevation.1", "corner_radius": "medium".
Shadows: Define in primitives.shadows with layers array (official: elevation.1–3). Use blur_radius_pt 4000-24000 and alpha colors (#0000001A to #00000026).
Gradients: Define in primitives.surfaces or primitives.gradients as linear_gradient with angle_degrees and stops array (pos 0-1000, color).
Glass effects: Named surface (glass_light) + named blur: "background" in box_decoration.
Preview Rendering (CLI)
- Pack + compile a directory, then render a page PNG:
k2f pack <dir> -o /tmp/doc.K2F && k2f compile /tmp/doc.K2F && k2f render /tmp/doc.K2F -o /tmp/preview.png box_decorationcan apply to leaf nodes too (cards don’t have to be containers).
Tables
- Prefer native
content.type: "table"with explicitcolumn_widthsand inline or asset-backeddata. - For ad-hoc table-like layouts, use
layout.type="grid"and put cell nodes directly inchildren(row-major order). - Style headers/cells with roles like
table_header_cell/table_row_cell. Borders create double borders between cells; use spacing/backgrounds instead.
Layout Notes (Theme)
theme.jsonroles/variants may setself_align(start|center|end|stretch) to override a stack parent’s cross-axisalign_itemsfor that node (e.g., buttons/icons can opt out ofstretch).text_alignproperties in roles must be one ofstart,center,end, orjustify(notleft/right).- Containers may use
layout.type: "columns"(count2..=4); children may setcolumn_span: "all"for full-width figures.
Gotchas
- Theme Modifiers: Must be nested as
modifiers: { "precedence": [], "styles": { "type": { "intent": { patch... } } } }. Direct mapping fails. - Padding:
padding_ptmay be a uniform integer or{top, right, bottom, left}(not an array). - Gradients:
linear_gradientprimitives must include"type": "linear". - Roles:
line_height_multis required for all roles.