> ## Documentation Index
> Fetch the complete documentation index at: https://docs.experio.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent Flows

> Build node-based agent workflows that compile to LangGraph and run with human-in-the-loop approvals

## Overview

Agent Flows let you compose typed **nodes** into a flow on a visual canvas. When you publish a flow, Experio compiles it to a LangGraph graph and runs it — orchestrating LLM calls, knowledge graph queries, MCP tools, document generation, and human approvals as a single pipeline. A flow can run on its own from the canvas, or be enabled as a **sub-agent** that the chat agent launches on a user's behalf.

Navigate to **Admin > AI & Agents > Agent Flows**.

<Note>
  Agent Flows are distinct from [Flows](/admin-guide/flows), which orchestrate data-processing jobs (reader, ingestion, enrichment). Agent Flows orchestrate AI **agent** behavior and compile to LangGraph.
</Note>

## The Flows List

The Agent Flows page lists every flow with its name, description, tags, and latest published version. A **Sub-agent** badge column shows whether a flow is exposed to the chat agent, and a filter above the list switches between **All flows** and **Sub-agent enabled**. From here you can:

* **Create** a new empty flow (give it a name — the system handles the internal id)
* **Open** a flow to edit it on the canvas
* **Duplicate a template** into a new draft (see [Templates](#templates))
* **Delete** a flow

## Building a Flow

Opening a flow shows the **canvas editor**. You build a flow by dragging nodes from the **palette** onto the canvas. Nodes are compact cards — they don't show input/output ports on the canvas. To **connect** two nodes, drag from one node onto another; the canvas auto-wires their compatible ports. Edges float between nodes and re-route automatically as you move nodes around.

The flow **name** is editable inline at the top of the editor. A collapsible right-hand pane holds the support panels; it re-opens automatically when you click a node:

* **Inspect** — configure the selected node (its config fields, input bindings, and budget), or the selected edge's routing. Each node also takes an optional **Display name** — the human-readable step name end users see in the chat progress view while the flow runs (it falls back to the node's label or id)
* **Run** — start and watch a run (see [Running a Flow](#running-a-flow))
* **Versions** — review prior published versions and control which one is **Live** (see [Publishing and Versioning](#publishing-and-versioning))

### Bindings

Each node has typed **input** and **output** ports under the hood. Connecting two nodes auto-wires their compatible ports; to send one specific value, drag from a node's output port to a target input in the Inspect panel. A binding path looks like `$.nodes.<node_id>.outputs.<port>`, and inputs can also bind to run parameters (`$.params.*`), the chat message (`$.params.message`), and uploaded files (`$.files.*`). Bindings are validated when you save — type mismatches and missing required inputs are surfaced inline on the canvas.

### Edit as JSON

The canvas toolbar includes an **Edit as JSON** action. It opens the flow's full definition as JSON, where you can **export** it (copy or download) or **paste an edited definition back**. Applying a pasted definition runs the same server-side validation as the **Validate** button — unparseable or structurally-invalid JSON (missing `nodes`/`edges` arrays) is rejected before it touches the canvas.

### Node palette

| Node                         | Type                  | Description                                                                                                                                    |
| ---------------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| **Start**                    | `control.start`       | Flow entry point; exposes run params and uploaded files.                                                                                       |
| **End**                      | `control.end`         | Flow exit point; collects bound inputs as the flow result.                                                                                     |
| **Condition**                | `control.condition`   | Evaluate a predicate over flow state and route on the result.                                                                                  |
| **Merge**                    | `control.merge`       | Converge conditional branches; outputs the branch that ran.                                                                                    |
| **Map**                      | `control.map`         | Fan a list out over a body node in parallel (one branch per item).                                                                             |
| **Join**                     | `control.join`        | Collect map branch results after every branch settles.                                                                                         |
| **Loop**                     | `control.loop`        | Bounded loop guard; every cycle passes through it.                                                                                             |
| **Knowledge Graph Query**    | `knowledge_graph`     | Scope and retrieve from the knowledge graph. Returns rows in `data` mode, or additionally synthesizes a cited narrative in `report` mode.      |
| **MCP action**               | `mcp.action`          | Run a task with the tools of one MCP server.                                                                                                   |
| **Orchestrator agent**       | `agent.orchestrator`  | Give the agent a goal plus a set of allowed blocks and a budget; the LLM picks the path.                                                       |
| **Knowledge research agent** | `agent.deep_research` | A bounded research agent over the internal knowledge graph + documents (and optionally one MCP server).                                        |
| **Web research agent**       | `agent.web_research`  | A bounded research agent over the live web (Tavily), with cited sources.                                                                       |
| **LLM generate**             | `llm.generate`        | Generate text from a templated prompt plus optional context.                                                                                   |
| **LLM extract**              | `llm.extract`         | Extract structured fields from context against a per-node schema.                                                                              |
| **LLM classify**             | `llm.classify`        | Classify the input into one of the configured categories.                                                                                      |
| **Generate DOCX**            | `data.generate_docx`  | Produce a Word document artifact from structured sections, optionally branded with a registered Document Template.                             |
| **Generate PPTX**            | `data.generate_pptx`  | Produce a PowerPoint presentation artifact (one slide per section), optionally branded with a registered PPTX template.                        |
| **Generate file**            | `data.generate_file`  | Produce a document artifact in a chosen format — Word (`.docx`), PowerPoint (`.pptx`), PDF, or HTML — reusing the agent's existing generators. |
| **Index uploads**            | `data.index_files`    | Parse, chunk, and embed uploaded files so downstream nodes can use them.                                                                       |
| **Human review**             | `human.review`        | Pause the flow for a reviewer; resume when approved or edited.                                                                                 |

<Note>
  The **Knowledge Graph Query** node has an `on_clarify` policy that controls what happens when scope needs clarification: **fail** the node, **pause** for human input (interrupt), or **continue** with empty rows.
</Note>

<Note>
  The **Generate DOCX** and **Generate PPTX** nodes each expose a **Document Template** selector — pick a registered template by name (managed under [Document Templates](/admin-guide/document-templates)) to brand the output. The **Generate file** node adds a **format chooser** (Word, PowerPoint, PDF, or HTML); the template selector is shown only for the `docx` and `pptx` formats. Markdown in generated content (`##` headings, `**bold**`, bullets) is rendered as real Word/PPTX styling instead of literal markers.
</Note>

### Budgets

Agent nodes (orchestrator, knowledge research, web research, MCP action) run a model-driven loop and must be **bounded**. Each exposes a budget — max model calls, max tool calls, max tokens, and max wall-seconds — so a single node can never run unchecked. Unset fields fall back to the node's contract defaults.

## Publishing and Versioning

A flow you are editing is a **draft**. Publishing snapshots the current draft into an immutable **version**:

1. Click **Publish**. The draft is validated first — publishing is blocked if validation reports errors. Validation also checks **MCP action** nodes: an unknown or disabled MCP server, or **Allow writes** enabled on a server that doesn't support writes, blocks publishing; whitelisted write tools that would be stripped because **Allow writes** is off are surfaced as a warning.
2. A new `AgentFlowVersion` is created with an incrementing version number. Published versions are immutable.
3. The flow's **latest published version** pointer advances to the new version.

### The live version

Every run of a flow uses its **live** version — the version the chat agent launches, and the default for a canvas or API run. The **Versions** panel marks the current one with a **Live** badge.

By default a flow **follows the latest published version**: each time you publish, the newest version automatically becomes live. To roll back or hold on an older version, click **Set as live** on any validated version in the panel — this **pins** the live version there, and publishing no longer changes what's live. Click **Follow latest** to clear the pin and return to auto-advancing on publish.

Only a version that passes validation can be set as live. Existing runs always stay on the version they started with; changing the live version only affects **new** runs.

You can review prior versions from the **Versions** panel. Use **Validate** at any time to run save-time validation on the draft without publishing.

## Letting the chat agent run a flow

You don't wire a flow to a dedicated assistant. Instead, you let the **normal chat agent** discover and launch it as a background **sub-agent**:

1. Open the flow and turn on the **Sub-agent** toggle in the editor header. The flow becomes available to the chat agent.
2. Write a clear flow **description** in the editor next to the toggle. The chat agent reads this description to decide **when** to run the flow, so describe what the flow does and the kind of request it handles. A sub-agent flow with no description shows an amber nudge — the agent can't route to a flow it can't recognize.

Once enabled, the chat agent can launch the flow during a normal conversation. When a user asks for something a flow covers — for example, "prepare a response for this RFP" — the agent confirms once ("I can run *RFP Response Pipeline* — proceed?"), then launches the flow **in the background**. The conversation stays fully usable while the flow runs. Users can also launch a sub-agent flow directly from the chat composer's **Launch a flow** menu, which skips the matching step and starts the chosen flow immediately.

The agent maps the user's request onto the flow's parameters automatically (flows read them as `$.params.<name>` / `{{ params.<name> }}`, and `$.params.message` is typically the user's core request forwarded at launch) and binds the conversation's uploaded files to the flow's file slots. If the flow needs a file the user hasn't provided, the agent asks for it instead of launching.

While a sub-agent flow runs, a **live flow-run view** opens in the chat's right-hand panel showing a progress bar with a step counter ("Step X of N"), the currently-running step by its **Display name**, a checklist of steps in the order they execute, produced files, and a **Stop** control; the conversation pulses in the sidebar until the run finishes. Closing the panel leaves a **View progress** control (above the message box) to reopen it, and a finished run leads with the result and files, with the step-by-step run detail under a **Show details** toggle. When the flow finishes, it posts a message into the conversation with the full result and any files it produced — this arrives on its own (no manual refresh). Users can also just ask the agent for the status or results of a flow it launched.

<Note>
  A paused sub-agent run surfaces an **Awaiting review** card in the conversation's live flow-run panel, where the user can approve or reject it (with a comment) without leaving chat; the panel's reopen control turns amber ("Review needed") and the conversation's sidebar row shows an amber review badge until the pause is resolved. The same pending review is also listed in the **Agent Inbox** (**Admin > AI & Agents > Agent Inbox**) for a reviewer to act on. Either path resumes the flow, which then posts its outcome back to the conversation. See [Human-in-the-Loop](#human-in-the-loop-hitl).
</Note>

## Running a Flow

### From the canvas

Use the **run panel** in the editor to start a run with parameters and uploaded files. The run executes in the background — progress, per-node status, and produced artifacts stream back to the panel. The **usage panel** shows per-node model/tool call counts and token usage — including, for **MCP action** nodes, the names of the tools the run actually called, so you can confirm it used the tool you intended.

### From chat

When a flow is **Sub-agent enabled**, the chat agent can launch it during a normal conversation — see [Letting the chat agent run a flow](#letting-the-chat-agent-run-a-flow). The agent confirms, runs the flow in the background, maps the user's request onto the flow's parameters, binds uploaded files to the flow's input slots, and posts the result and any produced files back into the conversation when the run finishes.

## Human-in-the-Loop (HITL)

Flows pause whenever they reach a **Human review** node (or a Knowledge Graph node configured to interrupt on clarification). A paused run waits for a reviewer to **approve** or **reject** (with a comment) before it resumes.

Paused runs surface in the **Agent Inbox** at **Admin > AI & Agents > Agent Inbox**, which lists every run awaiting human input — newest pause first — with the paused node and a click-through to act on it. Runs you start from the canvas also surface their pause in the editor's **Run** panel.

Resuming a run is atomic: two reviewers cannot both resume the same pause.

<Note>
  The review payload shown to a reviewer (and any generated documents) is cleaned of raw `[evidence:…]` citation markers, so reviewers see readable text. Inline citations are still preserved in the assistant's chat answers.
</Note>

## Templates

Experio seeds two starter templates you can duplicate into your own draft:

* **RFP Response Pipeline** — extracts requirements from an uploaded RFP, drafts sections, and produces a formatted response document.
* **Grunley Scope Merge** — merges uploaded scope-of-work documents into a single document.

Duplicate a template from the flows list, then edit and publish your copy.

## REST API

Agent Flows are also available over REST under `/api/agent-flows/` for programmatic use:

| Endpoint                                      | Purpose                                                                                                                                                                                     |
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET/POST /api/agent-flows/`                  | List and create flows (writes are staff-only). Add `?subagent_enabled=true` to list only sub-agent-enabled flows.                                                                           |
| `PATCH /api/agent-flows/{id}/`                | Update flow fields, including `subagent_enabled` and `description` (staff-only)                                                                                                             |
| `POST /api/agent-flows/{id}/publish/`         | Validate and publish the draft as a new version                                                                                                                                             |
| `POST /api/agent-flows/{id}/set-live/`        | Set the live version: body `{"version": <number>}` pins live to a validated version; `{"version": null}` clears the pin so the flow follows the latest published version again (staff-only) |
| `GET /api/agent-flows/{id}/versions/`         | List published versions                                                                                                                                                                     |
| `POST /api/agent-flows/{id}/runs/`            | Start a run (returns immediately; executes in the background)                                                                                                                               |
| `GET /api/agent-flows/runs/`                  | List runs; filter with `?surface=` (e.g. `chat`, `canvas`, `subagent`) and `?channel=<id>`                                                                                                  |
| `GET /api/agent-flows/runs/{run_id}/`         | Poll run status, state, step log, and usage                                                                                                                                                 |
| `POST /api/agent-flows/runs/{run_id}/resume/` | Resume a paused (HITL) run                                                                                                                                                                  |
| `GET /api/agent-flows/pending-hitl/`          | List runs awaiting human input                                                                                                                                                              |
| `GET /api/agent-flows/node-types/`            | Node registry metadata for the canvas palette                                                                                                                                               |

<Note>
  A flow's JSON carries `subagent_enabled` (whether the chat agent can launch it) and its live-version pointers: `live_version` (the pinned version id, or `null` when the flow follows the latest published version) and `live_version_number` (the effective live version number).
</Note>

<Note>
  Reads are available to authenticated users; creating, editing, and publishing flows require staff permissions.
</Note>
