# Functions

> Tools the LLM calls at a node, written as direct functions or explicit schemas, and how they choose the next node.

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



A function is a tool the LLM can call at a node. Its handler does work and returns
`[result, nextNode]`:

* `result` is delivered to the LLM as the tool result (any JSON value, or `null`).
* `nextNode` is the `NodeConfig` to move to, `null` to stay on the node and let the LLM respond,
  or `NO_RESPONSE` to stay and **not** respond (the next reply is triggered by the user).

## Schemas [#schemas]

The explicit form is a `FlowsFunctionSchema`, whose handler receives the arguments object and the
flow manager. The [node example](https://polvallverdu.github.io/pipedog/docs/flows/nodes.md) uses it.

## Direct functions [#direct-functions]

A **direct function** is a plain async function whose first parameter is `flowManager`; the other
parameters are the tool's arguments, matched by name. JavaScript has no docstrings or type hints at
runtime, so attach the description and the parameter schemas as properties:

```ts
/**
 * A direct function: the first parameter is the flow manager, the rest are
 * the tool's arguments. Its description and parameter schemas are attached
 * as metadata, since JavaScript has no docstrings or type hints at runtime.
 */
async function bookSlot(fm: FlowManager, day: string, hour: number) {
  fm.state.slot = { day, hour };
  return [{ booked: true }, createAskReasonNode()] as const;
}
Object.assign(bookSlot, {
  description: "Book an appointment slot.",
  parameters: {
    day: { type: "string", description: "Weekday name." },
    hour: { type: "integer", description: "Hour of the day, 0-23." },
  },
});

// Per-tool call options, as a decorator-style wrapper.
const slowLookup = flowsToolOptions({ cancelOnInterruption: false, timeoutSecs: 30 })(
  Object.assign(
    async (fm: FlowManager, query: string) => {
      void fm;
      return [{ matches: [query] }, NO_RESPONSE] as const;
    },
    { description: "Search the records.", parameters: { query: { type: "string" } } },
  ),
);

const node: NodeConfig = {
  taskMessages: [{ role: "developer", content: "Help the caller book a slot." }],
  functions: [bookSlot as any, slowLookup as any],
};
```

`flowsToolOptions` sets per-tool `cancelOnInterruption` (default `false` in Flows) and `timeoutSecs`.

## Global functions [#global-functions]

Tools available at every node go in `globalFunctions` on the `FlowManager`. They are registered once
and offered alongside each node's own functions.

## Errors [#errors]

If a handler throws, the LLM receives an error result and the conversation stays on the current
node. A tool built from a [flow config](https://polvallverdu.github.io/pipedog/docs/flows/flow-configs.md) must return
`[result, TRANSITION_IN_YAML]` (the config chooses the destination); returning a node or a node name
there is an error reported to the LLM.
