Implementing human approval workflow in LangChain agents

I’m working on a LangChain agent project where I need to add human approval steps. I want the agent to stop and ask for permission before doing important tasks like running tools or making database changes. The notification should go through Slack or websockets.

I was thinking about using custom callbacks but not sure if that’s the right approach. I tried looking into Humanlayer but it doesn’t support what I need right now. Since I’m using LangChain instead of LangGraph, the interrupt feature won’t work for my setup.

Has anyone implemented something similar? What would be the best way to handle this kind of human-in-the-loop pattern? Any suggestions would be appreciated.

honestly, i just run a basic approval service on a separate thread. the agent pauses, sends approval requests to an api endpoint that handles slack notifications. way simpler than managing state in callbacks or dealing with fancy workflow tools.

I built something similar but used custom tool wrappers instead of callbacks. Just create a decorator that catches tool calls and shoots approval requests through Slack’s Block Kit API. The agent sits there waiting for someone to hit approve on the channel or click the interactive buttons before moving forward. For database stuff, I queue everything up and only run it once approval comes back. The trick is keeping state while it’s paused - Redis works great for storing execution context. Way more control than callbacks since you can pick and choose which tools need approval.

totally agree, custom callbacks have worked well for me too! i find slack webhooks really make the process smoother. websockets can be tricky, so sticking with slack sounds wiser. hope that helps!

Try a middleware approach - intercept agent execution at the chain level instead of individual tools or callbacks. I built a custom chain wrapper that watches for specific action types before they run. When it spots operations needing approval, it sends a message to a queue and pauses execution until getting confirmation. The approval service picks up these messages and handles Slack integration separately. This keeps your agent code clean and makes changing approval rules easy without touching core logic. Main benefit: you can use the same approval pattern across multiple agents without duplicating code. For websockets, keeping connections alive during long approval waits is tricky, so async message queuing works better in production.

I’ve hit this problem multiple times. Best solution? Use a workflow automation platform for the approval pipeline.

Custom callbacks and tool wrappers are a nightmare. You’re building state management, retry logic, timeouts, notification channels - it gets messy fast.

Better approach: have your LangChain agent make HTTP calls to trigger approval workflows. The workflow handles Slack notifications, button interactions, timeouts, and state persistence. Your agent just waits for the HTTP response.

Here’s my setup: critical tools hit an approval endpoint first. Workflow sends formatted Slack messages showing what the agent wants to do. Team approves or rejects with buttons. Agent gets yes/no and continues or stops.

For database ops, the workflow can queue commands and only execute after approval. Way more flexible than pausing agent execution.

Took me 2 hours to set up vs weeks of custom code. You get logging, analytics, and can modify approval logic without touching agent code.

Latenode works great for this - native Slack integrations and easy webhooks with LangChain agents.