Agent File
| Name (singular): | Agent File |
| Name (plural): | Agent Files |
| Alias (uri): | agent_file |
| Identifier (ID): | cerb.contexts.agent.file |
An agent file is a single file stored inside an agent filesystem volume.
In normal use you don't create or edit these records directly. Files are written through the filesystem command set – by an AI agent using its agent_terminal tool, or by a worker in Setup » Developers » Agent Filesystem Terminal. The record type exists so files are searchable, linkable, and reportable like any other record.
Frontmatter
A Markdown file can open with a --- fenced YAML block. It's parsed and stored separately in frontmatter_json, which lets a volume of documents carry structured metadata – a title, tags, an owner – that can be listed without opening each file.
/runbooks/refund.md:
---
title: Refund a customer
description: How to issue a refund and notify the customer.
tags:
- billing
- support
version: 3
reviewed: 2026-07-14
is_public: false
owner:
team: Support
email: support@example.com
---
# Refund a customer
1. Open the ticket and confirm the charge in the billing portal.
2. Issue the refund.That file's frontmatter_json (stored minified, shown here expanded):
{
"title": "Refund a customer",
"description": "How to issue a refund and notify the customer.",
"tags": ["billing", "support"],
"version": 3,
"reviewed": "2026-07-14",
"is_public": false,
"owner": { "team": "Support", "email": "support@example.com" }
}Values keep their YAML types: version is a number, is_public is a boolean, a list becomes an array, and a nested map becomes a nested object. Dates are the exception – reviewed stays a string.
content is the whole file, frontmatter block included. Nothing is stripped,
so reading this file returns the --- fences and the YAML along with the body, and
size counts them. frontmatter_json is an index alongside the
content, not a slice taken out of it -- which means an agent rewriting a file has to re-emit the
block, or it's gone.
What parses
| Rule | Detail |
|---|---|
| Extension | Only .md and .markdown. Any other file stores nothing, however valid its block |
| Position | The opening --- must be the very first thing in the file |
| Fences | Exactly three dashes. The closing fence may have trailing spaces, nothing else |
| Structure | The block must be a mapping or a list – a lone scalar is rejected |
| Size | A parsed block over 64KB is discarded rather than truncated |
When it doesn't parse
Nothing happens, and that's the thing to know: a malformed block, a block below line 1, or an unsupported extension stores frontmatter_json as null. The file still saves normally, with no error and no warning. If you added frontmatter and nothing came of it, this is why – check the extension first, then the position.
A horizontal rule at the top of a file can be captured by accident. Two ---
rules with text between them look exactly like a frontmatter block, and if that text happens to
parse as YAML it's stored as metadata. A document opening with ---, then
Note: this is prose., then --- quietly gains a
Note key. Rare, but silent when it happens.
Reading it back
There's no frontmatter: search filter, and no content: filter either, so this metadata isn't something you can query a worklist by. It's read through the filesystem commands instead:
ls /runbooks --fields title,tags--fields prints per-key values as columns without opening any file, on both ls and find. A list joins with commas; a nested map joins its values. A missing key prints empty – and so does a false boolean, which makes the two indistinguishable in a listing.
Piped rows carry the decoded map as meta, which is always a map and empty rather than absent when a file has no frontmatter – so a fallback is safe across a volume where only some files carry it:
search refund | results|map(r => r.meta.title ?? r.path)In scripting, the frontmatter_json placeholder is the raw JSON string rather than a map, so there's no per-key access through it.
The field is also writable through the Records API, and an explicit value wins over the one parsed from the content – so it's possible, deliberately or otherwise, for the stored metadata to disagree with the file it describes.
Bulk import
Files arrive in bulk by uploading a ZIP archive to a volume, which is imported in the background as a queue job. Each import is tracked so a volume's card can show the history of past imports.
Records API
These fields are available in the Records API and packages:
| Req'd | Field | Type | Notes |
|---|---|---|---|
content |
text | The file's contents | |
created_at |
timestamp | The date/time when this record was created | |
file_extension |
text | The file's extension | |
filesystem_id |
number | The ID of the parent agent filesystem | |
frontmatter_json |
text | The file's parsed frontmatter, as JSON | |
id |
number | The ID of this file | |
links |
links | An array of record type:id tuples to link to. Prefix with - to unlink. |
|
| x | name |
text | The file's name |
size |
number | The file's size, in bytes | |
updated_at |
timestamp | The date/time when this record was last modified |
Search Query Fields
These filters are available in agent file search queries:
| Field | Type | Description |
|---|---|---|
created |
date | When the record was created |
fieldset |
virtual | Filter by custom fieldset |
file_extension |
text | The file's extension |
filesystem.id |
number | The parent agent filesystem |
id |
number | The record ID |
name |
text | The file name (partial match) |
size |
number | The file's size, in bytes |
updated |
date | When the record was last modified |
watchers |
virtual | Filter by watchers |