Skip to main content
<Trellis> lets Sol or Fable decide the workflow shape from evidence found during the run: authors return declarative agent | sequence | parallel data, and Smithers validates and compiles it into ordinary tasks in the same run. Terra and Luna only execute bounded goals; their schemas can’t delegate. Trellis is experimental and coexists with the fixed <DelegationChain>: use it for open-ended work with runtime-adaptive topology, and keep fixed JSX for known deterministic graphs.
The run must pin the same concurrency value:
Trellis rejects an omitted or mismatched run cap, and rejects requireRerenderOnOutputChange: false, to keep recursive fan-out in one authoritative scheduler pool and ensure outputs trigger the continuation render consuming them.

Props

Spread delegationV2Schemas into createSmithers and pass its outputs: it registers raw author/worker envelopes, validation rows, canonical outcomes, the final row, and reserved question/answer rows. semanticRevision is a caller-owned cache/identity revision: bump it when an agent’s provider, sandbox, ambient commands, or tool policy changes invisibly to the agent fingerprint, so Trellis derives new root/final node IDs instead of reusing stale semantic results.

Exceptional Sol/Fable execution

Direct Sol/Fable implementation is disabled unless criticalExecutionPolicy is set. With a policy, an authored execute node must:
  • request a registered criticality category
  • state the invariant and line sensitivity
  • name workspace-relative paths and expected changed lines
  • identify surrounding delegated work
  • feed its output to an independent review node that is (or feeds) a declared program output, so the next author continuation can’t race it
Independent means a different role backed by a non-overlapping agent or failover chain, beyond merely a different graph node. Trellis derives the allowed reviewer-role matrix from agents: executor and reviewer can’t share an AgentLike object or a non-empty AgentLike.id, and any failover-chain overlap disqualifies that pairing. The validator admits requests only inside the caller’s category, path-prefix, and line ceiling. The compiler binds the canonical grant to the exact invocation, program ID/digest, logical node, role, execute work kind, and the reviewer’s role/outcome node: an ungranted or mismatched Sol/Fable complete becomes runtime_failed/invalid_return. Policy and grant hashes persist in task metadata; changing policy changes the root semantic identity. Phase A ships this as an admission contract only: the runtime doesn’t compare the reported estimate to a real diff or prevent symlink/ambient-shell escapes. Configure an adapter-owned sandbox/tool boundary for those guarantees.

Authority and return types

Every model return is a strict top-level object containing a tagged union: An authored subworkflow can contain Sol, Fable, Terra, or Luna agent nodes inside sequence and parallel containers: Sol/Fable nodes recursively render another author invocation, Terra/Luna nodes render one worker plus one deterministic settlement, and workers can’t smuggle graph structure since subworkflow is absent from their output schema. The runtime never trusts a model’s terminal claim directly: settlement binds it to the trusted assignment’s role, work kind, output contract, and exact acceptance IDs, and every passed or failed criterion must cite a real evidence or artifact ID. Bad coverage, a dangling proof, the wrong work kind, or a contract-specific shape violation becomes parent-visible runtime_failed/invalid_return.

Recursive execution

One logical author invocation proceeds:
  1. Sol/Fable returns complete, blocked, or a proposed subworkflow.
  2. A deterministic validation node receives a bounded raw JSON proposal and rejects unknown fields/tags, bad roles, unresolved/forward references, unsafe parallel writes, invalid critical execution, contract mismatches, and resource-limit violations.
  3. One semantic-repair author turn may correct rejected IR: a structural diff permits changes only at diagnosed fragments and necessarily affected references, so valid nodes, intent, and continuation state can’t be replaced. Rejection never mounts descendants.
  4. Accepted IR compiles inline into the current run and preserves explicit declared-output fan-in.
  5. Every child settles to a canonical outcome; the author receives a bounded, provenance-bearing evidence packet and either finishes or authors the smallest corrective fragment.
This expresses direct delegation, pipelines, fan-out/fan-in, research/POC waves, debate, and review/optimization loops; the loop is the author continuation over settled evidence, rather than a model-authored JavaScript condition. Accepted history is append-only. Physical IDs include runtime/prompt/registry versions, the root assignment, author lineage, generation, semantic program digest, logical ID, and phase: reordering parallel siblings doesn’t change the digest, but changing sequence order or prompt semantics does. Completed rows are replay-safe without treating a mutable logical ID as identity.

Fuel and concurrency

maxTotalAuthorTurns hard-caps all Sol/Fable calls, including semantic repair. After an accepted fragment, remaining turns split deterministically between the parent continuation and immediate nested authors by sorted logical ID; shares are immutable and non-refundable, so unused child fuel burns and siblings can’t race or reset a shared counter. Author tasks get no execution retries (maxSchemaRetries={0}). At the last permitted depth, Sol/Fable may still author Terra/Luna work, but validation blocks another Sol/Fable child from mounting. Trusted task metadata persists the pinned root concurrency, global author-turn cap, generation/depth limits, and each invocation’s immutable allocation and local remainder, so workflow UIs can distinguish selected-run truth from next-launch controls. A root invocation’s remainder isn’t the global remainder once fuel splits into child allocations. An authored parallel.maxConcurrency may add a smaller local cap but can’t exceed the pinned root value. This release rejects nested local caps that Smithers can’t compose faithfully.

Output contracts

Work intent and output shape are separate. The closed registry supports work_product, goal_contract, plan, evaluation, classification, issue_scan, condition, artifact_collection, and evidence_collection; the validator restricts which work kinds may promise each contract, and settlement checks contract-specific cardinality or structured detail. Unfavorable evidence is still a completed result: a failed review, disproven POC, or failed preview is not automatically blocked. Runtime crash, timeout, cancel, invalid return, fuel exhaustion, and invalid subworkflow remain typed separately.

Phase A limitations

  • The nonblocking ask_question broker isn’t wired: prompts say questions are unavailable, and the UI offers no answer control.
  • Task.allowTools isn’t an authority boundary for every adapter: prompt policy can’t stop a shell-capable agent from invoking ambient commands, so configure role agents with a real sandbox/tool policy. The example UI labels this boundary explicitly rather than presenting prompt policy as enforced tool or filesystem isolation.
  • Hierarchical token, USD, and time reservations are not enforced.
  • Only agent | sequence | parallel is authorable; branches, loops, macros, approvals, arbitrary callbacks, child runs, and model-authored schemas are intentionally unavailable.
The repository includes a real custom UI and example workflow documented at trellis.