flow.yaml, the one tool it calls lives in handlers.py, and bot.py loads the config and joins the two.
Hello World Example
View the full source code on GitHub
Prerequisites
Pipecat Flows is included with Pipecat. Install Pipecat with the services used in this example:The Flow
flow.yaml is the whole graph: two nodes, one tool, and the transition between them.
flow.yaml
initial_nodenames the node the conversation starts in.nodesholds the flow’s nodes, keyed by name. The key is the node’s name, soinitialandendare whattransition_torefers to.role_messagesets the bot’s personality. It is sent as the LLM’s system instruction and persists across transitions until another node sets its own.task_messagessay what the LLM should do at this node.functionslists the tools the node offers. Here, one entry namesrecord_favorite_colorand says that when it completes, the conversation moves to theendnode.post_actionsrun after the LLM responds.end_conversationgracefully terminates the call.
record_favorite_color. Those come from the Python.
The Handler
handlers.py holds the Python the config names.
handlers.py
record_favorite_color is a direct function: its first parameter is flow_manager, the rest — here, color — become the tool’s parameters, and Flows derives the schema the LLM sees from the signature and the Google-style docstring.
It returns a tuple of (result, TRANSITION_IN_YAML). The result is given to the LLM as context. TRANSITION_IN_YAML says the handler is not choosing where the conversation goes — the config’s transition_to decides that. Keeping transitions out of the Python is what lets the graph change without touching code.
The Bot
bot.py is a standard Pipecat pipeline plus four lines of Flows wiring:
bot.py
FlowConfig.from_filereads and validates the YAML.Flow(config, handlers=handlers)joins the config to the module holding the Python it names.handlershere is the imported module; a mapping of names to callables, or a list of modules, works too.global_functions=flow.global_functionspasses along the tools the config makes available at every node. This flow has none, so the list is empty, but wiring it up now means adding one later is a config-only change.initialize(flow.initial_node)starts the conversation in the node the config named.
The Same Flow in Code
The same bot, written as a programmatic flow, is inexamples/flows/python/hello_world.py. Read the two side by side to see what moves between the config and the Python.
Next Steps
Flow Configs
The full config format, loading, and validation
Functions
Node functions, edge functions, and branch tables
Examples
Explore more complex examples
API Reference
Complete technical reference