I’m working on a LangChain agent project where I need to add manual approval steps. Basically I want the agent to stop execution and wait for human confirmation before doing critical operations like executing tools or making database changes.
The notification should happen through slack messages or websocket connections. I’m thinking about using custom callbacks but not sure if that’s the right approach.
Since I’m using standard LangChain (not LangGraph), the interrupt feature won’t work for my case. Humanlayer doesn’t support my current setup either.
What are some alternative approaches to implement this pause-and-approve workflow? Any suggestions would be appreciated.
I built something like this last year for AI agents making production changes.
Don’t use decorators - they’re a mess with multiple approval points. You need a workflow layer between your LangChain agent and tool execution.
Here’s what worked: create a workflow that pauses, sends approval requests to Slack via webhook, then waits for response. The trick is solid state management that handles pause/resume without losing context.
You could build it with Redis and custom handlers, but it’s a nightmare to maintain. Just the webhook integrations will eat weeks.
I went with Latenode for this. It’s got approval nodes that pause workflows and trigger Slack notifications or websockets. When approval comes back, it resumes with full context. No custom callbacks.
Best part - wrap your entire LangChain agent in a Latenode workflow and drop approval gates wherever you want. Way cleaner than decorators or Redis hacks.
Custom callbacks work great for this. I built something similar by extending BaseCallbackHandler to catch tool executions. The callback grabs the on_tool_start event, shoots a request to Slack, then blocks with asyncio.Event until someone approves it through a webhook. The tricky part is keeping execution state while paused. I dump the agent’s current state to a database with unique IDs, so when approval hits, it picks up exactly where it stopped. Don’t forget timeouts and rejections - I expire pending approvals after 30 minutes. For websockets, just add another channel in your callback handler. When the approval endpoint fires, it can ping both Slack and any connected websocket clients. Works perfectly with standard LangChain, no extra workflow tools needed.
try usin a decorator for your tool calls - it’ll send approval requests and wait for replies. I did something similar with redis as a msg broker. agent drops the request in redis, slack bot handles it. bit hacky but worked great!
just override the tool call in your agent class. when it hits a critical tool, pause n send your slack webhook or websocket msg. store the agent state in temp memory or file, then poll for the approval. once approved, restore state n keep going. way easier than callbacks.