Reads & Writes
FromSpec: The Source Vocabulary
FromSpec: The Source Vocabulary
FromSpec is the unified source vocabulary used by gated writes, dynamic step loading, retrieve result injection, and passFields. One way to specify a source, everywhere. Six forms cover all cases: keywords (previous, output), input keys (input.X), literals, step references, and slate references.
The six forms
FromSpec appears as the value of from: in write actions, dynamic step declarations, and passFields. Six forms are accepted:
| Form | Example | What it resolves to |
|---|---|---|
previous (keyword) | from: previous | All survivors of the immediately preceding step |
output (keyword) | from: output | The current step's own combined output |
input.X (input key) | from: "input.context" | A value from the runtime inputs map |
| literal string | from: "No data available" | The literal string itself |
| step reference | from: { stepId: "draft", nodeRef: current } | A specific step's output (optionally a specific node) |
| slate reference | from: { slate: "Memory", folder: facts, file: core.md } | Contents of a slate file or metatag |
# Keyword: previous step's survivors
then:
write:
to: { slate: "Memory", folder: trace, file: latest.md }
from: previous
# Keyword: current step's output
then:
write:
to: { slate: "Memory", folder: results, file: current.md }
from: output
# Input key
then:
write:
to: { slate: "Memory", folder: queries, file: log.md }
from: "input.context"
# Literal string
then:
write:
to: { slate: "Memory", folder: notes, file: marker.md }
from: "--- Execution boundary ---"
# Step reference
then:
write:
to: { slate: "Memory", folder: drafts, file: best.md }
from: { stepId: generate, nodeRef: current }
# Slate reference
then:
write:
to: { slate: "Memory", folder: backup, file: copy.md }
from: { slate: "Memory", folder: drafts, file: best.md }Keywords: previous and output
Two bare-string keywords have special meaning:
previous resolves to the combined output of the step immediately before the current one in execution order. This is the step that ran just before the current step in the pipeline loop.
# Write the previous step's output to a slate
then:
write:
to: { slate: "Memory", folder: trace, file: latest.md }
from: previous
on: overwriteoutput resolves to the current step's own combined output (all surviving nodes joined with double newlines). This is mainly used in gated writes under if/then — the write fires after the gate evaluates, so output is the step's output that was just evaluated.
# If the gate passes, write this step's output to memory
if:
jsonMatches: { properties: { confidence: { minimum: 0.8 } } }
then:
write:
to: { slate: "Memory", folder: facts, file: verified.md }
from: output
on: appendBoth keywords are only meaningful in the context of a write action or passField — they refer to runtime execution state, not config-time declarations.
Input keys: input.X
Any bare string starting with input. is treated as an input-key lookup. The runtime resolves it against the execution's inputs map.
# Write the original user question to a slate
from: "input.context"
# Write the system time
from: "input.systemTime"Common input keys:
| Key | Contents |
|---|---|
input.context | The user's message (the last user role message from the API call) |
input.systemTime | The current UTC time in ISO 8601 format |
input.localTime | The local time (when a timezone was supplied) |
input.timezone | The timezone string (when supplied) |
Missing input keys resolve to an empty string — no error. This makes input.X safe to use in fallback positions.
Step references
An object with stepId resolves to a specific step's output. Optionally narrow to a specific node or node reference.
# Read a specific step's combined output
from: { stepId: generate }
# Read a specific node (by number)
from: { stepId: generate, node: 3 }
# Read the current node's output from a specific step
from: { stepId: generate, nodeRef: current }
# Read the previous node's output
from: { stepId: generate, nodeRef: previous }nodeRef values:
current— the node number matching the current execution context (e.g., node 3 of step A reads node 3 of the referenced step).previous— the node before the current one. If the current node is 1, falls back to node 1.accumulate— all nodes of the referenced step, joined. Only valid inmulti_ingestfields, not in FromSpec.
node vs nodeRef: node takes a specific integer (read node 3 regardless of context). nodeRef takes a keyword that resolves relative to the current execution context.
Slate references
An object with slate resolves to a slate location. This lets one write copy content from one slate location to another.
# Copy a file's contents
from: { slate: "Memory", folder: drafts, file: best.md }
# Read a metatag value
from: { slate: "Memory", folder: drafts, file: best.md, metatag: score }If no file is specified, the reference is invalid for FromSpec (slate references require a file). For folder-level reads (indexes, trees), use the slateRead field type with system metatags instead.
Fallback in FromSpec contexts
Several FromSpec-consuming declarations also accept a fallback: field. When the primary from: resolves to an empty value or a source-missing error, the fallback is consulted.
# Gated write with fallback
then:
write:
to: { slate: "Memory", folder: trace, file: latest.md }
from: { stepId: optional_step } # might not have run
fallback: previous # fall back to previous step's output
on: overwrite
# Dynamic step with fallback
- id: dynamic_step
dynamic: true
from: { stepId: planner } # planner's output is the config
fromFallback: "input.context" # if planner didn't run, use the inputFallback resolution uses the same FromSpec vocabulary. The fallback chain is one level deep — there is no fallback-of-fallback. If both primary and fallback miss, the resolved value is empty.
Fallback is consulted when:
- The primary source resolves to an empty string.
- The primary source raises a
NodeDependencyError(the referenced step didn't run or the node doesn't exist).
Other errors (slate store unavailable, JSON parse failures) propagate without consulting the fallback.