Framework how-tos
Add human approval to LangGraph workflows
A tactical walkthrough for pausing LangGraph, routing approval through Contro1, and resuming execution safely.
LangGraph works best with approval nodes at deterministic checkpoints and webhook-based resume handling.
Key takeaways
- Place approval nodes at deterministic checkpoints, not wherever the LLM decides.
- Use LangGraph's interrupt pattern so state is persisted while the human decides.
- Resume through a verified webhook, never through a raw HTTP endpoint.
- Store the request id in your graph state for idempotent resume.
- Treat approvals as an organizational workflow: route by role, enforce deadlines, escalate missed decisions, and keep agents away from dangerous actions until a human owner approves.
Start with the real approval boundary
LangGraph makes it easy to pause and resume a workflow, but the important design decision happens before code: where should the agent lose autonomy? A good approval boundary is not "ask a human sometimes." It is a deterministic checkpoint before a high-impact action executes.
Use approvals for actions that move money, change access, write to production systems, send customer-visible messages, override policy, or create hard-to-reverse state. Keep low-risk reads, summarization, and internal drafting outside the approval path so the graph still moves quickly.
- Gate the action before execution, not after the tool has already run.
- Put the approval node immediately before the risky edge in the graph.
- Include the proposed action, business object, reason, risk, and fallback path.
- Persist the request id and correlation id so retries do not create duplicate approvals.
Pattern for LangGraph
- Pick the checkpoint in your graph where a human decision belongs.
- Create the approval request from that node with full business context.
- Store the request id and correlation metadata in graph state.
- Resume only after verifying the signed callback.
Organization-in-the-loop, not a developer breakpoint
Contro1 is human-in-the-loop done right, and then it goes further: it puts the whole organization in the loop, giving you the full suite to govern agents: policy triggers, approval hierarchy and quorum, shift coverage, role routing, and SLA escalation, now wrapped around LangGraph agent work. Every risky action lands with whoever would have owned the decision anyway, not just whoever happens to be online.
The agent still does the hard work: gathering context, preparing the action, drafting the response, and moving the workflow forward. The management, accountability, and final business decisions stay with the people who owned them before agents entered the process.
That matters most when the graph reaches a risky node. The reviewer sees the context, the request routes to the right owner, the SLA starts, missed decisions escalate, the callback is signed, and the audit trail records what happened. Agents should not perform dangerous actions on their own authority.
Use the LangGraph human approval connector
If you are already using LangGraph, do not hand-roll the pause, approval request, webhook verification, and resume logic from scratch. The Contro1 LangGraph connector gives you the framework-specific pieces for approval nodes, LangChain tool-style approval requests, signed webhook handling, and thread correlation.
Minimal implementation flow
- Create a graph state field for approval metadata: request id, correlation id, target action, and reviewer decision.
- Add a prepare node that builds the proposed action without executing it.
- Add an approval node that calls Contro1 and interrupts the LangGraph thread while the human decides.
- Add approved and rejected edges so both outcomes are explicit in the graph.
- Handle the Contro1 webhook in a signed endpoint that resumes the correct LangGraph thread.
What the approval request should include
A reviewer should be able to decide without spelunking through traces or opening five internal tools. The request should carry the same business context a human operator would need if another employee asked for approval in Slack or an internal workflow system.
- Who or what the action affects: customer, account, ticket, deployment, payment, or user.
- The exact action the agent wants to take and the system it will touch.
- Why the agent recommends the action, including relevant evidence and confidence signals.
- The risk if approved, the cost if rejected, and the fallback if nobody responds.
- The SLA, escalation owner, and audit metadata needed by the organization.
Failure modes to avoid
- Pausing after the risky action instead of before it.
- Sending approvals to a shared inbox with no owner, shift, deadline, or escalation path.
- Letting the LLM choose whether a policy-required action needs approval.
- Resuming from an unsigned webhook or a raw endpoint anyone can call.
- Creating a new approval request every time the same graph node retries.
- Treating rejection as an error instead of a first-class branch in the graph.
Frequently asked questions
Should approval happen inside the graph or outside it?
The approval request should be triggered by the graph node, but the final resume should happen through a verified callback path - not an open HTTP endpoint.
What if the approval times out?
Set a deadline on the request. On timeout, the graph receives a rejection or escalation event and takes the fallback path you defined.
Can a single run create multiple approvals?
Yes. Each risky tool call can gate independently. Give each one a distinct idempotency key and correlation id.