> ## Documentation Index
> Fetch the complete documentation index at: https://developer.watson-orchestrate.ibm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuring callbacks

Use callbacks to invoke a tool when specific events occur during an agentic workflow. Callbacks are fire-and-forget, the workflow engine invokes the registered tool and ignores its return value. Callbacks are part of the workflow specification and are serialized into the compiled flow JSON. The tools that you register as callbacks must already be deployed in watsonx Orchestrate, since they are not runtime Python callables.

To configure a callback, call the `add_callback()` method on your `Flow` instance. The method creates a `FlowCallback` object, appends it to the workflow specification, and returns `Self` to support method chaining. Call `add_callback()` multiple times to register separate callbacks for different event sets.

<ParamField path="tool" type="string" required>
  The identifier of the deployed tool to invoke when the callback fires. Use one of the following formats:

  * `tool_name`: The tool name only.
  * `tool_name:tool_uuid`: The tool name with a specific instance UUID.
  * `toolkit:tool_name`: The tool scoped to a toolkit.
  * `toolkit:tool_name:tool_uuid`: The toolkit-scoped tool with a specific instance UUID.
</ParamField>

<ParamField path="events" type="List[FlowCallbackEventKind]" required>
  The lifecycle events that trigger this callback. Specify at least one value. For all available values, see [Events reference](#events-reference).
</ParamField>

<ParamField path="batch_interval" type="int">
  The time, in milliseconds, that the engine waits to accumulate events before it dispatches a single batched invocation. If you omit this parameter, the server default applies.
</ParamField>

## Batching rules

The flow engine batches callback events before it invokes the registered tool. The following rules govern how and when the engine dispatches a batch:

* The engine accumulates events for the duration specified by `batch_interval` before it dispatches a single invocation. If you omit `batch_interval`, the server default applies.
* When a blocking event is dispatched, the engine immediately flushes all events that are currently queued for that callback. If the callback tool is registered for both blocking and non-blocking events, the queued non-blocking events are dispatched at flush time regardless of whether the batch timer has elapsed.

## Events reference

The following `FlowCallbackEventKind` members and their wire values are available. Pass any combination to `add_callback(events=[...])`.

<ParamField path="ON_FLOW_START" type="flow:on_flow_start">
  The flow started execution.
</ParamField>

<ParamField path="ON_FLOW_END" type="flow:on_flow_end">
  The flow completed successfully.
</ParamField>

<ParamField path="ON_FLOW_ERROR" type="flow:on_flow_error">
  The flow failed with an error.
</ParamField>

<ParamField path="ON_FLOW_ABORT" type="flow:on_flow_abort">
  An external action aborted the flow instance.
</ParamField>

<ParamField path="ON_FLOW_DELETE" type="flow:on_flow_delete">
  The flow instance was deleted.
</ParamField>

<ParamField path="ON_TASK_WAIT" type="task:on_task_wait">
  A task is waiting for user input (elicitation). The callback payload includes an `elicitation` object that describes the required input.
</ParamField>

<ParamField path="ON_TASK_ERROR" type="task:on_task_error">
  A task failed during execution.
</ParamField>

<ParamField path="ON_TASK_MESSAGE" type="task:on_task_message">
  A task generated a message.
</ParamField>

## Callback event payload

The flow engine calls the registered tool and passes a `FlowCallbackEventsPayload` object as input.

### `FlowCallbackEventsPayload`

<ParamField path="events" type="List[FlowCallbackEventPayload]" required>
  One or more event payloads delivered in this callback invocation.
</ParamField>

### `FlowCallbackEventPayload`

<ParamField path="event" type="EventMetadata" required>
  Metadata that describes the event: its kind, when it occurred, the flow instance it belongs to, and any task or error context.
</ParamField>

<ParamField path="output" type="dict">
  The flow output value. Present only when `state` is `completed`.
</ParamField>

<ParamField path="elicitation" type="ElicitationDetails">
  Details of the pending user input request. Present only when `state` is `input_required`, which corresponds to `ON_TASK_WAIT` events.
</ParamField>

### `EventMetadata`

<ParamField path="id" type="string" required>
  A unique identifier for this event occurrence.
</ParamField>

<ParamField path="kind" type="string" required>
  One of the wire strings listed in the [Events reference](#events-reference).
</ParamField>

<ParamField path="created_at" type="string" required>
  An ISO 8601 timestamp that records when the event occurred.
</ParamField>

<ParamField path="instance_id" type="string" required>
  A unique identifier for the running flow instance that generated this event.
</ParamField>

<ParamField path="flow_name" type="string" required>
  The name of the flow.
</ParamField>

<ParamField path="environment_id" type="string" required>
  The environment where the flow is running, for example `draft` or `live`.
</ParamField>

<ParamField path="state" type="string" required>
  The execution state of the flow when the event fired. Valid values are `working`, `input_required`, `completed`, `failed`, `aborted`, and `deleted`.
</ParamField>

<ParamField path="parent_instance_id" type="string">
  The parent flow instance ID. Present only when this flow is a child flow.
</ParamField>

<ParamField path="parent_flow_name" type="string">
  The parent flow name. Present only when this flow is a child flow.
</ParamField>

<ParamField path="task_id" type="string">
  The task ID. Present only for `ON_TASK_*` events.
</ParamField>

<ParamField path="task_name" type="string">
  The internal task name. Present only for `ON_TASK_*` events.
</ParamField>

<ParamField path="task_display_name" type="string">
  The human-readable task name. Present only for `ON_TASK_*` events.
</ParamField>

<ParamField path="error" type="ErrorDetails">
  Details of the error that caused the flow or task to fail. Present only for `ON_FLOW_ERROR` and `ON_TASK_ERROR` events. Contains `message` (string, required) and `code` (string, optional).
</ParamField>

### `ElicitationDetails`

Present only when `state` is `input_required`.

<ParamField path="mode" type="string" required>
  The elicitation mode. Currently always `"form"`.
</ParamField>

<ParamField path="message" type="string" required>
  A message that describes the input that the user must provide.
</ParamField>

<ParamField path="elicitationId" type="string" required>
  A unique identifier for this elicitation request. The value is the same as `task_id`.
</ParamField>

<ParamField path="requestedSchema" type="dict" required>
  A JSON Schema object that defines the expected structure, types, and validation rules for the user input.
</ParamField>

<ParamField path="meta.assignee" type="string" required>
  The user ID or email address of the user who must provide the input.
</ParamField>

<ParamField path="meta.response_items" type="list" required>
  An array of `ResponseItem` objects, where each object describes one input field. Supported `response_type` values: `text`, `number`, `option`, `date`, `datetime`, `time`, `file_upload`, `file_download`, `object`, and `forms`.
</ParamField>

## Building a compatible callback tool

The flow engine identifies compatible callback tools by matching the tool's input schema against the `FlowCallbackEventsPayload` structure. You can register any of the following tool types as a callback: **Python**, **OpenAPI**, **MCP**, or **Flow**.

<Note>
  When you use a **Flow tool** as a callback, the callback flow must not contain user activity nodes. Callback flows run asynchronously and do not have access to the originating user's chat thread, so the system cannot deliver user interactions inside a callback flow.
</Note>

For more information, see [Flow callback example](https://github.com/IBM/ibm-watsonx-orchestrate-adk/tree/main/examples/flow_builder/flow_callback/README.md).

## `FlowCallback` direct construction

To build a callback object separately before you attach it, construct a `FlowCallback` directly and append it to `aflow.spec.callbacks`. The `FlowCallback` model mirrors the parameters of `add_callback()` exactly.

```python theme={null}
# Import FlowCallback to construct a callback object directly,
# and FlowCallbackEventKind to reference the available lifecycle events.
from ibm_watsonx_orchestrate.flow_builder.types import FlowCallback
from ibm_watsonx_orchestrate.flow_builder.flow_callback_types import FlowCallbackEventKind

# Build a FlowCallback that targets a toolkit-scoped tool identified by name and UUID.
# The callback fires on ON_FLOW_START and ON_FLOW_END, and batches events
# for up to 60 seconds before dispatching a single invocation.
callback = FlowCallback(
    tool="audit_toolkit:audit_logger:xyz-789-ghi-012",
    events=[FlowCallbackEventKind.ON_FLOW_START, FlowCallbackEventKind.ON_FLOW_END],
    batch_interval=60_000  # 1 minute
)

# Attach the callback to the flow by appending it to the spec's callbacks list.
aflow.spec.callbacks.append(callback)
```

<Note>
  `Flow.add_callback()` is the preferred, higher-level API. Use direct `FlowCallback` construction only when you need to manipulate the spec list explicitly.
</Note>

## Example

The following example registers two callbacks on the same flow. The first callback handles flow-level lifecycle events and uses the server default batch interval. The second handles task-level events with a custom 30-second interval.

```py Python [expandable] theme={null}
# BaseModel is used to define strongly typed input and output schemas for the flow.
from pydantic import BaseModel
# Flow is the builder class; flow is the decorator that registers the function as a
# flow definition; START and END are sentinel nodes that mark the flow boundaries.
from ibm_watsonx_orchestrate.flow_builder.flows import Flow, flow, START, END
# FlowCallbackEventKind enumerates all lifecycle events that can trigger a callback.
from ibm_watsonx_orchestrate.flow_builder.flow_callback_types import FlowCallbackEventKind

# my_tool is the deployed tool that this flow executes as its sole task node.
from .my_tool import my_tool


# Define the input schema: the flow accepts a single string field named "message".
class FlowInput(BaseModel):
    message: str


# Define the output schema: the flow returns a single string field named "result".
class FlowOutput(BaseModel):
    result: str


# The @flow decorator registers this function as a named, deployable flow definition.
# input_schema and output_schema enforce the contract for callers of this flow.
@flow(
    name="example_flow_with_callbacks",
    display_name="Example Flow with Callbacks",
    input_schema=FlowInput,
    output_schema=FlowOutput,
)
def build_example_flow_with_callbacks(aflow: Flow) -> Flow:
    # Wrap my_tool as a task node in the flow graph.
    node = aflow.tool(my_tool)
    # Connect START → node → END to form a linear single-step flow.
    aflow.sequence(START, node, END)

    # Register a callback for flow-level lifecycle events.
    # "flow_callback_handler" is a deployed tool that receives these events.
    # No batch_interval is set, so the server default batching window applies.
    aflow.add_callback(
        tool="flow_callback_handler",
        events=[
            FlowCallbackEventKind.ON_FLOW_START,   # fires when the flow begins
            FlowCallbackEventKind.ON_FLOW_END,     # fires when the flow completes successfully
            FlowCallbackEventKind.ON_FLOW_ERROR,   # fires when the flow fails
        ],
    )

    # Register a second callback for task-level events using a toolkit-scoped tool.
    # batch_interval=30_000 means the engine waits up to 30 seconds to accumulate
    # task events before dispatching a single batched invocation.
    aflow.add_callback(
        tool="monitoring_toolkit:task_event_handler",
        events=[
            FlowCallbackEventKind.ON_TASK_WAIT,    # fires when a task awaits user input
            FlowCallbackEventKind.ON_TASK_ERROR,   # fires when a task fails
            FlowCallbackEventKind.ON_TASK_MESSAGE, # fires when a task emits a message
        ],
        batch_interval=30_000,
    )

    return aflow
```

For the full example and complete code, see [Flow callback example](https://github.com/IBM/ibm-watsonx-orchestrate-adk/tree/main/examples/flow_builder/flow_callback/README.md).
