What is a Node?
In the conceptual graph, a Node is a vertex that performs three key actions:- Receive: Accept incoming events like user audio, text, or system triggers.
- Process: Execute custom Python code, business logic, or AI inference.
- Send: Emit new events to pass control to the rest of the graph.
Abstracted Nodes
To help you get started quickly, we have abstracted two common node patterns for you. You can use these out of the box or build your own custom nodes from scratch.1. The Base Node (Node)
The Node class is the raw primitive. It gives you full control but assumes nothing. It is perfect for deterministic logic, API calls, or routing decisions.
Key Features:
- Raw Event Access: You get the raw event and decide exactly what to do with it.
- No Overhead: No LLM context or streaming logic unless you build it.
process_event() to handle incoming events.
2. The Output Agent (OutputAgentNode)
This is the most common node type. It is a full-featured conversational agent designed to interact with Large Language Models (LLMs).
Key Features:
- Auto-Interruption: Automatically handles user interruptions during playback only when the user is speaking.
- Streaming: Manages the complexity of streaming LLM tokens to the user in real-time.
- Context Management: Maintains conversation history automatically.
generate_response() as an async generator that yields text chunks.
How to Write a Custom Node
1
Inherit from Node
Create a new class that inherits from
Node (or OutputAgentNode).2
Override process_event
Implement the
process_event async method. This is your logic handler.3
Propagate Events
Crucial: You must manually send events if you want the flow to continue.
Custom Node Examples
Best Practices
Name your nodes descriptively
Name your nodes descriptively
Use clear, unique names for debugging. This name shows up in your logs.
Keep nodes simple
Keep nodes simple
One node, one responsibility. If you need to filter AND log AND route, chain three small nodes together instead of building one complex node. This makes testing much easier.
Always propagate events
Always propagate events
Unless you are intentionally building a filter that drops events, always remember to call
await self.send_event(event) at the end of your logic.Handle errors gracefully
Handle errors gracefully
Don’t let exceptions break the event chain.

