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 wikipedia

pip install openai==0.28.1

Step 2: Setup OpenAI Environment
import os
import getpass
os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:")

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!"))

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:

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

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

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)]

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,
)

Step 7: Testing the Agent
A Wikipedia search doesn’t trigger validation (non-terminal tool):
agent.run(
"when did USA gained independence",
callbacks=callbacks,
)

A pre-approved terminal command also runs without prompting:
agent.run("print 'Hello World' in the terminal", callbacks=callbacks)

A non-pre-approved terminal command triggers the human approval prompt:
agent.run("list all directories in /private", callbacks=callbacks)

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.