Skip to Content
Human-in-the-loop

Human-in-the-loop

Roadmap

This capability is on the Roadmap; the API shown here is the planned design.

Refunds over €100 need a human. Today that is bespoke code, per team, per framework. DDK will let you declare the approval requirement on the tool itself:

@donkey.tool(approval="required", risk="financial") async def issue_refund(ticket_id: str, amount: float): ...

When the agent calls issue_refund, DDK raises ApprovalRequired (or triggers the framework’s own interrupt), records the pending approval against the correlation ID, and resumes when you resolve it:

await donkey.approvals.resolve(approval_id, approved_by=reviewer.id)

Mapped onto what your framework already has

DDK does not introduce a new pause mechanism. It maps one vocabulary onto the primitive each framework already ships:

Framework / protocolNative primitive
LangGraphinterrupt() / Command(resume=…)
OpenAI Agents SDKtool-approval / guardrail hooks
Google ADKbefore/after tool callbacks
Strandshooks
MCPelicitation
Omni GatewayTrusted Agent Identity step-up (MFA)

What DDK adds

Every framework already has human-in-the-loop. DDK adds three things on top, none of which is a new mechanism:

  1. Normalisation — one vocabulary across frameworks, so approval policy is not rewritten when a team switches from ADK to LangGraph.
  2. Auditability — the pending approval appears in the span, and the approver’s identity lands in the audit trail next to the correlation ID. “Who approved this refund?” becomes a query.
  3. Gateway routing — a high-risk approval can be routed through the gateway’s identity layer for step-up MFA, rather than trusting a click in your own UI.

Out of scope

DDK will not ship an approval queue or an approval UI — both are on the will-not-build list. It integrates with whatever you already run: Slack, ServiceNow, or LangGraph’s own checkpointer.

A queue would mean owning a durable store, an escalation model, and a notification system — a product rather than a feature.

Last updated on