Fapost\Foundation\Contracts\NodeHandlerInterface.
Identity
type() is the node’s unique identifier, such as send_message. It must be
unique across every registered handler, including those from other extensions.
version() is the handler’s current version; the engine resolves a handler by the
pair (type, version) from an in-memory registry, with no database query on the
hot path.
label() and category() are what the builder shows: the node’s name and the
group it appears under.
Configuration
configSchema() returns the schema the builder uses to validate the node and draw
its form. This is the mechanism that lets an extension be configurable without
shipping any front-end code — see Builder UI extensions.
Execution
execute() receives three things:
It returns a
NodeExecutionResult, built through one of its named constructors:
The handler must be graph-unaware
The engine resolves what comes next from the flow’s edges, using the source node id together with the handle the handler returned. A handler that decides which node runs next has taken a decision that belongs to the flow definition, and the same handler can then no longer be reused in a differently-shaped flow.sourceHandle defaults to 'default'. A node with several outcomes — a branch, a
validation that can fail — returns a different handle per outcome, and the person
building the flow wires each handle where they want it to go.
Writing outside the session
State changes go back throughstateChanges on the result. Mutations that live
outside the session JSON — contact attributes, contact language — are performed by
the handler through the writer it receives on NodeExecutionContext, such as
ContactWriterInterface.