Anvia
Human in the Loop

Approval Handlers

Resolve pending tool approvals from your application code.

withToolApprovalHandler(...) receives the pending approval request and returns the final decision.

Handler Shape

const response = await agent
  .prompt("Refund order A-100.")
  .withHook(approvalHook)
  .withToolApprovalHandler(async (approval, action) => {
    const approved = await approvals.waitForDecision({
      id: approval.id,
      toolName: approval.toolName,
      args: approval.args,
      reason: approval.reason,
      timeoutMs: action.timeoutMs,
    });

    return {
      ...approval,
      status: approved ? "approved" : "rejected",
      resolvedAt: new Date().toISOString(),
    };
  })
  .send();

The handler can call a database, wait on a queue, show a UI, or apply a policy decision. Anvia does not own that approval system.

Approval Request

The approval request contains the tool call Anvia is about to run.

type ApprovalRequest = {
  id: string;
  toolName: string;
  toolCallId?: string;
  internalCallId: string;
  args: string;
  status: "pending";
  requestedAt: string;
  reason?: string;
};

Store this object if you need an audit trail.

Return Approved

When the handler returns approved, Anvia runs the tool.

return {
  ...approval,
  status: "approved",
  resolvedAt: new Date().toISOString(),
};

Return Rejected

When the handler returns rejected, Anvia does not run the tool. The reason becomes the tool result sent back to the model.

return {
  ...approval,
  status: "rejected",
  resolvedAt: new Date().toISOString(),
  reason: "Reviewer denied the refund.",
};

Return Timed Out

Use timed_out when your approval workflow did not resolve in time.

return {
  ...approval,
  status: "timed_out",
  resolvedAt: new Date().toISOString(),
  reason: "No reviewer responded within 60 seconds.",
};

timeoutMs is passed to the handler through the approval action. Your handler decides how to enforce the timeout.

No Handler

If a hook requires approval but the request has no approval handler, Anvia rejects the tool call and sends a rejection message back to the model.