pod.toml reference

Every table and field in the pod.toml v0.1 manifest. konareef pod validate checks a pod against this schema offline; reef-core remains the authoritative parser and execution environment.

Reading this reference

pod_spec_version, [pod], [runtime], and [directive] are required; everything else is optional. Unknown fields are rejected — most tables forbid extra keys. In v0.1 every file path is repo-relative and must start with ./. The spec is pre-1.0: it may still make breaking changes before pod_spec_version = "1.0".

Minimal example

pod_spec_version = "0.1"

[pod]
name    = "hello-world"
version = "0.1.0"

[runtime]
kind = "lobster"

[directive]
task = "Say hello to the world and write it to ./greeting.md."

Top-level fields

KeyTypeRequiredDescription
pod_spec_versionstringyesMust be "0.1".
[pod]tableyesIdentity.
[runtime]tableyesWhich runtime executes the pod.
[directive]tableyesWhat the pod should do.
[model], [hardware], [dependencies], [context], [inputs], [output], [budget], [wallet], [hooks], [marketplace]tablenoDocumented below.

[pod]

Pod identity. name and version are required.

[pod]
name        = "invoice-summarizer"
version     = "1.2.0"
description = "Summarizes invoices and extracts payment terms."
authors     = ["Dave <[email protected]>"]
license     = "MIT"
homepage    = "https://example.com/invoice-summarizer"
tags        = ["finance", "documents"]
lineage_id  = "37c90baadd4c3c8e79f544ed7356c17b"
FieldTypeRequiredDescription
namestringyesMatches ^[a-z][a-z0-9_-]*$, 1–64 chars.
versionstringyesSemver (MAJOR.MINOR.PATCH).
authorsarray<string>noUnique entries.
licensestringnoLicense identifier.
descriptionstringnoHuman-readable summary.
homepagestring (uri)noPublic homepage.
tagsarray<string>noDiscovery tags, unique.
lineage_idstringno32-char lowercase hex; a per-lineage salt-lookup key. Generated by konareef pod init.

[runtime]

The registered runtime that executes the pod. Required.

[runtime]
kind    = "orca"
version = "^0.1"
FieldTypeRequiredDescription
kindstringyesA registered runtime: orca, lobster, pi-agent, kimi-cli, … (lobster is the one-shot runtime shipping in reef-core).
versionstringnoCargo-style constraint: ^0.1, ~1.2.0, >=0.3, *.

[model]

The model the runtime should use. The provider key is resolved from the reef-core vault at spawn — never stored here.

[model]
provider    = "anthropic"
name        = "claude-sonnet-4-5"
max_tokens  = 2000
temperature = 0.2
FieldTypeRequiredDescription
providerstringyesProvider identifier (e.g. anthropic).
namestringyesModel name.
max_tokensinteger ≥ 1noMaximum output tokens.
temperaturenumber 0–2noRandomness control.
provider_optstablenoProvider-specific options (free-form).

[hardware]

Optional resource requirements for the runtime.

[hardware]
cpu_cores = 4
memory    = "8GiB"
disk      = "20GiB"

[hardware.gpu]
kind     = "nvidia"
count    = 1
vram_gib = 24
model    = "A10G"
FieldTypeDescription
cpu_coresinteger ≥ 1CPU cores requested.
memory / diskbyte sizeBinary units, e.g. "8GiB", "512MiB".
gpu.kindenumnvidia, amd, or apple.
gpu.count / gpu.vram_gibinteger ≥ 1GPU count and per-GPU VRAM (GiB). Required within [hardware.gpu].
gpu.modelstringOptional GPU model name.

[dependencies]

External requirements. Secrets are declared by name only — values come from the reef-core vault at spawn.

[dependencies]
system  = ["pandoc"]
runtime = ["some-runtime-plugin"]
secrets = ["OPENAI_API_KEY", "GITHUB_TOKEN"]
FieldTypeDescription
systemarray<string>System packages the runtime expects.
runtimearray<string>Runtime-level dependencies.
secretsarray<string>Secret names matching ^[A-Z][A-Z0-9_]*$. Never put values here.

[context]

Memory, skills, tools, and prompt files the pod composes at spawn.

[[context.prompts]]
role = "system"
path = "./prompts/system.md"

[[context.tools]]
source = "./tools/search.toml"

[[context.memory]]
kind     = "openbrain"
snapshot = "2026-06-01"
Sub-tableFields
[[context.memory]]kind = openbrain → snapshot; file → path; http → url; inline → content.
[[context.skills]]source (required, ./path), version (constraint).
[[context.tools]]source (required), config (table).
[[context.prompts]]role = system / user_template / assistant_seed, path (required).

[inputs]

A map of input name → descriptor. Names match the identifier pattern. Inputs are surfaced to the directive template (e.g. {{name}}).

[inputs]
customer_name = { type = "string", required = true }
urgency       = { type = "enum", values = ["low", "normal", "high"], default = "normal" }
retries       = { type = "int", min = 0, max = 5, default = 1 }
typeType-specific attributes
stringdefault, pattern
intdefault, min, max
floatdefault, min, max
booldefault
enumvalues (required), default

Every input also accepts required (boolean) and description (string).

[directive]

What the pod should do. Provide exactly one of task (inline) or template (a Mustache file). Required.

[directive]
template       = "./prompts/system.md"
max_iterations = 5
tools_allowed  = ["web_search"]
tools_denied   = ["shell"]
FieldTypeDescription
taskstringInline directive. Mutually exclusive with template.
templatepathMustache-templated directive file (./…).
max_iterationsinteger ≥ 1Agent iteration cap.
tools_allowed / tools_deniedarray<string>Tool allow/deny lists.

[output]

The definition of done — success/failure predicates plus declared deliverables. This is not a JSON output schema.

[output]
format = "markdown"

[[output.success]]
kind  = "file_exists"
path  = "./report.md"

[[output.success]]
kind  = "min_words"
path  = "./report.md"
count = 200

[[output.failure]]
kind  = "timeout_seconds"
value = 600

[[output.deliverables]]
path        = "./report.md"
description = "The finished report."

Predicate kinds (used in both success and failure):

kindFields
file_existspath
min_wordspath, count
contains_regexpath, pattern
timeout_secondsvalue
budget_exhausted
tool_calledtool
custom_scriptscript (./…)

Deliverables: path (required), description, optional (boolean).

DSL vs. what runs today

The [output] predicate DSL is intentionally broader than what reef-core evaluates at runtime today. Declare the definition of done you want; treat the richer predicates as forward-looking until the runtime confirms enforcement.

[budget]

Hard spending caps, denominated in satoshis.

[budget]
max_sats          = 1000
per_call_cap_sats = 200
daily_cap_sats    = 5000
FieldTypeDescription
max_satsinteger ≥ 0Total cap for the run.
per_call_cap_satsinteger ≥ 0Cap per model/tool call.
daily_cap_satsinteger ≥ 0Rolling daily cap.

[wallet]

How the pod's spend wallet is provisioned.

[wallet]
strategy = "fresh"
FieldTypeDescription
strategyenumfresh, reuse, or pooled. Required.
reusestringWallet reference — required when strategy = "reuse".

[hooks]

Lifecycle scripts (repo-relative paths) run around spawn.

[hooks]
pre_spawn  = "./hooks/pre.sh"
on_success = "./hooks/done.sh"

Fields: pre_spawn, post_spawn, on_success, on_failure — each a ./… path.

[marketplace]

Listing metadata for pods published to the marketplace.

[marketplace]
listed      = true
price_model = "per_run"
price_sats  = 500
categories  = ["finance", "documents"]
FieldTypeDescription
listedbooleanWhether the pod is listed.
price_modelenumper_run, subscription, or free.
price_satsinteger ≥ 0Price in satoshis.
preview_urlstring (uri)Preview link.
icon / screenshotspath(s)Repo-relative asset paths.
categoriesarray<string>Marketplace categories, unique.

Full example

pod_spec_version = "0.1"

[pod]
name        = "invoice-summarizer"
version     = "1.2.0"
description = "Summarizes invoices and extracts payment terms."
authors     = ["Dave"]
license     = "MIT"
tags        = ["finance", "documents"]

[runtime]
kind    = "orca"
version = "^0.1"

[model]
provider    = "anthropic"
name        = "claude-sonnet-4-5"
temperature = 0.2

[dependencies]
secrets = ["OPENAI_API_KEY"]

[inputs]
customer_name = { type = "string", required = true }
urgency       = { type = "enum", values = ["low", "normal", "high"], default = "normal" }

[directive]
template       = "./prompts/system.md"
max_iterations = 5

[output]
format = "markdown"

[[output.success]]
kind = "file_exists"
path = "./summary.md"

[[output.failure]]
kind  = "timeout_seconds"
value = 600

[[output.deliverables]]
path        = "./summary.md"
description = "The invoice summary."

[budget]
max_sats          = 5000
per_call_cap_sats = 500

[wallet]
strategy = "fresh"

[marketplace]
listed      = true
price_model = "per_run"
price_sats  = 500
categories  = ["finance"]

Common mistakes