# Nodes

> A node is one step of a flow, with a role, task messages, functions and actions.

Source: https://polvallverdu.github.io/pipedog/docs/flows/nodes/



A node is a `NodeConfig`:

| Field                        | Meaning                                                                                                              |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `taskMessages`               | Required. What the LLM should do at this node, as messages (usually `role: "developer"`).                            |
| `name`                       | Optional. Shown in logs and used as `flowManager.currentNode`; generated if omitted.                                 |
| `roleMessage`                | The bot's role or personality. Sent as the LLM's system instruction and kept across nodes until a node sets another. |
| `functions`                  | Tools the LLM may call at this node, in addition to the manager's global functions.                                  |
| `preActions` / `postActions` | [Actions](https://polvallverdu.github.io/pipedog/docs/flows/actions.md) before and after the LLM's response.                                                  |
| `contextStrategy`            | How [the conversation history](https://polvallverdu.github.io/pipedog/docs/flows/context-strategies.md) changes on entering the node.                         |
| `respondImmediately`         | Whether the LLM answers as soon as the node is entered. Defaults to `true`; set `false` to wait for the user.        |

```ts
function createGreetingNode(): NodeConfig {
  return {
    name: "greeting",
    roleMessage: "You are a friendly receptionist at a dental clinic. Speak briefly.",
    taskMessages: [{ role: "developer", content: "Greet the caller and ask for their name." }],
    functions: [
      new FlowsFunctionSchema({
        name: "record_name",
        description: "Record the caller's name.",
        properties: { name: { type: "string", description: "The caller's name." } },
        required: ["name"],
        // Handlers receive (args, flowManager) and return [result, nextNode].
        handler: async (args, fm) => {
          fm.state.name = args.name;
          return [{ status: "ok" }, createAskReasonNode()];
        },
      }),
    ],
  };
}

function createAskReasonNode(): NodeConfig {
  return {
    name: "ask_reason",
    taskMessages: [{ role: "developer", content: "Ask why they are calling." }],
  };
}

await flowManager.initialize(createGreetingNode());
```

## Role and task messages [#role-and-task-messages]

Keep the persona in `roleMessage` (set once, usually on the first node) and the step's job in
`taskMessages`. A node's task messages are what makes the LLM stay on one topic: say what to do,
what to collect, and when to call the node's functions.

Only the functions of the **current** node (plus global functions) are offered to the LLM. Entering
a node replaces the tool set.

## Entering a node [#entering-a-node]

`flowManager.initialize(node)` enters the first node. A function enters the next one by returning
it. You can also enter a node yourself with `flowManager.setNodeFromConfig(node)`, for example from
an event handler. On entry the manager runs the node's pre-actions, applies the context strategy,
registers the node's functions, asks the LLM to respond (unless `respondImmediately` is `false`),
and finally runs the post-actions.

`flowManager.currentNode` is the name of the active node.
