Configuration options for the middleware
A middleware instance that can be passed to createAgent
Basic usage with selective tool approval
import { humanInTheLoopMiddleware } from "langchain";
import { createAgent } from "langchain";
const hitlMiddleware = humanInTheLoopMiddleware({
interruptOn: {
// Interrupt write_file tool and allow edits or approvals
"write_file": {
allowedDecisions: ["approve", "edit"],
description: "⚠️ File write operation requires approval"
},
// Auto-approve read_file tool
"read_file": false
}
});
const agent = createAgent({
model: "openai:gpt-4",
tools: [writeFileTool, readFileTool],
middleware: [hitlMiddleware]
});
Handling approval requests
import { type HITLRequest, type HITLResponse, type Interrupt } from "langchain";
import { Command } from "@langchain/langgraph";
// Initial agent invocation
const result = await agent.invoke({
messages: [new HumanMessage("Write 'Hello' to output.txt")]
}, config);
// Check if agent is paused for approval
if (result.__interrupt__) {
const interruptRequest = result.__interrupt__?.[0] as Interrupt<HITLRequest>;
// Show tool call details to user
console.log("Actions:", interruptRequest.value.actionRequests);
console.log("Review configs:", interruptRequest.value.reviewConfigs);
// Resume with approval
const resume: HITLResponse = {
decisions: [{ type: "approve" }]
};
await agent.invoke(
new Command({ resume }),
config
);
}
Different decision types
import { type HITLResponse } from "langchain";
// Approve the tool call as-is
const resume: HITLResponse = {
decisions: [{ type: "approve" }]
};
// Edit the tool arguments
const resume: HITLResponse = {
decisions: [{
type: "edit",
editedAction: { name: "write_file", args: { filename: "safe.txt", content: "Modified" } }
}]
};
// Reject with feedback
const resume: HITLResponse = {
decisions: [{
type: "reject",
message: "File operation not allowed in demo mode"
}]
};
Production use case with database operations
const hitlMiddleware = humanInTheLoopMiddleware({
interruptOn: {
"execute_sql": {
allowedDecisions: ["approve", "edit", "reject"],
description: "🚨 SQL query requires DBA approval\nPlease review for safety and performance"
},
"read_schema": false, // Reading metadata is safe
"delete_records": {
allowedDecisions: ["approve", "reject"],
description: "⛔ DESTRUCTIVE OPERATION - Requires manager approval"
}
},
descriptionPrefix: "Database operation pending approval"
});
Using dynamic callable descriptions
import { type DescriptionFactory, type ToolCall } from "langchain";
import type { AgentBuiltInState, Runtime } from "langchain/agents";
// Define a dynamic description factory
const formatToolDescription: DescriptionFactory = (
toolCall: ToolCall,
state: AgentBuiltInState,
runtime: Runtime<unknown>
) => {
return `Tool: ${toolCall.name}\nArguments:\n${JSON.stringify(toolCall.args, null, 2)}`;
};
const hitlMiddleware = humanInTheLoopMiddleware({
interruptOn: {
"write_file": {
allowedDecisions: ["approve", "edit"],
// Use dynamic description that can access tool call, state, and runtime
description: formatToolDescription
},
// Or use an inline function
"send_email": {
allowedDecisions: ["approve", "reject"],
description: (toolCall, state, runtime) => {
const { to, subject } = toolCall.args;
return `Email to ${to}\nSubject: ${subject}\n\nRequires approval before sending`;
}
}
}
});
afterModel phase, intercepting before tool execution
Creates a Human-in-the-Loop (HITL) middleware for tool approval and oversight.
This middleware intercepts tool calls made by an AI agent and provides human oversight capabilities before execution. It enables selective approval workflows where certain tools require human intervention while others can execute automatically.
A invocation result that has been interrupted by the middleware will have a
__interrupt__property that contains the interrupt request.Features
Decision Types
When a tool requires approval, the human operator can respond with:
approve: Execute the tool with original argumentsedit: Modify the tool name and/or arguments before executionreject: Provide a manual response instead of executing the tool