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.
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
| Key | Type | Required | Description |
|---|---|---|---|
pod_spec_version | string | yes | Must be "0.1". |
[pod] | table | yes | Identity. |
[runtime] | table | yes | Which runtime executes the pod. |
[directive] | table | yes | What the pod should do. |
[model], [hardware], [dependencies], [context], [inputs], [output], [budget], [wallet], [hooks], [marketplace] | table | no | Documented 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"
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Matches ^[a-z][a-z0-9_-]*$, 1–64 chars. |
version | string | yes | Semver (MAJOR.MINOR.PATCH). |
authors | array<string> | no | Unique entries. |
license | string | no | License identifier. |
description | string | no | Human-readable summary. |
homepage | string (uri) | no | Public homepage. |
tags | array<string> | no | Discovery tags, unique. |
visibility | string | no | open (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_id | string | no | 32-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"
| Field | Type | Required | Description |
|---|---|---|---|
kind | string | yes | A registered runtime: orca, lobster, pi-agent, kimi-cli, … (lobster is the one-shot runtime shipping in reef-core). |
version | string | no | Cargo-style constraint: ^0.1, ~1.2.0, >=0.3, *. |
execution_class | string | no | cloud (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
| Field | Type | Required | Description |
|---|---|---|---|
provider | string | yes | Provider identifier (e.g. anthropic). |
name | string | yes | Model name. |
max_tokens | integer ≥ 1 | no | Maximum output tokens. |
temperature | number 0–2 | no | Randomness control. |
provider_opts | table | no | Provider-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"
| Field | Type | Description |
|---|---|---|
cpu_cores | integer ≥ 1 | CPU cores requested. |
memory / disk | byte size | Binary units, e.g. "8GiB", "512MiB". |
gpu.kind | enum | nvidia, amd, or apple. |
gpu.count / gpu.vram_gib | integer ≥ 1 | GPU count and per-GPU VRAM (GiB). Required within [hardware.gpu]. |
gpu.model | string | Optional 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"]
| Field | Type | Description |
|---|---|---|
system | array<string> | System packages the runtime expects. |
runtime | array<string> | Runtime-level dependencies. |
secrets | array<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-table | Fields |
|---|---|
[[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 }
| type | Type-specific attributes |
|---|---|
string | default, pattern |
int | default, min, max |
float | default, min, max |
bool | default |
enum | values (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"]
| Field | Type | Description |
|---|---|---|
task | string | Inline directive. Mutually exclusive with template. |
template | path | Mustache-templated directive file (./…). |
max_iterations | integer ≥ 1 | Agent iteration cap. |
tools_allowed / tools_denied | array<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):
| kind | Fields |
|---|---|
file_exists | path |
min_words | path, count |
contains_regex | path, pattern |
timeout_seconds | value |
budget_exhausted | — |
tool_called | tool |
custom_script | script (./…) |
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.
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
| Field | Type | Description |
|---|---|---|
max_sats | integer ≥ 0 | Spending limit for the run. A run can spend somewhat more than this before it stops. |
per_call_cap_sats | integer ≥ 0 | Accepted, not enforced yet. |
daily_cap_sats | integer ≥ 0 | Accepted, not enforced yet. |
[wallet]
How reef-core provisions the pod's spend wallet.
[wallet]
strategy = "fresh"
| Field | Type | Description |
|---|---|---|
strategy | enum | fresh, reuse, or pooled. Required. |
reuse | string | Wallet 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"]
| Field | Type | Description |
|---|---|---|
listed | boolean | Whether the pod is listed. |
price_model | enum | per_run, subscription, or free. |
price_sats | integer ≥ 0 | Price in satoshis. |
preview_url | string (uri) | Preview link. |
icon / screenshots | path(s) | Repo-relative asset paths. |
categories | array<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
- Missing a required table —
pod_spec_version,[pod],[runtime], and[directive]must all be present. - Both
taskandtemplatein[directive]— provide exactly one. - A file path without the leading
./— v0.1 only accepts repo-relative paths. - An unknown field or misspelled table — extra keys are rejected; run
konareef pod validateto catch them. - Putting a secret value in
[dependencies].secrets— declare the name only. - Expecting dollars — budgets are in satoshis.