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.
visibilitystringnoopen (default) or closed. A closed pod publishes its body encrypted and must set [runtime] execution_class = "cloud". reef-core refuses a closed pod that breaks these rules at publish. See Closed pods.
lineage_idstringno32-char lowercase hex. A per-lineage salt-lookup key. Generated by konareef pod init.

Closed pods

A closed pod keeps its body (prompts, skills and other files) out of public view. To declare one, set two fields:

[pod]
name       = "invoice-summarizer"
version    = "1.2.0"
visibility = "closed"

[runtime]
kind            = "orca"
execution_class = "cloud"

A closed pod must set execution_class = "cloud". It cannot use local-mount. konareef pod publish encrypts the body before it sends the pod. reef-core also checks these rules at publish and refuses a closed pod that breaks them. See Errors you may see.

What stays public. The signed head of the pod stays public. It contains the name, the version, the interface, the tool names, the secret names, and the path and SHA-256 hash of each body file. The public lookup returns only this head. konareef install also gets only the signed head, not the body.

What closed does not mean. konareef infrastructure decrypts the body to run the pod. Every field that a pod reads goes to the model provider as part of the prompt. Someone can also make a run show its prompt or copy body files into its output. Closed keeps the body out of the public lookup and out of konareef install. It does not hide the body from the run.

On the hosted service. A closed pod runs only while it is listed. If it is not listed, a run request gets closed_pod_not_listed. Closed pods get custody proofs only: there is no zero-knowledge tier for a closed pod. For a closed pod, the run log and the live stream keep each event name and time. reef-core removes the text. An error shows only as runtime_error.

[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, *.
execution_classstringnocloud (platform-run) or local-mount (needs the commissioner's machine to mount a drive). Optional for a pod you only run yourself. Required to list a pod: konareef pod listing publish refuses a pod that omits it, and reef-core rejects the listing with execution_class_undeclared.

[model]

The model the runtime should use. reef-core resolves the provider key from its vault at spawn. The key is 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. Declare secrets by name only. reef-core supplies the values from its 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). source names a tool file (./…) or a runtime built-in tool. It does not install or restrict the tool.
[[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. Declaration only: not enforced yet.

[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).

Users can download only declared deliverables. This rule applies to every pod, open or closed. A user can download only the files that [[output.deliverables]] lists. A request for any other file gets HTTP 404. A pod that declares no deliverables serves no files.

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]

Spending limits, in satoshis.

[budget]
max_sats = 1000
FieldTypeDescription
max_satsinteger ≥ 0Spending limit for the run. A run can spend somewhat more than this before it stops.
per_call_cap_satsinteger ≥ 0Accepted, not enforced yet.
daily_cap_satsinteger ≥ 0Accepted, not enforced yet.

[wallet]

How reef-core provisions the pod's spend wallet.

[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

[wallet]
strategy = "fresh"

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

Common mistakes