Redeo Docs
DocsLADR / The Manifest Field

Dynamic Steps

The Manifest Field

The Manifest Field

The manifest field injects a runtime snapshot of the ladder's state into the prompt. It is the primary input for dynamic step generation — the planner LLM reads the manifest to know what sources it can reference. Manifest fields support targeted views via from:, or a configurable default bundle declared at the config level.

Declaring a manifest field

The manifest field is declared like any other field, with type: manifest. An optional from: selects a specific view; without from:, the field uses the config-level defaultManifest bundle (or the full dump if no default is declared).

yaml
fields:
  # Specific view — just the current time
  - name: Now
    type: manifest
    from: time

  # Specific view — file listing for one folder
  - name: Facts
    type: manifest
    from: { index: { slate: Memory, folder: facts } }

  # Bare — uses defaultManifest bundle (or full dump)
  - name: Available
    type: manifest

Manifest views

The from: property selects what data the manifest injects. Each view is a single-purpose snapshot — you inject only what the step needs, keeping token cost minimal.

from: valueWhat it injectsApproximate cost
timeCurrent timestamp(s): UTC now, optional local time + timezone~30 tokens
structureSlate titles + folder names, no files~3 tokens per folder
{ index: { slate, folder } }Flat file list for one folder: [{ name, size }, ...]~5 tokens per file
{ index: { slate, depth: N } }File lists across all folders in the slate, capped at N files per folderbounded
{ tree: { slate, depth: full } }Full recursive tree of all folders and filesscales with slate size
{ tree: { slate, depth: N } }Recursive tree, depth-limited to Nbounded
bare (no from:)defaultManifest bundle, or full dump if no default declaredvaries

Time view injects the current timestamp(s). Useful for time-aware reasoning without a separate text field.

yaml
- name: Now
  type: manifest
  from: time

Renders as:

json
{ "now": "2026-07-26T12:00:00Z", "localNow": "2026-07-26T08:00:00-04:00", "timezone": "America/New_York" }

Structure view injects slate titles and folder names — the skeleton of available memory, without any file details. Useful when the planner needs to know what slates exist but doesn't need file-level granularity.

yaml
- name: Layout
  type: manifest
  from: structure

Index view injects a flat file listing. With folder, it lists files in one folder. With depth: N, it lists files across all folders, capped at N files per folder to bound token cost.

yaml
- name: Facts
  type: manifest
  from: { index: { slate: Memory, folder: facts } }

- name: AllFiles
  type: manifest
  from: { index: { slate: Memory, depth: 10 } }

Tree view injects a recursive folder tree. depth: full includes everything; depth: N limits recursion depth.

yaml
- name: MemoryTree
  type: manifest
  from: { tree: { slate: Memory, depth: full } }

Default manifest bundle

When a step declares a bare type: manifest (no from:), the engine resolves it using the config-level defaultManifest bundle. This lets you declare a standard set of views once at the top of the ladder and reuse them everywhere.

yaml
ladrVersion: "0.1"
name: My Ladder
exit: answer
allowedTargets: { strategy: universal }
knobs: {}
steps: [ ... ]
defaultManifest:
  - time
  - structure
  - index: { slate: Memory, folder: facts }

Now any step with a bare manifest field gets exactly these three views — time, structure, and the facts folder listing — instead of the expensive full dump.

Resolution rule:

Step declaresConfig has defaultManifestResult
type: manifest + from: time(ignored)Just the time view
type: manifest (bare)YesThe defaultManifest bundle
type: manifest (bare)NoFull dump (backward compat)

Full dump (backward compat)

When a bare manifest field has no from: AND the config declares no defaultManifest, the engine injects the full runtime snapshot — the original behavior. This includes:

  • Inputs — all non-internal input keys (input.context, input.systemTime, etc.)
  • Knobs — resolved knob values
  • Steps — every step's ID, loop index, node count, and survivor count
  • Slates — every slate's title, folders, and files (with sizes)
  • Time — current UTC time (+ local time/timezone if supplied)

This is the most expensive option. For production ladders, declare a defaultManifest with targeted views to keep token costs bounded.

Using the manifest for planning

The manifest is the planner's map. The planner LLM reads it, decides what to do, and emits a step config that references only sources listed in the manifest.

yaml
- id: plan_next
  fields:
    - { name: Available, type: manifest }
    - { name: Context, type: text, from: input.context }
  systemPrompt: |
    You are a planning agent. Based on Available sources and the Context,
    decide what to do next.

    Emit a JSON step config:
    {
      "systemPrompt": "...",
      "fields": [
        { "name": "...", "type": "ingest", "from": { "stepId": "...", "loopRef": "current" } },
        { "name": "...", "type": "slateRead", "from": { "slate": "...", "folder": "...", "file": "..." } }
      ],
      "nodes": 3
    }

    Reference ONLY sources listed in Available. Do not invent step IDs or slate names.
  if:
    jsonMatches:
      type: object
      required: [systemPrompt, fields]
      properties:
        systemPrompt: { type: string, minLength: 10 }
        fields: { type: array, minItems: 1 }
        nodes: { type: integer, minimum: 1, maximum: 5 }
    then: continue
    else: abort

The if: jsonMatches gate self-validates the emitted config before the dynamic step loads it. If the planner's output doesn't match the schema, the ladder aborts (or fires else:).

Validation against the manifest: The runtime validates that every field reference in the generated config resolves to something in the manifest. If the planner references a step ID that doesn't exist, or a slate that wasn't declared, the dynamic step load fails.