Workflow Nodes¶
A Tryll workflow is a graph of nodes, each responsible for one step of the per-turn loop. Seventeen node types ship in the box; together they cover the common patterns of conversational inference (generation, retrieval, intent classification, instructions, detection, fallback, guardrails, composition, routing).
Every producing node below writes its text output into a named slot on
the turn's shared blackboard, consumed by downstream nodes via input or by
any template's {{slot.<name>}} tag — see
Slots and inter-node value passing.
Nodes are referenced by their NodeType name on the
wire protocol:
| Node | NodeType |
Exit routes | Use for |
|---|---|---|---|
| Generate | Generate |
default |
Language-model inference. The workhorse. |
| Generate and Speak | GenerateAndSpeak |
default |
Fused LLM generation + streaming TTS. |
| Speak | Speak |
default |
TTS-only; voices its input-resolved slot (default: user_message, like every other input-bearing node). |
| Transform | Transform |
default |
Model-free: renders a Mustache template into its own slot. No inference, no wire emission — composition/rewriting glue between other nodes. |
| Instruction | Instruction |
default |
Attach a named instruction slot to the current interaction; rendered by downstream Generate via {{#instructions}} / {{slot.<name>}}. |
| Retrieve | Retrieve |
found, not_found |
Vector search over a static embedded string storage or an experimental named mutable KB. |
| Write to Memory | WriteToMemory |
written, failed |
Experimental upsert into a named mutable KB. Place Retrieve before write in the same turn. |
| Classify Intent | ClassifyIntent |
found, not_found |
Top-1 embedding similarity against a labelled KB; attaches an IntentionComponent for downstream routing. |
| Classify Intent (LLM) | ClassifyIntentLLM |
found, not_found |
Intent classification via the language model's first-token logprobs. |
| Classify Attributes (LLM) | ClassifyAttributesLLM |
default, triggered |
Score several specialist questions about one line in a single batched call; writes one slot per attribute. |
| Intent to Instruction | IntentToInstruction |
default |
Look up the detected intent in a Map string storage and write the matching instruction slot. |
| Tool Call | ToolCall |
tool_called, no_tool_called |
Detect whether the model wants to call an external tool. |
| Canned Response | CannedResponse |
default |
Emit a fixed reply from a string storage without calling the model. |
| Regex Guardrail | RegexGuardrail |
triggered, not_triggered |
Regex-match an input slot (default user_message); branch the graph on pattern hits. |
| Pause | Pause |
default, timeout |
No-op checkpoint; the executor suspends the turn after this node until the client sends ResumeAgentRequest, or until pause_timeout_ms elapses (0 waits forever). |
| Branch | Branch |
then, else |
Model-free conditional routing: tests a turn-local slot or an agent variable and picks then or else. |
| Summarize | Summarize |
default |
Fold ageing turns into a rolling summary that Generate-class nodes render in their system message, so a long conversation stays coherent at a fixed token cost instead of being trimmed away. |
Exit-route legend¶
Every node's reference page lists its named exits. Each exit is a typed
string field on the node's params object (e.g. default_exit,
triggered_exit). An empty string routes the turn to END (the default);
a non-empty string must name another node in the graph. The server rejects
graphs where an exit field names a missing node with error
3003 GraphCompilationFailed.
Common patterns:
- Straight line. Generate →
default→END. Minimal single-turn agent. - Branch on guardrail. Guardrail →
triggered→ CannedResponse →END; Guardrail →not_triggered→ Generate →default→END. - Instruction then generate. Instruction →
default→ Generate. The instruction's text is exposed as{{slot.<name>}}and{{#instructions}}in the Generate node's Mustache template. - Rewrite then retrieve. Transform →
default→ Retrieve (inputset to the Transform node's name) → Generate. See Query rewriting for RAG. - Retrieve then generate. Retrieve →
found→ Generate; Retrieve →not_found→ Generate (same target). Thenot_foundpath is fine — the projection drops to the user message alone. - Tool-call detection. ToolCall →
tool_called→END(client handles the tool); ToolCall →no_tool_called→ Generate. - Intent classification. ClassifyIntent →
found→ IntentToInstruction →default→ Generate; ClassifyIntent →not_found→ Generate (general answer, no instruction override). See How to build an intent-driven NPC. - Refusal fallback. Generate (hidden classification pass,
send=None) →default→ Branch (Contains/Equalson the verdict slot) →then→ CannedResponse →END; Branch →else→ Generate (the real answer) →default→END. Catches a model's own "I can't help with that" or an unsafe verdict without shipping the refusal text verbatim.
Params¶
Every node carries one typed params table, an arm of the NodeParams
FlatBuffers union in nodes.fbs (for example GenerateParams or
RetrieveParams). A NodeDescription is just a name plus those
params; there is no (key, value) parameter list. Each node's reference
page lists the fields of its table, their defaults and ranges, and which
ones are structural. Tool definitions live on ToolCallParams.tools.
On the wire, the union discriminator is 1-based and follows the order of
the NodeParams union (GenerateParams = 1 … SummarizeParams = 16, ClassifyAttributesLLMParams = 17).
Client NodeType enums are 0-based, so a client enum value is one lower
than the wire discriminator for the same node.
Diagnostics¶
When the agent is created with enable_diagnostics = true, every node
contributes to TurnComplete.debug_info. Each node's reference page has a
Diagnostics section listing the keys it records; the payload that holds them —
the envelope, the shared prompt and engine sections, and the rules for when a key is
omitted — is documented in
Turn Diagnostics JSON. See also
agent parameters — diagnostics.
Related¶
- Concept: Workflows, graphs, and nodes
- Agent Parameters — how the graph is carried on the wire.
- Glossary