> ## Documentation Index
> Fetch the complete documentation index at: https://daily-docs-pr-4892.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Functions

> Define function calls and handlers in Pipecat Flows.

Functions in Pipecat Flows serve two key purposes:

1. **Process data** by interfacing with external systems and APIs to read or write information
2. **Progress the conversation** by transitioning between nodes in your flow

## How Functions Work

When designing your nodes, clearly define the task in the `task_messages` and reference the available functions. The LLM will use these functions to complete the task and signal when it's ready to move forward.

For example, if your node's job is to collect a user's favorite color:

1. The LLM asks the question
2. The user provides their answer
3. The LLM calls the function with the answer
4. The function processes the data and determines the next node

## Defining a Function

The preferred way to define a function is with a **direct function**: a single async function that is *both* the handler (the code that runs) and the schema (what is advertised to the LLM). Flows auto-derives the function's metadata — name, description, parameter properties (with their descriptions), and which parameters are required — from the function's signature and docstring.

The first parameter is always `flow_manager` (a [`FlowManager`](/api-reference/pipecat-flows/flow-manager)); the function's own parameters follow. Document each parameter in a Google-style docstring.

```python theme={null}
async def record_favorite_color(
    flow_manager: FlowManager,
    color: str,
) -> tuple[str, NodeConfig]:
    """Record the color the user said is their favorite.

    Args:
        color: The user's favorite color.
    """
    print(f"Your favorite color is: {color}")
    return color, create_end_node()

# List the function in a node
node_config = NodeConfig(
    # ...
    functions=[record_favorite_color],
)
```

<Note>
  The direct-function schema generator doesn't yet map `Literal` types to a
  JSON-schema `enum`. Express enum-like constraints in the docstring prose
  instead (e.g. *'Must be one of "red", "green", or "blue"'*). If you need a
  strict `enum` in the schema, use the
  [`FlowsFunctionSchema`](#advanced-defining-a-function-with-flowsfunctionschema)
  pattern.
</Note>

## Return Values

A function can return any JSON-serializable value (string, dict, list, etc.) that gets passed to the LLM. To also specify the next node, return a tuple:

* **Result**: Data provided to the LLM for context in subsequent completions, or `None`. Any JSON-serializable value is accepted.
* **Next Node**: The `NodeConfig` for Flows to transition to next, or `None`.

A function that doesn't need to change conversational state can return `None` for the next node. One that *only* changes conversational state, without doing other work, can return `None` for the result.

## Per-Function Call Options

By default, a function is not cancelled when the user interrupts, and it uses the LLM service's global timeout. To override either, decorate the function with `@flows_tool_options`:

```python theme={null}
from pipecat.flows import flows_tool_options

# This lookup is only useful for the current turn, so cancel it if the user
# interrupts and the conversation moves on.
@flows_tool_options(cancel_on_interruption=True)
async def check_weather(
    flow_manager: FlowManager,
    city: str,
) -> tuple[dict, None]:
    """Look up the current weather for a city.

    Args:
        city: The city to look up.
    """
    return {"weather": await get_weather(city)}, None
```

## Advanced: Defining a Function with `FlowsFunctionSchema`

Direct functions cover most cases. Reach for `FlowsFunctionSchema` when you need explicit control over the schema — for example a strict `enum` constraint or a numeric `minimum`/`maximum` — that a direct function can't yet express.

A `FlowsFunctionSchema` spells out the function's name, description, and parameters by hand, and takes the `handler` that runs when the LLM calls the function:

```python theme={null}
from pipecat.flows import FlowsFunctionSchema

async def record_favorite_color(
    args: FlowArgs, flow_manager: FlowManager
) -> tuple[str, NodeConfig]:
    """Record the color, then set the next node."""
    print(f"Your favorite color is: {args['color']}")
    return args["color"], create_end_node()

record_favorite_color_func = FlowsFunctionSchema(
    name="record_favorite_color",
    description="Record the color the user said is their favorite.",
    properties={
        # A strict enum — the kind of explicit control a direct function can't yet express.
        "color": {"type": "string", "enum": ["red", "green", "blue"]},
    },
    required=["color"],
    handler=record_favorite_color,
)

# List the schema in a node
node_config = NodeConfig(
    # ...
    functions=[record_favorite_color_func],
)
```

The `handler` is required. It receives the LLM-supplied arguments and returns the same [result and next-node values](#return-values) as a direct function. To override its call options, decorate it with `@flows_tool_options`, the same decorator direct functions use.
