Octonode Playbook

The `.octonode` Config Reference

Canonical Octonode repository documentation.

The .octonode Config Reference

Authority depends on the deployment mode (see ADR 001). Direct CLI commands are file-authoritative: .octonode is read and written in place. Server/Studio deployments are store-authoritative for environments, node configuration, and workflow topology. There, .octonode is a versioned import/export artifact: on startup a semantic file revision is imported deterministically, with external changes winning for previously imported records while Studio-only records remain in the store. It may be written in YAML (.octonode or .octonode.yaml) or JSON (.octonode.json) — the tooling round-trips either. A published JSON Schema (octonode.schema.json) powers editor autocomplete and validation.

Ownership model (why two-way sync is tractable)

Every field has exactly one owner. No field is ever merged from two sides.

FieldOwnerWritten by scan?Effect of editing
nodes[].signature.*Codeyes (replace)drift — scan/validate flag it; code wins
nodes[].idConfig (seeded by code)seed oncerename rebinds identity
nodes[].runtime.*Configneverchanges process supervision (timeout, retries, exclusive async execution)
nodes[].presentation.*Confignevervisual editor only
environments.*Configneverinjected into node processes
workflows[].*Configneverbuilds the runtime DAG (Phase 4)
sourcesConfigneverwhat scan probes

scan writes only the signature subtree. Editing .octonode never rewrites your source code — config→code means routing/runtime, not code generation.

Shape

apiVersion: octonode.dev/v1
metadata:
  name: my-project
  version: 0.1.0

# Project-wide defaults (optional).
defaults:
  language: typescript               # used by `octonode add` when --lang is omitted

# Commands `octonode scan` probes (via describe) to discover nodes.
sources:
  - node nodes/validate.cjs
  - node nodes/charge.cjs

environments:
  dev:  { vars: { LOG_LEVEL: debug } }
  prod: { inherits: dev, vars: { LOG_LEVEL: warn } }   # single-level inheritance

nodes:
  - id: validate                     # stable identity; edges reference this
    signature:                       # CODE-OWNED — generated by scan, read-only
      language: typescript
      command: node nodes/validate.cjs
      inputs:  { type: object, properties: { order: { type: object } } }
      outputs: { type: object, properties: { valid: { type: boolean } } }
      checksum: sha256:…             # content hash, for drift detection
    runtime:      { timeout_ms: 5000, retries: 2 }   # CONFIG-OWNED
    presentation: { icon: shield-check }             # CONFIG-OWNED

workflows:
  - id: main
    # Explicit membership list (optional).  Nodes listed here are included in the
    # workflow even if they have no edges yet (useful for isolated/root nodes added
    # via `octonode add`).  The scheduler reads this list together with the edges
    # to build the DAG.
    nodes: [validate, charge]
    edges:
      - from: { node: validate, output: valid }
        to:   { node: charge,   input:  valid }
    # Workflow invocation form (source workflows project this from function params).
    inputs: { type: object, properties: { order: { type: object } }, required: [order] }
    # Fixed node inputs; applied after edges and before expressions.
    bindings:
      charge:
        currency: { kind: literal, value: USD }
    evaluations:
      - id: accepts-valid-order
        input: { order: { id: "A-1" } }
        expect:
          status: ok
          outputs: { charge: { charged: true } }
    test_workflows:
      - path: tests/main.test.ts
        runner: vitest

# Workspace-owned resources attached by stable id. Values and secrets stay out of Git.
attachments:
  plugins: [postgres]
  variables: [DATABASE_URL]
  dataTables: [customers]

defaults block

FieldTypeDescription
defaults.language"typescript"Fallback language for octonode add when --lang is omitted.

The block is optional; omitting it is equivalent to no default (the user must supply --lang).

workflows[].nodes — explicit membership

A workflow's nodes list declares which node IDs participate in the workflow. It is CONFIG-OWNED and never written by scan.

  • Nodes wired together by edges are automatically part of the workflow even without an explicit listing; nodes is only needed for nodes with no edges yet (e.g. immediately after octonode add).
  • Duplicate entries are silently de-duplicated.
  • octonode add --workflow <id> appends the new instance ID idempotently.
FieldTypeDescription
workflows[].nodesstring[]Explicit node membership; merged with the set derived from edges.

workflows[].inputs and bindings

inputs is a JSON Schema for starting the workflow. bindings stores fixed per-node values as either { kind: literal, value } or { kind: symbol, symbol, value }. See workflow inputs and triggers.

Promise topology

Source workflows project Promise joins into workflows[].promises as { node, mode }. Their indexed incoming edges preserve Promise member order. A control edge orders two nodes without copying the upstream output into the downstream input. Both fields are code-owned for source workflows; use normal data edges for hand-authored canvas workflows.

workflows[].evaluations — workflow test cases

Evaluations are CONFIG-OWNED cases that run through the same DAG scheduler as normal executions. They inherit the workflow's visibility and are versioned with the project config. expect.outputs is an exact terminal-output object; omit it to check only the run status.

FieldTypeDescription
idstringUnique case id within the workflow.
descriptionstringOptional human-readable purpose.
inputJSONInput passed to every workflow root.
expect.status"ok" | "error" | "partial"Expected run status; defaults to ok.
expect.outputsJSON objectOptional exact terminal outputs keyed by node id.
judge.workflowstringOptional related workflow that grades the target run.
judge.rubricstringExplicit criteria passed to the judge workflow.
judge.threshold0..1Minimum numeric judge score; defaults to 0.7.

workflows[].test_workflows — linked repository tests

Studio discovers conventional *.test.* and *.spec.* files automatically. Link the files that verify a workflow explicitly so unrelated project tests do not inherit its visibility.

FieldTypeDescription
pathstringProject-relative test file path.
runner"vitest" | "jest" | "playwright" | "promptfoo"Installed test adapter used for this file.

A judge workflow receives { rubric, threshold, target }, where target contains the workflow id, case id, input, expected assertions, and full candidate run trace. Its terminal output must contain either { score: 0..1, reason?: string } or { passed: boolean, reason?: string }.

Commands

CommandPurpose
octonode init [path]scaffold a new config (--format json|yaml, --name, --force)
octonode scancode→config: probe sources via describe, write signatures
octonode scan --checkCI gate: write nothing, exit non-zero on drift
octonode validateschema + structural checks (duplicates, drift, orphans, edges)
octonode invoke <id> --env <e>config→runtime: resolve a node, inject env + runtime, run it

Studio's project Compile action runs source discovery, synchronizes code-owned signatures, then applies the same structural checks. Errors fail Compile; warnings remain advisory.

nodes[].runtime — process supervision

FieldTypeDescription
timeout_mspositive integerHard deadline for one attempt.
retriesnon-negative integerRetry attempts after the initial attempt.
retry_backoff_msnon-negative integerBase delay between retry attempts.
concurrencypositive integerReserved per-node concurrency limit.
asyncbooleanWait for running nodes, execute alone in this workflow run, then resume parallel work.

The Code and Documentation tabs follow .gitignore and optional .octonodeignore rules. .octonodeignore only adds exclusions; secret files, binaries, dependencies, build output, and .git are always hidden from the browser editor. The Code tab keeps the source editor and compile workflow. The separate Documentation tab lists non-code text files, starting at root README.md when available, and supports creating, renaming, deleting, and editing them up to 2 MB. Documents stay ordinary project files rather than nodes or config records, so Git and cloud snapshots include the same files. Markdown preview is sanitized and does not auto-load local or remote media, while JSON/YAML previews validate and format a read-only projection without rewriting the source.

Drift & orphans

  • Drift: a signature whose stored content no longer matches what code reports (or whose checksum is stale from a hand-edit). scan rewrites it (code wins); scan --check fails; validate warns.
  • Orphan: a node whose source is no longer discovered. scan marks signature.orphaned: true rather than deleting it (so it never silently drops human-authored topology). Remove it yourself once you're sure.

On this page