Skip to content

Workflow React Hooks

Our React library, @llamaindex/ui, is the recommended way to integrate your UI with a LlamaAgents workflow server and LlamaCloud. It comes pre-installed in any of our templates containing a UI. The library provides both React hooks for custom integrations and standard components.

Our React hooks provide an idiomatic way to observe and interact with your LlamaAgents workflows remotely from a frontend client.

There are 4 hooks you can use:

  1. useWorkflow: Get actions for a specific workflow (create handlers, run to completion).
  2. useHandler: Get state and actions for a single handler (stream events, send events).
  3. useHandlers: List and monitor handlers with optional filtering.
  4. useWorkflows: List all available workflows.

Configure the hooks with a workflow client. Wrap your app with an ApiProvider that points to your deployment:

import { ApiProvider, type ApiClients, createWorkflowsClient } from "@llamaindex/ui";
const deploymentName =
(import.meta as any).env?.VITE_LLAMA_DEPLOY_DEPLOYMENT_NAME || "default";
const clients: ApiClients = {
workflowsClient: createWorkflowsClient({
baseUrl: `/deployments/${deploymentName}`,
}),
};
export function Providers({ children }: { children: React.ReactNode }) {
return <ApiProvider clients={clients}>{children}</ApiProvider>;
}

Use useWorkflows to list all workflows available in the deployment:

import { useWorkflows } from "@llamaindex/ui";
export function WorkflowList() {
const { state, sync } = useWorkflows();
if (state.loading) return <div>Loading…</div>;
return (
<div>
<button onClick={() => sync()}>Refresh</button>
<ul>
{Object.values(state.workflows).map((w) => (
<li key={w.name}>{w.name}</li>
))}
</ul>
</div>
);
}

Start a workflow by name with useWorkflow. Call createHandler with a JSON input payload to get back a handler state immediately.

import { useState } from "react";
import { useWorkflow } from "@llamaindex/ui";
export function CreateHandler() {
const workflow = useWorkflow("stream");
const [handlerId, setHandlerId] = useState<string | null>(null);
async function handleClick() {
const handlerState = await workflow.createHandler({});
setHandlerId(handlerState.handler_id);
}
return (
<div>
<button onClick={handleClick}>Create Handler</button>
{handlerId && <div>Created: {handlerId}</div>}
</div>
);
}

Subscribe to a handler’s live event stream using subscribeToEvents:

import { useEffect, useState } from "react";
import { useWorkflow, useHandler, WorkflowEvent, isStopEvent } from "@llamaindex/ui";
export function StreamEvents() {
const workflow = useWorkflow("stream");
const [handlerId, setHandlerId] = useState<string | null>(null);
const handler = useHandler(handlerId);
const [events, setEvents] = useState<WorkflowEvent[]>([]);
async function start() {
setEvents([]);
const h = await workflow.createHandler({});
setHandlerId(h.handler_id);
}
useEffect(() => {
if (!handlerId) return;
const sub = handler.subscribeToEvents({
onData: (event) => setEvents((prev) => [...prev, event]),
});
return () => sub.unsubscribe();
}, [handlerId]);
const stop = events.find(isStopEvent);
return (
<div>
<button onClick={start}>Start & Stream</button>
{handlerId && <div>Status: {handler.state.status}</div>}
{stop && <pre>{JSON.stringify(stop.data, null, 2)}</pre>}
{!stop && events.length > 0 && <div>{events.length} events received</div>}
</div>
);
}

Use useHandlers to query and monitor a filtered list of workflow handlers. This is useful for progress indicators or “Recent runs” views.

import { useHandlers } from "@llamaindex/ui";
export function RecentRuns() {
const { state, sync } = useHandlers({
query: { status: ["running", "completed"] },
});
if (state.loading) return <div>Loading…</div>;
const handlers = Object.values(state.handlers);
return (
<div>
<button onClick={() => sync()}>Refresh</button>
<ul>
{handlers.map((h) => (
<li key={h.handler_id}>
{h.handler_id.slice(0, 8)}… — {h.status}
</li>
))}
</ul>
</div>
);
}

The sync option controls whether to fetch handlers on mount. Call sync() manually to refresh the list from the server at any time.

HookPurposeKey Methods/Properties
useWorkflow(name)Work with a specific workflowcreateHandler(input), runToCompletion(input), state.graph
useHandler(handlerId)Work with a specific handlersendEvent(event), subscribeToEvents(callbacks), sync(), state.status, state.result
useHandlers({ query, sync })List/filter handlerssync(), setHandler(h), actions(id), state.handlers
useWorkflows({ sync })List all workflowssync(), state.workflows