Symphonix Documentation · Core 0.61.0

Developer reference

What a flow may contain, what the engine exports, what a package and a collection are on disk, and what an agent tells a board — each rendered from the file the code is held to.

Why this page is short

Every reference document on this site is rendered from the single file the product's own tests hold, not retyped for the web. So there is no second description of a node type here to drift out of agreement with the first one. This page says what each document answers and which to open; the documents themselves are the reference.

The only content below is the version matrix, and that is derived from the compiler's own constants at build time for the same reason.

The reference documents#

Which document answers which question#

What you needWhere it is
Every node type, and what each one's fields meanThe DSL reference — one section per node type, each with the version it arrived in
Channels: the types, the reducers, what a view isThe DSL reference, under state
Edges: plain, conditional, routes, limitsThe DSL reference; and Writing a flow for the reasoning
MCP declarations — requires.mcpThe DSL reference, from 0.23; and Build your first MCP agent for how it is used
What the engine exports, and what it throwsThe API reference
What a solution package may contain, and the gates into the libraryThe solution package format
What a knowledge collection is on diskThe collection format
What an agent tells a board, and what a board may tell an agentThe monitoring protocol
What a generated project containsDeploy and monitor, and Deployment

The vocabulary every document assumes#

Four words, and one rule about numbers. Having these straight makes the rest of the reference read easily; not having them straight is where most confusion starts.

Channels#

A flow's state is a set of named channels, declared with a type and a reducer. The types are string, number, boolean, list, object, any and file. The built-in reducers are replace, append and merge; anything else is looked up in the registry.

A node writes to the channel named in its output, and the reducer decides what writing means — replace overwrites, append adds to a list, merge folds into an object. Which matters most in a fan-out, where several copies of the same node write at once.

Nodes#

Fourteen kinds: handler, llm, tool, tools, fanout, ask, form, read, flow, agent, work, knowledge, index and database. That is the whole list, and there is no planner among them — Plan and Execute is composition.

Edges#

A plain edge goes from one node to the next. A conditional edge reads a channel and chooses, with routes mapping a value to a target and limits capping how many times a route may be taken — which is how a loop goes round and how it stops.

A route that reaches an MCP server is decided by a model, not by generated code

A conditional edge's router is generated JavaScript, and a model asked to write JavaScript that reads what somebody meant writes a list of regular expressions. One had seventeen patterns, matched “add customer” and not “add cust”, and sent the question to the wrong half of an agent — where a second model answered it from the wrong half's data, with nothing in the flow saying anything was wrong.

So where a route leads to an MCP server, an llm node classifies into a channel and the edge routes on that channel. Edges that only choose between ordinary handlers are unaffected.

Requirements#

requires is what the flow needs from whatever deploys it, and the division inside it is deliberate. services and settings carry prose. packages names npm dependencies. mcp is the one that is declared rather than described: the server's name and the tools this flow may call, and nothing about transport, address, command or credential, which are the deployment's.

All three arrive on the same object at run time, so a name may not be two of them at once — a handler reading services.crm has to know which was meant.

Error handling#

What the engine throws#

ClassThrown when
LGFlowErrorThe base. Everything below extends it, so one catch can hold them all.
LGFlowValidationErrorA flow is not a valid flow. Carries the problems, each with the path in the document it is about.
LGFlowRoutingErrorA route could not be taken — no matching target, or a limit reached.
LGFlowAgentErrorA run failed inside the graph.
LGFlowTriggerErrorA trigger could not start or could not run.
These are the exported class names, and the pages here use them unchanged

They are identifiers in the engine's public API, so renaming them in prose would give you code that does not compile. Where this site's own pages talk about the product they use its product names; where a reference document names a type you will catch, it names it exactly. The API reference opens with the same note.

What a flow can say about failure#

Declared on a nodeWhat it doesFrom
retryTry the node again before giving up.0.3
onErrorName the node a failure routes to, or END.0.3
onError: "SKIP"Carry on past the failed node rather than routing anywhere. The word is reserved, so an older flow with a node actually called SKIP still means what it meant.0.32

How a failure is categorised at run time#

Separately from the class, every failure is filed under one of these, and the category goes on the journal entry and the run's exit event:

llm · tool · timeout · agent · delegation · validation · trigger · runtime · unknown

From the error's class, its code, and which call it came out of — never from its message, so the wording can be improved without moving anybody's counts. Deploy and monitor has the reasoning, including why delegation is kept apart from agent.

Version compatibility#

A flow declares a version and gets exactly that version's features. Every version from 0.1 still compiles, and a flow at 0.12 is refused the things 0.13 added rather than being quietly upgraded. So the question this table answers is: what may a flow at version N declare? — everything listed at N and every row above it.

From versionWhat a flow may declare from then on
0.2state — channels — the flow's own named state
limits — a cap on how many times a route may be taken
0.3llm — a model call as a node
onError — where a run goes when a node throws
retry — try a node again before giving up
scopedLimits — a limit counted per something rather than per run
0.4tools — a tool as a node
0.5approval — a node that waits for a person to approve
0.6fanout — the same work over every item in a list
0.7describe — prose a node carries about what it is for
0.8ask — a node that asks the person a question
0.9files — file channels, and where their bytes live
remembers — state that carries from turn to turn
packages — npm packages the generated project needs
conversation — the thread, and what persists along it
0.10forms — a node that collects several fields at once
read — fetching a document by address
suggestions — replies offered to the person as buttons
0.11views — how a channel is shown to a person
0.12page — the flow's own stylesheet for its chat
0.13subflow — another flow run as a single step
0.14interactiveSubflow — a subflow that may itself stop for a person
0.15structuredOutput — an llm node declaring the shape of the answer
0.17dynamicFields — a form taking its fields from state
askingForFields — an llm node asking for a form's fields
0.19agent — a node that runs a registered agent chosen at run time
0.20triggers — a schedule, an event or a webhook starting the flow
0.21identity — who the agent is, and being reachable as itself
0.22users — this flow's people must be identified before it answers
0.23mcp — MCP servers, declared by name and tool list
0.24work — the ReAct loop — the model calls the tools itself
0.25shell — the chat page's own frame
0.26colors — the agent's palette
layout — how the chat page is arranged
logo — the agent's mark
who — what the agent says it is
0.27approvalNeeds — what an approval has to have before it can be given
0.28approvalWhy — the reason attached to an approval
0.29approvalExhibits — what an approver is shown alongside the question
0.30knowledge — a knowledge collection the flow answers from
0.31building — building an index from a folder of documents
0.32onErrorSkip — carry on past a failed node instead of routing
0.33database — a database the flow may be asked questions over

All 43 features, grouped by the version that introduced them — read out of the compiler's own FEATURE_VERSIONS when this page was built, not transcribed. The current language version is 0.33.

Three version numbers, on three clocks — never read one for the other

The language version (0.33) says what a flow.json may contain. The monitoring protocol (0.19) says what an agent tells a board. The package version (0.61.0) says what this build is. They move independently, and a test enforces that none is inferred from another.

And never decide a capability from a version number. Capabilities are named precisely so that an older agent's silence is not mistaken for a “no”. Released

The subject guides#

Longer-form than the reference and shorter than a tutorial: one per subject, each rendered from the product's own documentation.

What on this page has been verified

The node kinds, channel types, reducers, error classes and the whole version matrix were read out of the engine's source at build time — NODE_TYPES, CHANNEL_TYPES, BUILT_IN_REDUCERS, src/errors.js and FEATURE_VERSIONS in Core 0.61.0. The failure categories and the three-clocks rule are the engine's own. Nothing on this page restates a node type's fields, because the rendered DSL reference is the one place those are written. Released