> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pipecat.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Nodes & Messages

> Configure Pipecat Flows conversation nodes: role and task messages, respond_immediately, and how nodes shape each step.

Pipecat Flows represents a conversation as a graph where each step is a **node**. A node is the unit of both forms of flow: in a [flow config](/pipecat/flows/flow-configs) it is a keyed entry under `nodes`, and in code it is a `NodeConfig` object. Either way it may contain the following properties:

* `name`: The name of the node; used as a reference to transition to the node. In a config, the node's key under `nodes` *is* its name, so there is no separate field.
* `role_message`: A `str` defining the bot's role/personality. Sent as the LLM's system instruction and persists across transitions until changed. Typically set once in the initial node.
* `task_messages`: A list of message `dicts` defining the current node's objectives.
* `functions`: The tools the node offers. See [Functions](/pipecat/flows/functions).
* `pre_actions`: Actions to execute before LLM inference. Actions run once upon transitioning to a node.
* `post_actions`: Actions to execute after LLM inference. Actions run once after the node's initial LLM inference.
* `context_strategy`: Strategy for updating context during transitions. The default behavior is to append messages to the context.
* `respond_immediately`: Whether to run LLM inference as soon as the node is set. The default is True.

<Info>
  The only required field is `task_messages`, as your bot always needs a prompt
  to advance the conversation.
</Info>

## Messages

The `role_message` sets who the bot is, as a plain string. The `task_messages` say what it should do at this node, as a list of entries with a `role` and `content`, and focus the LLM on the immediate task, such as asking one question:

<Tabs>
  <Tab title="Declarative">
    ```yaml theme={null}
    nodes:
      initial:
        role_message: >
          You are an inquisitive child. Use very simple language. Ask simple
          questions. You must ALWAYS use one of the available functions to progress
          the conversation. Your responses will be converted to audio. Avoid
          outputting special characters and emojis.
        task_messages:
          - role: developer
            content: >-
              Say 'Hello world' and ask what is the user's favorite color.
    ```
  </Tab>

  <Tab title="Programmatic">
    ```python theme={null}
    NodeConfig(
        name="initial",
        role_message="You are an inquisitive child. Use very simple language. Ask simple questions. You must ALWAYS use one of the available functions to progress the conversation. Your responses will be converted to audio. Avoid outputting special characters and emojis.",
        task_messages=[
            {
                "role": "developer",
                "content": "Say 'Hello world' and ask what is the user's favorite color.",
            }
        ],
    )
    ```
  </Tab>
</Tabs>

<Tip>
  In code, nodes can be defined as plain dicts or as `NodeConfig` objects — both
  work identically.
</Tip>

### Placeholders

A `role_message` and a task message's `content` may refer to the manager's state with `{{ key }}` placeholders. `FlowManager` fills them in each time it enters the node, so a value a handler stored earlier in the conversation can appear in a later prompt:

```yaml theme={null}
role_message: You are an order-taking assistant for {{ restaurant_name }}.
```

Placeholders work the same way in both forms, since the manager renders them. See [Placeholders](/pipecat/flows/state-management#placeholders) for dotted paths, escaping, and what happens when a key is missing.

### Cross-Provider Compatibility

Task messages use Pipecat's OpenAI-style message format and are translated for whichever LLM provider you use. The role message is sent as that provider's system instruction.

## Respond Immediately

For each node in the conversation, you can decide whether the LLM should respond immediately upon entering the node (the default behavior) or whether the LLM should wait for the user to speak first before responding. You do this using the `respond_immediately` field.

<Tip>
  `respond_immediately=False` may be particularly useful in the very first node,
  especially in outbound-calling cases where the user has to first answer the
  phone to trigger the conversation.
</Tip>

<Tabs>
  <Tab title="Declarative">
    ```yaml theme={null}
    nodes:
      initial:
        task_messages:
          - role: developer
            content: >-
              Warmly greet the customer and ask how many people are in their party.
              This is your only job for now; if the customer asks for something
              else, politely remind them you can't do it.
        respond_immediately: false
    ```
  </Tab>

  <Tab title="Programmatic">
    ```python theme={null}
    NodeConfig(
        task_messages=[
            {
                "role": "developer",
                "content": "Warmly greet the customer and ask how many people are in their party. This is your only job for now; if the customer asks for something else, politely remind them you can't do it.",
            }
        ],
        respond_immediately=False,
        # ... other fields
    )
    ```
  </Tab>
</Tabs>

<Warning>
  Keep in mind that if you specify `respond_immediately=False`, the user may not
  be aware of the conversational task at hand when entering the node (the bot
  hasn't told them yet). While it's always important to have guardrails in your
  node messages to keep the conversation on topic, letting the user speak first
  makes it even more so.
</Warning>
