Human-in-the-Loop (HITL)¶
The Human-in-the-Loop system in SemanticKernel.Graph provides comprehensive capabilities for integrating human decision-making into automated workflows. It enables you to pause graph execution, request human approval, validate confidence levels, and manage batch approval processes.
Overview¶
The HITL system consists of several key components:
HumanApprovalGraphNode
: Pauses execution for human approval decisionsConfidenceGateGraphNode
: Monitors confidence levels and triggers human intervention when thresholds are not metHumanApprovalBatchManager
: Groups and manages multiple approval requests efficientlyHumanInteractionStore
: Persists and coordinates HITL requests and responsesWebApiHumanInteractionChannel
: Web-based interaction channel for production deployments
Core Classes¶
HumanApprovalGraphNode¶
Pauses graph execution and waits for human approval before continuing:
public sealed class HumanApprovalGraphNode : IGraphNode
{
public HumanApprovalGraphNode(
string approvalTitle,
string approvalMessage,
IHumanInteractionChannel interactionChannel,
string? nodeId = null,
IGraphLogger? logger = null);
public static HumanApprovalGraphNode CreateConditional(
string approvalTitle,
string approvalMessage,
Func<GraphState, bool> activationCondition,
IHumanInteractionChannel interactionChannel,
string? nodeId = null,
IGraphLogger? logger = null);
}
Constructor Parameters:
* approvalTitle
: Title of the approval request
* approvalMessage
: Detailed message presented to the user
* interactionChannel
: Communication channel for user interaction
* nodeId
: Optional unique identifier for the node
* logger
: Optional logger for diagnostics
Key Features: * Conditional activation: Optional activation conditions based on graph state * Multiple channels: Support for console, web API, CLI, and custom channels * Configurable timeouts: Automatic fallback actions when no response is received * Batch approval: Integration with batch approval management * Context awareness: Rich context information for human decision-making * State modifications: Optional user-approved state changes * Audit trail: Comprehensive tracking of approval decisions and metadata
Input Parameters:
* execution_context
: Current execution context
* previous_result
: Result from previous node execution
* graph_state
: Current graph state
* user_context
: User-specific context information
Output Parameters:
* approval_result
: Boolean result of the approval decision
* user_response
: Full user response object
* approved_by
: Identifier of the user who made the decision
* approval_timestamp
: When the decision was made
* user_modifications
: Any state modifications requested by the user
ConfidenceGateGraphNode¶
Monitors confidence levels and triggers human intervention when thresholds are not met:
public sealed class ConfidenceGateGraphNode : IGraphNode
{
public ConfidenceGateGraphNode(
double confidenceThreshold = 0.7,
string? nodeId = null,
IGraphLogger? logger = null);
public static ConfidenceGateGraphNode CreateWithInteraction(
double confidenceThreshold,
IHumanInteractionChannel interactionChannel,
string? nodeId = null,
IGraphLogger? logger = null);
}
Constructor Parameters:
* confidenceThreshold
: Minimum confidence threshold (0.0 to 1.0)
* nodeId
: Optional unique identifier for the node
* logger
: Optional logger for diagnostics
Key Features: * Configurable threshold: Set minimum confidence levels for automatic processing * Multiple sources: Support for LLM confidence, similarity scores, and custom metrics * Automatic analysis: Detects patterns of uncertainty and potential issues * Escalation levels: Different approval requirements based on confidence severity * Learning capabilities: Adjusts thresholds based on historical feedback * Manual bypass: Optional manual override capabilities
Input Parameters:
* confidence_score
: Overall confidence score
* uncertainty_factors
: Factors contributing to uncertainty
* llm_confidence
: LLM-generated confidence metrics
* similarity_scores
: Similarity-based confidence indicators
* validation_results
: Validation outcome confidence
* previous_confidence_history
: Historical confidence data
Output Parameters:
* gate_result
: Whether the gate passed or blocked execution
* confidence_level
: Current confidence level assessment
* uncertainty_analysis
: Detailed uncertainty factor analysis
* human_override
: Whether manual override was applied
* confidence_sources
: Sources contributing to confidence calculation
* gate_decision_reason
: Explanation of gate decision
HumanApprovalBatchManager¶
Efficiently manages and processes multiple approval requests:
public sealed class HumanApprovalBatchManager : IDisposable
{
public HumanApprovalBatchManager(
IHumanInteractionChannel defaultChannel,
BatchApprovalOptions? options = null,
IGraphLogger? logger = null);
}
Constructor Parameters:
* defaultChannel
: Default interaction channel for processing batches
* options
: Configuration options for batch processing
* logger
: Optional logger for diagnostics
Key Features: * Smart grouping: Groups requests by type, priority, user, and context * Configurable timeouts: Batch formation and processing timeouts * Partial approval: Option to process incomplete batches * Detailed statistics: Performance and usage metrics * Thread safety: Safe concurrent operations * Persistence: Optional batch state persistence
Events:
* BatchFormed
: Raised when a batch is ready for processing
* BatchCompleted
: Raised when a batch processing is finished
* RequestAddedToBatch
: Raised when a request is added to a batch
Batch Configuration Options:
public class BatchApprovalOptions
{
public int MaxBatchSize { get; set; } = 10;
public TimeSpan BatchFormationTimeout { get; set; } = TimeSpan.FromMinutes(5);
public TimeSpan MaxBatchAge { get; set; } = TimeSpan.FromHours(1);
public bool AllowPartialBatches { get; set; } = true;
public string[] GroupingCriteria { get; set; } = { "type", "priority" };
}
HumanInteractionStore¶
Abstracts persistence and coordination of HITL requests and responses:
public interface IHumanInteractionStore
{
Task<bool> AddPendingAsync(HumanInterruptionRequest request, CancellationToken cancellationToken = default);
Task<HumanInterruptionRequest?> GetRequestAsync(string requestId, CancellationToken cancellationToken = default);
Task<IReadOnlyList<HumanInterruptionRequest>> ListPendingAsync(string? executionId = null, string? nodeId = null, CancellationToken cancellationToken = default);
Task<bool> SubmitResponseAsync(HumanInterruptionResponse response, CancellationToken cancellationToken = default);
Task<bool> CancelAsync(string requestId, CancellationToken cancellationToken = default);
Task<ApprovalStatus> GetStatusAsync(string requestId, CancellationToken cancellationToken = default);
Task<HumanInterruptionResponse> AwaitResponseAsync(string requestId, CancellationToken cancellationToken = default);
}
Key Features: * Request management: Add, retrieve, and track pending requests * Response handling: Submit and process user responses * Status tracking: Monitor request status throughout lifecycle * Filtering: List requests by execution ID or node ID * Async operations: Non-blocking request/response handling * Cancellation support: Graceful cancellation of pending requests
Events:
* RequestAdded
: Raised when a new request is added
* ResponseSubmitted
: Raised when a response is submitted
* RequestCancelled
: Raised when a request is cancelled
WebApiHumanInteractionChannel¶
Web-based interaction channel for production deployments:
public sealed class WebApiHumanInteractionChannel : IHumanInteractionChannel, IDisposable
{
public WebApiHumanInteractionChannel(IHumanInteractionStore store);
public async Task InitializeAsync(Dictionary<string, object>? configuration = null);
}
Constructor Parameters:
* store
: Backing store for request/response coordination
Key Features:
* Web API integration: Exposes requests via backing store for REST consumption
* Event-driven: Raises events for request lifecycle changes
* Configuration: Flexible configuration options
* Store cooperation: Works with any IHumanInteractionStore
implementation
* Production ready: Designed for web-based approval interfaces
Events:
* ResponseReceived
: Raised when a response is received
* RequestTimedOut
: Raised when a request times out
* RequestAvailable
: Raised when a new request becomes available
* RequestCancelled
: Raised when a request is cancelled
Configuration and Options¶
HumanInteractionTimeout¶
Configures timeout behavior for human interactions:
public class HumanInteractionTimeout
{
public TimeSpan PrimaryTimeout { get; set; } = TimeSpan.FromMinutes(30);
public TimeSpan EscalationTimeout { get; set; } = TimeSpan.FromHours(2);
public TimeoutAction DefaultAction { get; set; } = TimeoutAction.Reject;
public bool EnableEscalation { get; set; } = false;
public string[] EscalationRecipients { get; set; } = Array.Empty<string>();
}
Properties:
* PrimaryTimeout
: Initial timeout for the interaction
* EscalationTimeout
: Extended timeout for escalation scenarios
* DefaultAction
: Action to take when timeout occurs
* EnableEscalation
: Whether to enable timeout escalation
* EscalationRecipients
: Recipients for escalation notifications
HumanInteractionOption¶
Defines available options for user selection:
public class HumanInteractionOption
{
public string OptionId { get; set; } = string.Empty;
public string DisplayText { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public object? Value { get; set; }
public bool IsDefault { get; set; } = false;
public bool RequiresJustification { get; set; } = false;
public string[] AllowedUsers { get; set; } = Array.Empty<string>();
}
Properties:
* OptionId
: Unique identifier for the option
* DisplayText
: Human-readable text for display
* Description
: Detailed description of the option
* Value
: Value returned when option is selected
* IsDefault
: Whether this is the default option
* RequiresJustification
: Whether justification is required
* AllowedUsers
: Users allowed to select this option
BatchApprovalOptions¶
Configures batch approval processing behavior:
public class BatchApprovalOptions
{
public int MaxBatchSize { get; set; } = 10;
public TimeSpan BatchFormationTimeout { get; set; } = TimeSpan.FromMinutes(5);
public TimeSpan MaxBatchAge { get; set; } = TimeSpan.FromHours(1);
public bool AllowPartialBatches { get; set; } = true;
public string[] GroupingCriteria { get; set; } = { "type", "priority" };
public bool EnableNotifications { get; set; } = true;
public string[] NotificationChannels { get; set; } = { "email", "webhook" };
}
Properties:
* MaxBatchSize
: Maximum number of requests per batch
* BatchFormationTimeout
: Time to wait for batch formation
* MaxBatchAge
: Maximum age of a batch before processing
* AllowPartialBatches
: Whether to process incomplete batches
* GroupingCriteria
: Criteria for grouping requests
* EnableNotifications
: Whether to enable batch notifications
* NotificationChannels
: Channels for batch notifications
Usage Examples¶
Basic Human Approval¶
Create a simple approval node with console interaction:
// Create console interaction channel
var consoleChannel = new ConsoleHumanInteractionChannel();
// Create approval node
var approvalNode = new HumanApprovalGraphNode(
"Document Review",
"Please review the generated document for accuracy and completeness",
consoleChannel,
"doc_review_approval");
// Configure approval options
approvalNode.AddApprovalOption("approve", "Approve and Continue", true, true)
.AddApprovalOption("reject", "Reject and Stop", false)
.AddApprovalOption("modify", "Approve with Modifications", "modified");
// Configure timeout
approvalNode.WithTimeout(TimeSpan.FromHours(24), TimeoutAction.Reject);
// Add to graph
graph.AddNode(approvalNode);
graph.AddEdge(previousNode, approvalNode);
Conditional Approval¶
Create approval nodes that only activate under specific conditions:
// Create conditional approval node
var conditionalApproval = HumanApprovalGraphNode.CreateConditional(
"High-Risk Transaction",
"Approval required for transactions above threshold",
state => state.GetValue<decimal>("transaction_amount") > 10000m,
consoleChannel,
"high_risk_approval");
// Configure priority and timeout
conditionalApproval.WithPriority(InteractionPriority.High)
.WithTimeout(TimeSpan.FromHours(4), TimeoutAction.Escalate);
// Add approval options
conditionalApproval.AddApprovalOption("approve", "Approve Transaction", true)
.AddApprovalOption("reject", "Reject Transaction", false)
.AddApprovalOption("review", "Request Additional Review", "review");
// Add routing based on approval result
graph.AddConditionalEdge(conditionalApproval, approvedNode,
edge => edge.Condition = "approval_result == true");
graph.AddConditionalEdge(conditionalApproval, rejectedNode,
edge => edge.Condition = "approval_result == false");
graph.AddConditionalEdge(conditionalApproval, reviewNode,
edge => edge.Condition = "approval_result == 'review'");
Confidence Gate¶
Monitor confidence levels and trigger human intervention:
// Create confidence gate node
var confidenceGate = new ConfidenceGateGraphNode(
confidenceThreshold: 0.8,
nodeId: "quality_gate");
// Configure confidence sources
confidenceGate.ConfidenceSources.Add(new LLMConfidenceSource("llm_confidence"));
confidenceGate.ConfidenceSources.Add(new SimilarityConfidenceSource("similarity_score"));
confidenceGate.ConfidenceSources.Add(new ValidationConfidenceSource("validation_result"));
// Configure aggregation strategy
confidenceGate.AggregationStrategy = ConfidenceAggregationStrategy.WeightedAverage;
// Configure timeout for human interaction
confidenceGate.TimeoutConfiguration.PrimaryTimeout = TimeSpan.FromMinutes(30);
confidenceGate.TimeoutConfiguration.DefaultAction = TimeoutAction.Reject;
// Allow manual bypass for urgent cases
confidenceGate.WithManualBypass(true);
// Add to graph
graph.AddNode(confidenceGate);
graph.AddEdge(previousNode, confidenceGate);
Batch Approval Management¶
Efficiently manage multiple approval requests:
// Create batch manager
var batchManager = new HumanApprovalBatchManager(
defaultChannel: consoleChannel,
options: new BatchApprovalOptions
{
MaxBatchSize = 20,
BatchFormationTimeout = TimeSpan.FromMinutes(10),
AllowPartialBatches = true,
GroupingCriteria = new[] { "type", "priority" }
});
// Subscribe to batch events
batchManager.BatchFormed += (sender, batch) =>
{
Console.WriteLine($"Batch {batch.BatchId} formed with {batch.Requests.Count} requests");
};
batchManager.BatchCompleted += (sender, args) =>
{
Console.WriteLine($"Batch {args.Batch.BatchId} completed in {args.ProcessingTime}");
};
// Use batch manager in approval nodes
var batchApprovalNode = new HumanApprovalGraphNode(
"Batch Document Review",
"Review multiple documents for approval",
consoleChannel,
"batch_doc_review");
// Configure batch processing
batchApprovalNode.WithTimeout(TimeSpan.FromHours(2), TimeoutAction.Escalate);
Web API Integration¶
Implement web-based approval interfaces:
// Create web API interaction channel
var interactionStore = new InMemoryHumanInteractionStore();
var webApiChannel = new WebApiHumanInteractionChannel(interactionStore);
// Initialize web API channel
await webApiChannel.InitializeAsync(new Dictionary<string, object>
{
["api_base_url"] = "https://api.example.com/approvals",
["timeout_seconds"] = 300,
["enable_notifications"] = true
});
// Subscribe to channel events
webApiChannel.ResponseReceived += (sender, response) =>
{
Console.WriteLine($"Received response: {response.Status} for request {response.RequestId}");
};
webApiChannel.RequestTimedOut += (sender, request) =>
{
Console.WriteLine($"Request {request.RequestId} timed out");
};
// Create web-based approval node
var webApprovalNode = new HumanApprovalGraphNode(
"Web Document Approval",
"Approve document via web interface",
webApiChannel,
"web_doc_approval");
// Configure web-specific options
webApprovalNode.WithTimeout(TimeSpan.FromHours(24), TimeoutAction.Escalate)
.WithPriority(InteractionPriority.Normal);
// Add approval options
webApprovalNode.AddApprovalOption("approve", "Approve Document", true, true)
.AddApprovalOption("reject", "Reject Document", false)
.AddApprovalOption("modify", "Request Modifications", "modify");
Integration with Graph Executor¶
Kernel Builder Extensions¶
Add HITL support to the kernel builder:
var builder = Kernel.CreateBuilder();
// Add basic HITL support
builder.AddHumanInTheLoop(consoleChannel);
// Add console-based HITL
builder.AddConsoleHumanInteraction(new Dictionary<string, object>
{
["prompt_format"] = "APPROVAL REQUIRED: {message}\nEnter 'approve' or 'reject': ",
["validation_pattern"] = @"^(approve|reject)$",
["retry_count"] = 3
});
// Add web API-based HITL
builder.AddWebApiHumanInteraction();
// Build kernel with HITL support
var kernel = builder.Build();
Graph Executor Configuration¶
Configure HITL behavior at the executor level:
var executor = new GraphExecutor("hitl-enabled-graph");
// Set default HITL timeout
executor.WithHumanApprovalTimeout(TimeSpan.FromHours(24), TimeoutAction.Reject);
// Configure HITL audit service
executor.WithHitlAuditService(new HitlAuditService(
interactionStore: interactionStore,
memoryService: memoryService,
logger: logger));
// Add HITL metrics collection
executor.WithHitlMetrics(new HitlMetricsCollector());
Advanced Patterns¶
Multi-Level Approval¶
Implement hierarchical approval workflows:
// Level 1: Basic approval
var level1Approval = new HumanApprovalGraphNode(
"Level 1 Approval",
"Initial review and approval",
consoleChannel,
"level1_approval");
// Level 2: Manager approval (only if amount > threshold)
var level2Approval = HumanApprovalGraphNode.CreateConditional(
"Level 2 Approval",
"Manager approval required for high-value transactions",
state => state.GetValue<decimal>("transaction_amount") > 50000m,
managerChannel,
"level2_approval");
// Level 3: Executive approval (only if amount > threshold)
var level3Approval = HumanApprovalGraphNode.CreateConditional(
"Level 3 Approval",
"Executive approval required for critical transactions",
state => state.GetValue<decimal>("transaction_amount") > 100000m,
executiveChannel,
"level3_approval");
// Configure approval chain
level1Approval.WithTimeout(TimeSpan.FromHours(4), TimeoutAction.Escalate);
level2Approval.WithTimeout(TimeSpan.FromHours(8), TimeoutAction.Escalate);
level3Approval.WithTimeout(TimeSpan.FromHours(24), TimeoutAction.Reject);
// Add to graph with conditional routing
graph.AddEdge(level1Approval, level2Approval);
graph.AddConditionalEdge(level2Approval, level3Approval,
edge => edge.Condition = "transaction_amount > 100000");
Confidence-Based Routing¶
Route execution based on confidence levels:
// Create confidence gate
var confidenceGate = new ConfidenceGateGraphNode(0.7, "quality_gate");
// Configure confidence sources
confidenceGate.ConfidenceSources.Add(new LLMConfidenceSource("llm_confidence"));
confidenceGate.ConfidenceSources.Add(new ValidationConfidenceSource("validation_score"));
// Add routing based on confidence
graph.AddConditionalEdge(confidenceGate, highConfidenceNode,
edge => edge.Condition = "gate_result == true");
graph.AddConditionalEdge(confidenceGate, lowConfidenceNode,
edge => edge.Condition = "gate_result == false");
// Configure low confidence path with human approval
var humanReviewNode = new HumanApprovalGraphNode(
"Human Review Required",
"Low confidence result requires human review",
consoleChannel,
"human_review");
lowConfidenceNode.AddEdge(humanReviewNode);
Batch Processing with Escalation¶
Handle batch approvals with escalation logic:
// Create batch manager with escalation
var batchManager = new HumanApprovalBatchManager(
defaultChannel: consoleChannel,
options: new BatchApprovalOptions
{
MaxBatchSize = 15,
BatchFormationTimeout = TimeSpan.FromMinutes(15),
AllowPartialBatches = false
});
// Subscribe to batch events
batchManager.BatchFormed += async (sender, batch) =>
{
// Send batch notification
await SendBatchNotificationAsync(batch);
// Start escalation timer
_ = Task.Run(async () =>
{
await Task.Delay(TimeSpan.FromMinutes(30));
if (batch.Requests.Any(r => r.Status == ApprovalStatus.Pending))
{
await EscalateBatchAsync(batch);
}
});
};
// Use batch manager in approval workflow
var batchApprovalNode = new HumanApprovalGraphNode(
"Batch Document Review",
"Review multiple documents for approval",
consoleChannel,
"batch_doc_review");
// Configure batch processing
batchApprovalNode.WithTimeout(TimeSpan.FromHours(1), TimeoutAction.Escalate);
Performance and Monitoring¶
Metrics Collection¶
Monitor HITL performance and usage:
// Create HITL metrics collector
var hitlMetrics = new HitlMetricsCollector();
// Subscribe to approval events
approvalNode.ApprovalCompleted += (sender, args) =>
{
hitlMetrics.RecordApproval(
nodeId: args.NodeId,
duration: args.Duration,
result: args.Result,
channel: args.ChannelType);
};
// Subscribe to confidence gate events
confidenceGate.GateActivated += (sender, args) =>
{
hitlMetrics.RecordGateActivation(
nodeId: args.NodeId,
confidenceLevel: args.ConfidenceLevel,
threshold: args.Threshold);
};
// Get HITL performance summary
var summary = hitlMetrics.GetPerformanceSummary();
Console.WriteLine($"Average approval time: {summary.AverageApprovalTime}");
Console.WriteLine($"Confidence gate activation rate: {summary.GateActivationRate:P2}");
Audit Trail¶
Maintain comprehensive audit records:
// Create HITL audit service
var auditService = new HitlAuditService(
interactionStore: interactionStore,
memoryService: memoryService,
logger: logger);
// Configure audit options
auditService.Configure(new HitlAuditOptions
{
EnableDetailedLogging = true,
RetainAuditDataFor = TimeSpan.FromDays(90),
LogSensitiveData = false,
EnableComplianceReporting = true
});
// Subscribe to audit events
auditService.AuditRecordCreated += (sender, record) =>
{
Console.WriteLine($"Audit record created: {record.RecordId}");
};
// Get audit summary
var auditSummary = await auditService.GetAuditSummaryAsync(
startDate: DateTimeOffset.UtcNow.AddDays(-30),
endDate: DateTimeOffset.UtcNow);
Security and Compliance¶
Authentication and Authorization¶
Secure HITL interactions:
// Create authenticated interaction channel
var authenticatedChannel = new AuthenticatedHumanInteractionChannel(
baseChannel: webApiChannel,
authProvider: new JwtAuthProvider(),
userStore: new UserStore());
// Configure authorization policies
authenticatedChannel.ConfigureAuthorization(new AuthorizationPolicy
{
RequireAuthentication = true,
RequireApprovalRole = true,
AllowedRoles = new[] { "approver", "manager", "admin" },
RequireMFA = true
});
// Use authenticated channel in approval node
var secureApprovalNode = new HumanApprovalGraphNode(
"Secure Document Approval",
"Approval requires proper authentication and authorization",
authenticatedChannel,
"secure_approval");
Data Privacy¶
Protect sensitive information in HITL workflows:
// Create privacy-aware approval node
var privacyApprovalNode = new HumanApprovalGraphNode(
"Privacy Review",
"Review data processing for privacy compliance",
consoleChannel,
"privacy_approval");
// Configure privacy options
privacyApprovalNode.AllowStateModifications = false; // Prevent state changes
privacyApprovalNode.WithPrivacyProtection(new PrivacyProtectionOptions
{
MaskSensitiveData = true,
LogAccessAttempts = true,
RequireJustification = true,
AuditDataAccess = true
});
// Add privacy-specific approval options
privacyApprovalNode.AddApprovalOption("approve", "Approve Processing", true)
.AddApprovalOption("reject", "Reject Processing", false)
.AddApprovalOption("modify", "Request Modifications", "modify");
See Also¶
- Human-in-the-Loop Guide - Comprehensive guide to HITL concepts and techniques
- Conditional Nodes - Conditional execution and routing patterns
- Graph State - State management for HITL workflows
- Graph Executor - Core execution engine that supports HITL
- HITL Examples - Complete examples demonstrating HITL capabilities