Skip to content

[Feature] agents: human-in-the-loop approval gate #430

Description

@pathosDev

Part of the agents epic #421.

Rationale

Destructive or expensive tool calls need a human decision — and that decision may take hours. The wait must be durable: it has to survive restarts, passivation and shard rebalancing. Event sourcing makes this nearly free.

Scope

  • Tools flagged requiresApproval: true persist approval-requested and park the turn (state awaiting-approval).
  • approval-decision command resumes (approved → execute tool; rejected → report to the model / fail the turn per policy).
  • Timeout via the scheduler for now; migrate to durable reminders once [Feature] Grain Reminders (persistent timers that survive deactivation) #168 lands.
  • ApprovalGate helper actor + HTTP example (approve/reject endpoint) for the examples app.
const deleteUser = tool({ name: 'delete_user', requiresApproval: true, /* … */ }, implementation);
// turn parks DURABLY (survives restart/rebalance) until:
support.tell({ kind: 'approval-decision', callId, approved: true });

Documentation

"Human in the loop" docs page (EN + DE); JSDoc; CHANGELOG; example in examples/agents.

Acceptance

  • Kill-while-parked test: restart recovers the awaiting-approval state and resumes correctly on decision; rejection path covered; timeout path covered.

Relates

Epic #421; depends on #424 (AgentActor). #205 (persistent ask — the generalized primitive; migrate when it lands), #168 (Reminders).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions