orgo.ai/v1 document, written in YAML or JSON. This page is the field-by-field reference. The canonical machine-readable contract is the JSON Schema at GET /api/template-schema. Point your editor at it for autocomplete and inline validation.
Two forms
Templates accept a canonical form and a shorter sugar form. Both normalize to the same document and the samedigest.
Sugar → canonical
api_version has no sugar: every document needs it, in either form. Don’t mix the forms: a document with a canonical template: block that otherwise parses as canonical is read as canonical, and its top-level sugar keys, such as cpu or on_every_boot, are ignored. In a sugar document, a canonical hardware value wins over its flat key: if a document sets both hardware.cpu and top-level cpu, the hardware value is used and the sugar key is ignored. ram and disk accept 4gb, 4g, or a bare 4; a sub-gigabyte size such as 512mb resolves to 0, which is the same as omitting it.
Top-level fields
Every field except
api_version and template is optional, so the smallest valid template is a name, a version, and the API version.
template
Identity and provenance.name and version are required.
hardware
The computer’s resource shape. Every field is optional; omit one and the platform default applies. A Create computer request’scpu, ram, and disk override these at launch. The template’s resolution always wins over the request’s, because the golden snapshot was captured at it.
vars and interpolation
vars are compile-time strings, interpolated across the document before build.
${var.X}resolves fromvars.${env.X}resolves from a literalenvvalue (not secret-backed ones).$${var.X}escapes to a literal${var.X}.- Only the
var.andenv.forms are substituted, so a shell variable such as${HOME}passes through unchanged. - An unknown reference is not caught by Validate template or at publish. It fails the build, and the build’s
errornames the exact field path.
env
Environment variables written to the computer. Keys must beUPPER_SNAKE_CASE. Each value is a literal string, or a {secret: <name>} reference resolved from the launching user’s vault at create time. A value cannot be both.
{secret: …} reference to a name you never declared under secrets is a validation error (unknown_reference).
Literal values are written to /root/.env, which is sourced at boot before services, terminal sessions, and boot hooks start, and by new interactive shells. Two caveats apply at launch, both covered in Secrets:
- A
{secret: …}reference is not applied. The value arrives only under the secret’s ownUPPER_SNAKE_CASEname, so the example above works becauseANTHROPIC_API_KEYis that name. - A launch that injects secrets rewrites
/root/.envwith only the secrets, so literal values are not set on that computer. Put a value a service needs in that service’s ownenv.
build
Package and command steps run once when baking the golden snapshot, before app installs. This is where dependencies get pre-installed so launches are instant.files
Files materialized into the computer. Each entry sets exactly one offrom or inline. Setting both, or neither, is a validation error.
File sources
Sources are fetched once, on the build machine, and the result is baked in.httpandhttpsdownload the URL.gitclones over HTTPS:git://github.com/owner/repo#path/to/filewrites that file, and a directory is written as a tar archive.s3works only for a public AWS bucket.fileis accepted by validation, but the build cannot read it and fails.secret://<name>must name a declared secret, but the file is never written. See Secrets.
apps
An app bundles an install step with the long-running services, health checks, and ports it needs. Services are managed by supervisord, so they start at boot and respawn on crash.name is required and must be unique kebab-case. requires lists other app names this one depends on, and data lists persistent data paths, validated the same way as files[].to.
services
health
A polled liveness check. Afterretries consecutive failures, on_fail runs. This is the per-app watchdog. type is required, and so is the field that type checks (url, port, command, or process). The other fields are optional.
every defaults to 30s, timeout to 5s, and retries to 3. All durations are Go duration strings (30s, 2m, 1h). on_fail is one of restart_service:<name>, restart_vm, alert, or none. Only restart_service acts: restart_vm and alert write a log line and do nothing else.
ports
terminal
Pre-staged tmux sessions. Each one is created detached on every cold boot unless it already exists, and itsrun, if set, is typed into it as the first command. A launch that restores the golden snapshot’s memory keeps the sessions the build left running. Orgo’s browser terminal attaches to them by name. name is required and must be unique.
Sessions are not auto-restarted. For a process that must respawn, use an app service instead.
hooks
Shell that runs at lifecycle points. Each runs withset -e and times out after 10 minutes.
telemetry
<otel_endpoint>/v1/metrics and logs to <otel_endpoint>/v1/logs, as OTLP JSON. Each logs entry names a service, whose log is /var/log/orgo/<service>.log.
egress_policy
Per-computer network filtering, applied on the host when the computer is created.mode is allow or block (allowlist and denylist also work), and rules lists domains, IPs, or CIDRs. The JSON Schema requires both fields, but publish does not check them: a policy with no rules, or with any other mode, leaves the computer unfiltered.
- Domain rules filter DNS lookups only. A rule matches any lookup whose name contains its second-level label, so
*.github.com,github.com, andapi.github.comall match every name containinggithub. - IP and CIDR rules filter traffic to those addresses.
blockdrops lookups that match a domain rule and traffic to a listed address. Everything else is allowed.allowaccepts traffic to listed addresses and lookups that match a domain rule, and drops all other lookups. With at least one domain rule, only lookups are filtered, so a connection made by IP address is not blocked. With only IP or CIDR rules, all other traffic is dropped.
streaming
Outbound RTMP(S) streams of the desktop.name, url, and key are required; url must start with rtmp:// or rtmps://.
streaming is parsed and validated, but no runtime streamer is wired up yet. A declared stream does not broadcast.Next steps
Secrets
The full secret-injection model.
Triggers
Sources, actions, and dedup.
Examples
Annotated real templates.
Publish API
Ship a template over HTTP.