LangChain agents use tools to help language models solve specific tasks like searching, calculating, and executing shell commands. Some tools — particularly shell tools — carry security risks when executed without oversight. The HumanApprovalCallbackHandler solves this by pausing the agent and asking a human to approve or reject each tool call before it executes.

Quick Answer: Add human validation to any LangChain tool with ShellTool(callbacks=[HumanApprovalCallbackHandler()]). The agent pauses before each tool call and prompts the user — type Y/Yes to approve or any other key to block.

When to Use Human Validation in LangChain

Scenario Use Human Validation? Reason
Shell command execution Yes — always ShellTool has no built-in safeguards
File system access Yes Risk of unintended reads or deletions
Simple web search Optional Low risk, but can be configured selectively
Math computation No No external system access or side effects
Wikipedia lookup No Read-only, no system risk

How to Add Human Validation to Any Tool in LangChain?

The complete Python script for this guide is available on Google Colaboratory.

Step 1: Install Modules

pip install langchain-experimental
pip install langchain-experimental running successfully in Google Colab
pip install wikipedia
pip install wikipedia running successfully in Google Colab
pip install openai==0.28.1
pip install openai version 0.28.1 running successfully in Google Colab

Step 2: Setup OpenAI Environment

import os
import getpass

os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:")
Setting OPENAI_API_KEY environment variable in Google Colab using getpass for secure key input

Step 3: Building the Tool

Import ShellTool and HumanApprovalCallbackHandler. The ShellTool executes shell commands — and by default, it runs with no safeguards:

from langchain.callbacks import HumanApprovalCallbackHandler
from langchain.tools import ShellTool

tool = ShellTool()
print(tool.run("echo Hello World!"))
ShellTool running echo Hello World with a security warning that the tool has no safeguards by default

The warning confirms that ShellTool requires human oversight — it should not be left to the agent to decide when to use it.

Step 4: Adding Human Validation

Pass HumanApprovalCallbackHandler() in the tool’s callbacks to add human-in-the-loop approval:

tool = ShellTool(callbacks=[HumanApprovalCallbackHandler()])
print(tool.run("ls /usr"))

The agent now pauses and asks for approval before running. Type Y or Yes (case-insensitive) to approve:

ShellTool with HumanApprovalCallbackHandler pausing and asking the user Y or N before running ls /usr

When permission is denied, the agent generates an error instead of executing:

GIF showing HumanApprovalCallbackHandler declining permission — agent responds with no tool available error

When permission is granted, the tool runs and returns the directory listing:

GIF showing HumanApprovalCallbackHandler granting permission — agent lists the private directory contents

Step 5: Configuring Human Validation

When the agent has many tools, validating each one is impractical. Use custom _should_check() and _approve() functions to apply validation selectively — only for specific tools:

from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain.llms import OpenAI

def _should_check(serialized_obj: dict) -> bool:
    return serialized_obj.get("name") == "terminal"

def _approve(_input: str) -> bool:
    if _input == "echo 'Hello World'":
        return True
    msg = (
        "Do you approve of the following input"
        "Anything except 'Y'/'Yes' (case-insensitive) will be treated as a no"
    )
    msg += "\n\n" + _input + "\n"
    resp = input(msg)
    return resp.lower() in ("yes", "y")

callbacks = [HumanApprovalCallbackHandler(should_check=_should_check, approve=_approve)]
Custom _should_check and _approve functions configured with HumanApprovalCallbackHandler for selective validation

Step 6: Building the Language Model

llm = OpenAI(temperature=0)
tools = load_tools(["wikipedia", "llm-math", "terminal"], llm=llm)
agent = initialize_agent(
    tools,
    llm,
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
)
Building LangChain agent with Wikipedia, llm-math, and terminal tools loaded via load_tools

Step 7: Testing the Agent

A Wikipedia search doesn’t trigger validation (non-terminal tool):

agent.run(
    "when did USA gained independence",
    callbacks=callbacks,
)
Agent answering USA independence question using Wikipedia without triggering human validation

A pre-approved terminal command also runs without prompting:

agent.run("print 'Hello World' in the terminal", callbacks=callbacks)
Agent printing Hello World in terminal using the pre-approved echo command without human validation prompt

A non-pre-approved terminal command triggers the human approval prompt:

agent.run("list all directories in /private", callbacks=callbacks)
Agent pausing and asking user to approve listing private directory contents before running the terminal command

Conclusion

To add human validation to any LangChain tool, pass HumanApprovalCallbackHandler() in the tool’s callbacks argument — the agent will pause and prompt for approval before each tool call. For multi-tool agents, configure selective validation using custom _should_check() and _approve() functions so that only high-risk tools like the terminal trigger the prompt, while safe tools like Wikipedia and math chains run automatically. This pattern is essential for any production LangChain agent that executes shell commands or accesses sensitive system resources.