Skip to main content
Human-in-the-loop workflows allow your agents to pause execution and request user input, approval, or manual intervention before continuing. This enables powerful patterns like approval workflows, user confirmations, data collection, and manual oversight of sensitive operations. Cedar’s human-in-the-loop system doesn’t use anything new – it just pieces together existing Cedar concepts (workflows like this can be created from scratch!)
This feature is currently only supported with Mastra backends. If interested in support for other providers, please reach out or join our Discord. For example backend code in Mastra, reach out as well!

How it works

This system uses Cedar’s existing architecture patterns:
  1. State Management: Stores workflow data in Cedar state (learn more about this concept)
  2. Response Processors: Handles the suspend/resume logic (learn more about this concept)
  3. Message Renderers: Creates the interactive UI (learn more about this concept)
  4. Input subscriptions (optionally): Sends workflow states to the backend with future messages (learn more about this concept).
Human-in-the-loop workflows work by:
  1. Backend suspends workflow - Your agent reaches a point requiring user input and returns a humanInTheLoop response
  2. Cedar processes suspension - The response processor stores workflow data and creates an interactive message
  3. User interacts - The UI displays workflow information with customizable UI that allows the user to provide the necessary data/input
  4. Workflow resumes - User input is sent to the backend to continue the suspended workflow

Backend Response Handling

Response Type

Your backend should return responses with type: "humanInTheLoop" when a workflow needs to be suspended:

Example Backend Response

Built-in Response Processor

Cedar automatically processes humanInTheLoop responses with the built-in processor:
If you want to override the logic of how human in the loop messages are handled, create a new response processor that handles this type of object response from the backend. You can work off of our implementation in packages/cedar-os/src/store/agentConnection/responseProcessors/humanInTheLoopResponseProcessor.ts

Storing workflow suspension data on the frontend

The preconfigured response processor stores all workflow suspension data in a single state key called 'humanInTheLoop'. Each workflow is stored by its runId with complete lifecycle information:

Custom State Setters

The response processor also registers custom setters on the humanInTheLoop state that handle workflow operations:
  • resume: Resumes a suspended workflow by sending the resume request to the backend and updating the workflow state
  • cancel: Cancels a suspended workflow and updates the state to cancelled
These setters are used internally when building the resumeCallback and cancelCallback functions that get passed to message renderers. You can also access them directly if you want to resume a workflow from somewhere else in the UI:

Message Rendering and User Input

Message Type

When a workflow is suspended, the built in response processor creates messages using the HumanInTheLoopMessage type:
This message is added to the chat the same way any other message is, so when rendering it, you can create custom UI for how to gather user input and when to call the callbacks given (see below for an example). We do register a custom message renderer for this, but you will likely need to override it since the data you’ll gather from the user is application specific. You can work off of the existing message renderer available here: packages/cedar-os/src/store/messages/renderers/HumanInTheLoopRenderer.tsx

Backend Integration

Required Routes

Your backend must implement a resume endpoint to handle workflow continuation:

Resume Endpoint (POST /chat/resume)

Default endpoint: /chat/resume or /chat/resume/stream (configurable via resumePath in provider config) Request format:
Response: Continue with normal chat response format

Provider Configuration

Configure the resume endpoint in your Cedar provider config:

Nested Workflows

Support complex workflows with hierarchical step paths:

Advanced Usage

State Subscriptions

Extract workflow states directly from Cedar state to display in the frontend:

Cross-Message Workflow Data

If you want the user to be able to resume a workflow by just typing a response, you should subscribe the stored humanInTheLoop state to the additionalContext. This means that at the next call to the backend, we will send that data and you can process it as you wish to implement custom resume logic.

Complete Example: Approval Workflow

Here’s a comprehensive example showing an approval workflow implementation:

1. Provider Configuration

2. Custom Typed Renderer

3. Register Custom Renderer

4. Backend Implementation

Your backend should return suspension responses like:

5. Complete User Flow

  1. User: “Please process the payment to vendor@example.com for $10,000”
  2. Backend: Returns suspension response above
  3. Cedar: Processes response, stores state, creates interactive message
  4. UI: Shows approval form with transaction details
  5. User: Reviews details, adds feedback, clicks “Approve”
  6. Cedar: Calls resume endpoint with approval data
  7. Backend: Continues workflow, processes payment, returns completion
  8. UI: Shows success message with approval details

6. Dashboard to show all in-process workflows (Optional)

This complete example demonstrates how Cedar’s human-in-the-loop system provides type-safe, customizable workflow management with minimal boilerplate while maintaining full integration with Cedar’s existing architecture.