diff --git a/api-reference/pipecat-flows/flow-manager.mdx b/api-reference/pipecat-flows/flow-manager.mdx
index 3e9b5827..e32ed13e 100644
--- a/api-reference/pipecat-flows/flow-manager.mdx
+++ b/api-reference/pipecat-flows/flow-manager.mdx
@@ -187,7 +187,7 @@ messages = flow_manager.get_current_context()
flow_manager.register_action(action_type: str, handler: Callable) -> None
```
-Register a handler for a custom action type. The handler can be either a legacy handler `(action)` or a modern handler `(action, flow_manager)`.
+Register a handler for a custom action type. The handler can be either a modern handler `(action, flow_manager)` or a legacy handler `(action)`. Legacy single-argument handlers are deprecated and will be removed in 2.0.0.
| Parameter | Type | Description |
| ------------- | ---------- | ---------------------------------------------------------- |
diff --git a/api-reference/pipecat-flows/types.mdx b/api-reference/pipecat-flows/types.mdx
index 0e933cc2..045ad3d3 100644
--- a/api-reference/pipecat-flows/types.mdx
+++ b/api-reference/pipecat-flows/types.mdx
@@ -119,10 +119,12 @@ Dataclass for defining function call schemas with Flows-specific properties. Pro
- Function handler to process the function call. Can be a legacy handler
- `(args)` or modern handler `(args, flow_manager)`. The handler should return a
- [`FlowResult`](#flowresult) or a
- [`ConsolidatedFunctionResult`](#consolidatedfunctionresult) tuple.
+ Function handler to process the function call. Can be a modern handler
+ `(args, flow_manager)`, legacy handler `(args)`, or zero-arg handler `()`.
+ Legacy and zero-arg handlers are deprecated. The handler returns any
+ JSON-serializable value, or a
+ [`ConsolidatedFunctionResult`](#consolidatedfunctionresult) tuple to also
+ specify the next node.
@@ -317,26 +319,31 @@ node_config: NodeConfig = {
## FlowsDirectFunction
-Protocol defining the interface for direct functions. Any async callable matching this signature can be used as a direct function in node configurations.
+Type alias for direct functions with automatic metadata extraction. Any async callable matching this signature can be used as a direct function in node configurations.
```python
-class FlowsDirectFunction(Protocol):
- def __call__(
- self, flow_manager: FlowManager, **kwargs: Any
- ) -> Awaitable[ConsolidatedFunctionResult]: ...
+FlowsDirectFunction = Callable[..., Awaitable[ConsolidatedFunctionResult]]
```
+Direct functions must accept `flow_manager: FlowManager` as the first parameter, followed by any named parameters described in the function's docstring. Python's `Protocol` system cannot express "any concrete named-parameter list", so this is defined as a generic `Callable`. Runtime validation is handled by `FlowsDirectFunctionWrapper.validate_function`.
+
## Type Aliases
### FlowResult
+
+ **Deprecated.** `FlowResult` is no longer required by any handler type and
+ will be removed in 2.0.0. Function handlers can return any JSON-serializable
+ value. Define your own `TypedDict` if you want a structured result.
+
+
```python
class FlowResult(TypedDict, total=False):
status: str
error: str
```
-Base return type for function results. The `status` field indicates the outcome. The optional `error` field contains an error message if execution failed. Additional fields are allowed and passed through to the LLM.
+Optional convention TypedDict for `status`/`error` results. The `status` field indicates the outcome. The optional `error` field contains an error message if execution failed. Additional fields are allowed and passed through to the LLM.
### FlowArgs
@@ -344,35 +351,69 @@ Base return type for function results. The `status` field indicates the outcome.
FlowArgs = dict[str, Any]
```
-Type alias for function handler arguments. Contains the parameters extracted from the LLM's function call.
+Type alias for function handler arguments. Contains the parameters extracted from the LLM's function call. Each invocation gets its own dict, so handlers may mutate it freely.
+
+
+ In 2.0.0, this alias is planned to widen to `Mapping[str, Any]` to align with
+ Pipecat's typing. Handlers that only read args will be unaffected; handlers
+ that mutate args will need to keep the annotation as `dict[str, Any]`
+ explicitly.
+
### ConsolidatedFunctionResult
```python
-ConsolidatedFunctionResult = tuple[FlowResult | None, NodeConfig | None]
+ConsolidatedFunctionResult = tuple[Any, NodeConfig | None]
```
Return type for consolidated function handlers that both do work and specify the next node:
-- First element: The function result (or `None` for transition-only functions)
+- First element: Any JSON-serializable value (or `None` for transition-only functions)
- Second element: The next node as a `NodeConfig`, or `None` for node functions
### FlowFunctionHandler
```python
-FlowFunctionHandler = Callable[
- [FlowArgs, FlowManager], Awaitable[FlowResult | ConsolidatedFunctionResult]
-]
+FlowFunctionHandler = Callable[[FlowArgs, FlowManager], Awaitable[Any]]
```
Type for modern function handlers that receive both arguments and the `FlowManager` instance.
+**Args:**
+- `args` (`FlowArgs`): Dictionary of arguments from the function call.
+- `flow_manager` (`FlowManager`): Reference to the FlowManager instance.
+
+**Returns:** Any JSON-serializable value, or a `ConsolidatedFunctionResult` tuple to also specify the next node.
+
+### ZeroArgFunctionHandler
+
+
+ **Deprecated.** Zero-argument function handlers are deprecated and will be
+ removed in 2.0.0. Update handlers to accept `(args, flow_manager)` instead.
+
+
+```python
+ZeroArgFunctionHandler = Callable[[], Awaitable[Any]]
+```
+
+Type for function handlers that take no arguments. The flow manager detects the signature automatically and emits a `DeprecationWarning`.
+
+**Returns:** Any JSON-serializable value, or a `ConsolidatedFunctionResult` tuple to also specify the next node.
+
### LegacyFunctionHandler
+
+ **Deprecated.** Single-argument function handlers are deprecated and will be
+ removed in 2.0.0. Update handlers to accept `(args, flow_manager)` instead.
+
+
```python
-LegacyFunctionHandler = Callable[
- [FlowArgs], Awaitable[FlowResult | ConsolidatedFunctionResult]
-]
+LegacyFunctionHandler = Callable[[FlowArgs], Awaitable[Any]]
```
-Type for legacy function handlers that only receive arguments. Both legacy and modern handlers are supported; the flow manager detects the signature automatically.
+Type for legacy function handlers that only receive arguments. Both legacy and modern handlers are supported; the flow manager detects the signature automatically and emits a `DeprecationWarning`.
+
+**Args:**
+- `args` (`FlowArgs`): Dictionary of arguments from the function call.
+
+**Returns:** Any JSON-serializable value, or a `ConsolidatedFunctionResult` tuple to also specify the next node.
diff --git a/pipecat-flows/guides/actions.mdx b/pipecat-flows/guides/actions.mdx
index de86ada8..789d5a60 100644
--- a/pipecat-flows/guides/actions.mdx
+++ b/pipecat-flows/guides/actions.mdx
@@ -67,7 +67,12 @@ async def notify_slack(action: dict, flow_manager: FlowManager):
flow_manager.register_action("notify_slack", notify_slack)
```
-Then use it in your node configuration:
+
+ Action handlers should accept `(action, flow_manager)`. Single-argument
+ handlers `(action)` are deprecated and will be removed in 2.0.0.
+
+
+Once registered, use it in your node configuration:
```python
"pre_actions": [
diff --git a/pipecat-flows/guides/functions.mdx b/pipecat-flows/guides/functions.mdx
index 7e82c1d1..37fb4710 100644
--- a/pipecat-flows/guides/functions.mdx
+++ b/pipecat-flows/guides/functions.mdx
@@ -54,9 +54,9 @@ async def record_favorite_color_and_set_next_node(
## Handler Return Values
-Function handlers return a tuple containing:
+Function handlers 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`. This can be any serializable value — a string, dict, etc.
+- **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`
Some handlers may not want to transition conversational state, in which case you can return `None` for the next node. Other handlers may _only_ want to transition conversational state without doing other work, in which case you can return `None` for the result.
@@ -69,7 +69,7 @@ For more concise code, you can optionally use Direct Functions where the functio
async def record_favorite_color(
flow_manager: FlowManager,
color: str
-) -> tuple[FlowResult, NodeConfig]:
+) -> tuple[str, NodeConfig]:
"""Record the color the user said is their favorite.
Args:
@@ -95,12 +95,12 @@ from pipecat_flows import flows_direct_function
async def long_running_lookup(
flow_manager: FlowManager,
order_id: str
-) -> tuple[FlowResult, NodeConfig]:
+) -> tuple[dict, NodeConfig]:
"""Look up an order that should not be cancelled if the user speaks.
Args:
order_id: The order ID to look up.
"""
order = await db.get_order(order_id)
- return {"status": "success"}, create_order_node(order)
+ return {"status": "success", "order": order}, create_order_node(order)
```