HITL Workflows header

Human-in-the-Loop (HITL) Workflows: Implementing Approval Systems with NeuronAgent

View on GitHub | Download Latest Release | Documentation

Introduction

Autonomous AI agents can execute complex tasks, but some decisions require human judgment. Financial approvals need manager review. Content moderation needs human oversight. Critical operations need validation. Human-in-the-Loop (HITL) workflows solve this by integrating human approval steps into automated agent workflows.

NeuronAgent provides a DAG-based workflow engine with built-in HITL support. Workflows can pause execution, request human approval, wait for decisions, and resume based on approval outcomes. This guide explains HITL workflow architecture, implementation patterns, and real-world examples using NeuronAgent.

What is Human-in-the-Loop (HITL)

HITL workflows combine automated agent execution with human decision points. Agents execute steps autonomously until reaching an approval step. The workflow pauses and requests human review. The human reviews context, makes a decision, and provides feedback. The workflow resumes based on the decision.

HITL workflows solve three problems. Problem one is trust. Some operations are too critical for full automation. Human oversight ensures quality and safety. Problem two is compliance. Regulations require human approval for certain actions. HITL workflows enforce compliance. Problem three is learning. Human feedback improves agent behavior over time.

HITL workflows include five components. Component one is workflow definition that specifies steps and approval points. Component two is approval steps that pause execution and request human input. Component three is notification systems that alert humans when approval is needed. Component four is decision interfaces that present context and collect decisions. Component five is state management that tracks approval status and resumes execution.

Why HITL Matters

HITL workflows enable safe automation. Agents handle routine tasks autonomously. Humans review critical decisions. This balance improves efficiency while maintaining control.

Consider a financial approval workflow. An agent analyzes a purchase request. The agent checks budget availability. The agent verifies compliance rules. For purchases over $10,000, the workflow requires manager approval. The agent pauses execution. The system notifies the manager. The manager reviews the request. The manager approves or rejects. The workflow resumes based on the decision.

Without HITL, agents would either reject all requests or approve all requests. Neither approach works for production systems. HITL enables conditional automation based on human judgment.

HITL Workflow Architecture

NeuronAgent's workflow engine supports HITL through approval steps. Workflows are defined as directed acyclic graphs (DAGs). Steps can be agent steps, tool steps, HTTP steps, conditional steps, or approval steps. Approval steps pause execution and request human input.

HITL Workflow Architecture
Figure: HITL Workflow Architecture

The workflow engine manages execution flow. Steps execute in dependency order. Approval steps pause execution. The engine stores workflow state. The engine resumes execution after approval. The engine handles timeouts and retries.

Workflow Definition

Workflows are defined using JSON or SQL. Each workflow has a name, description, and step definitions. Steps specify type, dependencies, and configuration. Approval steps specify approver roles, timeout settings, and notification channels.

-- Create workflow with approval step
CREATE TABLE workflows (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
description TEXT,
definition JSONB NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Example workflow definition
INSERT INTO workflows (name, description, definition) VALUES (
'content_moderation_workflow',
'Content moderation with human approval',
'{
"steps": [
{
"id": "analyze_content",
"type": "agent",
"agent_id": "content_analyzer",
"input": {"content": "{{workflow.input.content}}"},
"output": "analysis_result"
},
{
"id": "check_threshold",
"type": "conditional",
"condition": "{{analysis_result.risk_score}} > 0.7",
"if_true": "request_approval",
"if_false": "auto_approve"
},
{
"id": "request_approval",
"type": "approval",
"approver_role": "moderator",
"timeout_seconds": 3600,
"notification_channel": "email",
"context": {
"content": "{{workflow.input.content}}",
"analysis": "{{analysis_result}}"
}
},
{
"id": "auto_approve",
"type": "agent",
"agent_id": "content_publisher",
"input": {"content": "{{workflow.input.content}}"}
},
{
"id": "publish_approved",
"type": "agent",
"agent_id": "content_publisher",
"input": {"content": "{{workflow.input.content}}"},
"depends_on": ["request_approval"]
}
]
}'::jsonb
);

The workflow definition includes five steps. Step one analyzes content using an agent. Step two checks if risk score exceeds threshold. Step three requests human approval if threshold exceeded. Step four auto-approves if threshold not exceeded. Step five publishes content after approval.

Approval Step Configuration

Approval steps specify who can approve, how long to wait, and how to notify. Approver roles define permission requirements. Timeout settings prevent indefinite waiting. Notification channels specify how to alert approvers.

-- Approval step configuration
{
"id": "request_approval",
"type": "approval",
"approver_role": "moderator",
"timeout_seconds": 3600,
"notification_channel": "email",
"approval_options": [
{"value": "approve", "label": "Approve Content"},
{"value": "reject", "label": "Reject Content"},
{"value": "request_changes", "label": "Request Changes"}
],
"context": {
"content": "{{workflow.input.content}}",
"analysis": "{{analysis_result}}",
"risk_factors": "{{analysis_result.risk_factors}}"
},
"metadata": {
"workflow_id": "{{workflow.id}}",
"step_id": "request_approval",
"created_at": "{{workflow.created_at}}"
}
}

The approval step configuration specifies moderator role approval, one-hour timeout, email notifications, three decision options, and context for review.

Approval State Machine

Approval steps follow a state machine. States include pending, approved, rejected, expired, and cancelled. Transitions occur based on human decisions or timeouts.

Approval State Machine
Figure: Approval State Machine

The state machine ensures consistent approval handling. Pending state waits for human decision. Approved state allows workflow continuation. Rejected state stops workflow execution. Expired state handles timeout scenarios. Cancelled state handles manual cancellation.

-- Approval states table
CREATE TABLE approval_requests (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
workflow_id UUID REFERENCES workflows(id),
step_id TEXT NOT NULL,
state TEXT NOT NULL DEFAULT 'pending',
approver_id UUID,
decision TEXT,
decision_reason TEXT,
context JSONB,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP
);
-- State transitions
CREATE OR REPLACE FUNCTION update_approval_state()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.state != OLD.state THEN
NEW.updated_at = CURRENT_TIMESTAMP;
-- Handle state transitions
IF NEW.state = 'approved' THEN
-- Resume workflow execution
PERFORM resume_workflow(NEW.workflow_id, NEW.step_id);
ELSIF NEW.state = 'rejected' THEN
-- Stop workflow execution
PERFORM stop_workflow(NEW.workflow_id, 'rejected_by_approver');
ELSIF NEW.state = 'expired' THEN
-- Handle timeout
PERFORM handle_approval_timeout(NEW.workflow_id, NEW.step_id);
END IF;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER approval_state_trigger
BEFORE UPDATE ON approval_requests
FOR EACH ROW
EXECUTE FUNCTION update_approval_state();

The approval states table tracks approval requests. The trigger function handles state transitions. Approved state resumes workflow. Rejected state stops workflow. Expired state handles timeouts.

Workflow Engine Architecture

NeuronAgent's workflow engine executes DAG-based workflows. The engine manages step dependencies, handles approval pauses, and resumes execution after approvals.

Workflow Engine Architecture
Figure: Workflow Engine Architecture

The workflow engine includes five components. Component one is the executor that runs steps in order. Component two is the state manager that tracks workflow state. Component three is the approval handler that manages approval requests. Component four is the notification service that alerts approvers. Component five is the resume manager that continues execution after approval.

-- Workflow execution table
CREATE TABLE workflow_executions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
workflow_id UUID REFERENCES workflows(id),
state TEXT NOT NULL DEFAULT 'running',
current_step_id TEXT,
input_data JSONB,
output_data JSONB,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
completed_at TIMESTAMP
);
-- Workflow step execution table
CREATE TABLE workflow_step_executions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
execution_id UUID REFERENCES workflow_executions(id),
step_id TEXT NOT NULL,
state TEXT NOT NULL DEFAULT 'pending',
input_data JSONB,
output_data JSONB,
error_message TEXT,
started_at TIMESTAMP,
completed_at TIMESTAMP
);
-- Query workflow execution status
SELECT
we.id,
w.name AS workflow_name,
we.state,
we.current_step_id,
wse.step_id,
wse.state AS step_state,
ar.state AS approval_state
FROM workflow_executions we
JOIN workflows w ON we.workflow_id = w.id
LEFT JOIN workflow_step_executions wse ON we.id = wse.execution_id
LEFT JOIN approval_requests ar ON we.id = ar.workflow_id AND wse.step_id = ar.step_id
WHERE we.id = 'workflow-execution-uuid'
ORDER BY wse.started_at;

The workflow execution tables track execution state. The query shows workflow status, current step, and approval state.

Implementation Examples

Example 1: Content Moderation Workflow

A content moderation system uses HITL for high-risk content. The workflow analyzes content, checks risk scores, and requests approval for risky items.

-- Create content moderation workflow
INSERT INTO workflows (name, description, definition) VALUES (
'content_moderation',
'Moderate user-generated content with AI and human review',
'{
"steps": [
{
"id": "analyze_content",
"type": "agent",
"agent_id": "content_analyzer",
"input": {
"content": "{{workflow.input.content}}",
"content_type": "{{workflow.input.content_type}}"
}
},
{
"id": "check_risk",
"type": "conditional",
"condition": "{{analyze_content.risk_score}} >= 0.7",
"if_true": "human_review",
"if_false": "auto_approve"
},
{
"id": "human_review",
"type": "approval",
"approver_role": "content_moderator",
"timeout_seconds": 7200,
"context": {
"content": "{{workflow.input.content}}",
"risk_score": "{{analyze_content.risk_score}}",
"risk_factors": "{{analyze_content.risk_factors}}",
"suggested_action": "{{analyze_content.suggested_action}}"
}
},
{
"id": "auto_approve",
"type": "agent",
"agent_id": "content_publisher",
"input": {"content": "{{workflow.input.content}}"}
},
{
"id": "publish_approved",
"type": "agent",
"agent_id": "content_publisher",
"input": {"content": "{{workflow.input.content}}"},
"depends_on": ["human_review"]
}
]
}'::jsonb
);
-- Execute workflow
INSERT INTO workflow_executions (workflow_id, input_data) VALUES (
(SELECT id FROM workflows WHERE name = 'content_moderation'),
'{
"content": "User submitted content text...",
"content_type": "post",
"user_id": "user-123"
}'::jsonb
) RETURNING id;
-- Check approval status
SELECT
ar.id,
ar.state,
ar.decision,
ar.decision_reason,
ar.created_at,
ar.expires_at,
ar.context->>'risk_score' AS risk_score
FROM approval_requests ar
WHERE ar.workflow_id = 'workflow-execution-uuid'
AND ar.step_id = 'human_review';

The content moderation workflow analyzes content, checks risk scores, and requests human approval for high-risk items. The approval query shows pending approvals with risk scores.

Example 2: Financial Approval Workflow

A financial approval system uses HITL for purchase requests. The workflow validates requests, checks budgets, and requires approval for large purchases.

-- Create financial approval workflow
INSERT INTO workflows (name, description, definition) VALUES (
'purchase_approval',
'Approve purchase requests with budget validation',
'{
"steps": [
{
"id": "validate_request",
"type": "agent",
"agent_id": "request_validator",
"input": {
"request_id": "{{workflow.input.request_id}}",
"amount": "{{workflow.input.amount}}",
"category": "{{workflow.input.category}}"
}
},
{
"id": "check_budget",
"type": "tool",
"tool_name": "sql",
"input": {
"query": "SELECT available_budget FROM budgets WHERE category = $1",
"params": ["{{workflow.input.category}}"]
}
},
{
"id": "check_approval_required",
"type": "conditional",
"condition": "{{workflow.input.amount}} > 10000 OR {{check_budget.available_budget}} < {{workflow.input.amount}}",
"if_true": "manager_approval",
"if_false": "auto_approve"
},
{
"id": "manager_approval",
"type": "approval",
"approver_role": "manager",
"timeout_seconds": 86400,
"approval_options": [
{"value": "approve", "label": "Approve Purchase"},
{"value": "reject", "label": "Reject Purchase"},
{"value": "request_info", "label": "Request More Information"}
],
"context": {
"request_id": "{{workflow.input.request_id}}",
"amount": "{{workflow.input.amount}}",
"category": "{{workflow.input.category}}",
"available_budget": "{{check_budget.available_budget}}",
"validation_result": "{{validate_request.result}}"
}
},
{
"id": "auto_approve",
"type": "agent",
"agent_id": "purchase_processor",
"input": {"request_id": "{{workflow.input.request_id}}"}
},
{
"id": "process_approved",
"type": "agent",
"agent_id": "purchase_processor",
"input": {"request_id": "{{workflow.input.request_id}}"},
"depends_on": ["manager_approval"]
}
]
}'::jsonb
);
-- Execute purchase approval workflow
INSERT INTO workflow_executions (workflow_id, input_data) VALUES (
(SELECT id FROM workflows WHERE name = 'purchase_approval'),
'{
"request_id": "req-456",
"amount": 15000,
"category": "equipment",
"requester_id": "user-789"
}'::jsonb
) RETURNING id;
-- Query pending approvals
SELECT
ar.id AS approval_id,
ar.context->>'request_id' AS request_id,
ar.context->>'amount' AS amount,
ar.context->>'category' AS category,
ar.state,
ar.created_at,
ar.expires_at,
EXTRACT(EPOCH FROM (ar.expires_at - CURRENT_TIMESTAMP)) / 3600 AS hours_remaining
FROM approval_requests ar
WHERE ar.state = 'pending'
AND ar.step_id = 'manager_approval'
ORDER BY ar.created_at DESC;

The financial approval workflow validates requests, checks budgets, and requires manager approval for large purchases or budget overruns.

Example 3: Multi-Level Approval Workflow

Some workflows require multiple approval levels. A document publishing workflow needs editor approval, then manager approval.

-- Create multi-level approval workflow
INSERT INTO workflows (name, description, definition) VALUES (
'document_publishing',
'Publish documents with editor and manager approval',
'{
"steps": [
{
"id": "review_document",
"type": "agent",
"agent_id": "document_reviewer",
"input": {"document_id": "{{workflow.input.document_id}}"}
},
{
"id": "editor_approval",
"type": "approval",
"approver_role": "editor",
"timeout_seconds": 3600,
"context": {
"document_id": "{{workflow.input.document_id}}",
"review_result": "{{review_document.result}}"
}
},
{
"id": "manager_approval",
"type": "approval",
"approver_role": "manager",
"timeout_seconds": 7200,
"depends_on": ["editor_approval"],
"context": {
"document_id": "{{workflow.input.document_id}}",
"editor_decision": "{{editor_approval.decision}}",
"editor_notes": "{{editor_approval.decision_reason}}"
}
},
{
"id": "publish_document",
"type": "agent",
"agent_id": "document_publisher",
"input": {"document_id": "{{workflow.input.document_id}}"},
"depends_on": ["manager_approval"]
}
]
}'::jsonb
);
-- Check multi-level approval status
SELECT
we.id AS execution_id,
wse1.step_id AS step1_id,
wse1.state AS step1_state,
ar1.decision AS step1_decision,
wse2.step_id AS step2_id,
wse2.state AS step2_state,
ar2.decision AS step2_decision
FROM workflow_executions we
JOIN workflow_step_executions wse1 ON we.id = wse1.execution_id AND wse1.step_id = 'editor_approval'
LEFT JOIN approval_requests ar1 ON we.id = ar1.workflow_id AND wse1.step_id = ar1.step_id
LEFT JOIN workflow_step_executions wse2 ON we.id = wse2.execution_id AND wse2.step_id = 'manager_approval'
LEFT JOIN approval_requests ar2 ON we.id = ar2.workflow_id AND wse2.step_id = ar2.step_id
WHERE we.id = 'workflow-execution-uuid';

The multi-level approval workflow requires editor approval first, then manager approval. The query shows approval status at both levels.

Notification Systems

Approval workflows require notification systems. Approvers must be alerted when approval is needed. Notifications include context, deadlines, and action links.

-- Notification system
CREATE TABLE notifications (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
approval_request_id UUID REFERENCES approval_requests(id),
recipient_id UUID NOT NULL,
channel TEXT NOT NULL,
subject TEXT,
message TEXT,
status TEXT DEFAULT 'pending',
sent_at TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Create notification on approval request
CREATE OR REPLACE FUNCTION notify_approver()
RETURNS TRIGGER AS $$
DECLARE
approver_ids UUID[];
BEGIN
-- Get approvers for the role
SELECT array_agg(user_id) INTO approver_ids
FROM user_roles
WHERE role = NEW.approver_role;
-- Create notifications
INSERT INTO notifications (approval_request_id, recipient_id, channel, subject, message)
SELECT
NEW.id,
user_id,
'email',
'Approval Required: ' || NEW.step_id,
'An approval is required for workflow step: ' || NEW.step_id || E'\n\n' ||
'Context: ' || NEW.context::text || E'\n\n' ||
'Deadline: ' || NEW.expires_at::text
FROM unnest(approver_ids) AS user_id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER approval_notification_trigger
AFTER INSERT ON approval_requests
FOR EACH ROW
EXECUTE FUNCTION notify_approver();

The notification system creates email notifications when approval requests are created. Notifications include context and deadlines.

Best Practices

1. Clear Approval Context

Provide sufficient context for approvers. Include relevant data, risk factors, and suggested actions. Context helps approvers make informed decisions quickly.

-- Good approval context
{
"context": {
"request_id": "req-123",
"amount": 15000,
"category": "equipment",
"requester": "John Doe",
"budget_status": "within_budget",
"similar_requests": [
{"id": "req-100", "amount": 12000, "approved": true},
{"id": "req-101", "amount": 18000, "approved": false}
],
"risk_factors": [],
"suggested_action": "approve"
}
}

2. Reasonable Timeouts

Set appropriate timeout values. Too short causes frequent timeouts. Too long delays workflows unnecessarily. Consider urgency and approver availability.

-- Timeout recommendations
-- Urgent: 1 hour (3600 seconds)
-- Normal: 24 hours (86400 seconds)
-- Low priority: 7 days (604800 seconds)

3. Approval Options

Provide clear approval options. Include approve, reject, and request changes. Options should match workflow requirements.

4. State Management

Track approval state accurately. Update state immediately on decision. Handle timeouts gracefully. Log all state transitions for audit.

5. Error Handling

Handle approval failures gracefully. Retry transient failures. Escalate permanent failures. Provide fallback actions.

Real-World Use Cases

Use Case 1: Content Moderation Platform

A content platform processes 10,000 posts daily. AI analyzes all posts. High-risk posts (7% of total) require human approval. Average approval time is 2 hours. 95% of approvals complete within 4 hours.

The workflow reduces human workload by 93% while maintaining quality. AI handles routine moderation. Humans review edge cases. System processes 9,300 posts automatically daily.

Use Case 2: Financial Approval System

A company processes 500 purchase requests weekly. Requests under $10,000 auto-approve. Requests over $10,000 require manager approval. Average approval time is 6 hours. 98% of approvals complete within 24 hours.

The workflow accelerates processing while maintaining control. Routine requests process immediately. Large requests get human review. System maintains compliance automatically.

Use Case 3: Document Publishing Workflow

A documentation team publishes 200 documents monthly. All documents require editor approval. Documents over 5,000 words require manager approval. Average approval time is 4 hours for editors, 8 hours for managers.

The workflow ensures quality while maintaining speed. Editors review all content. Managers review long documents. System tracks approval status automatically.

Conclusion

HITL workflows enable safe automation by integrating human approval into agent workflows. NeuronAgent's workflow engine provides built-in HITL support through approval steps. Workflows pause execution, request human input, and resume based on decisions.

Key benefits include trust through human oversight, compliance through enforced approvals, and learning through human feedback. Implementation requires clear workflow definitions, proper state management, effective notifications, and reasonable timeouts.

Use HITL workflows when decisions require human judgment, regulations require human approval, or quality requires human oversight. NeuronAgent makes HITL implementation straightforward through its workflow engine.

Agentic AI: Guide to Autonomous AI Agents

Complete guide to building autonomous AI agents with NeuronAgent.

Agent Memory Systems: Long-Term vs Short-Term Memory in AI Agents

Learn how to implement memory systems for AI agents.

NeuronDB vs pgvector: Feature Comparison and Migration Guide

Compare NeuronDB and pgvector features and migration paths.

Support

For questions, issues, or commercial support, contact support@neurondb.ai

Share This Article

Suggested hashtags:

#HITL#HumanInTheLoop#ApprovalSystems#WorkflowEngine#NeuronAgent#AgentWorkflows#WorkflowAutomation#NeuronDB#PostgreSQL#AIAgents#AgenticAI
📋 View copy-ready text for manual posting
Human-in-the-Loop (HITL) Workflows: Implementing Approval Systems with NeuronAgent

Complete guide to implementing HITL workflows and approval systems with NeuronAgent workflow engine

#HITL #HumanInTheLoop #ApprovalSystems #WorkflowEngine #NeuronAgent #AgentWorkflows #WorkflowAutomation #NeuronDB #PostgreSQL #AIAgents #AgenticAI

https://neurondb.ai/blog/hitl-workflows-approval-systems-neuronagent