Human-in-the-loop for support agents

Your support agent should not issue that refund alone.

The escalation reaches a team lead on their phone and comes back as an answer, not a ticket in a queue.

How do I add human approval to an AI customer support agent?

Pushary adds human approval to an AI customer support agent with one call. Put it before the refund, the account change or the credit. A team lead gets a notification on their phone. They tap Approve or Deny while your agent waits. You can also ask them to type a different amount instead. If nobody answers in time, the refund does not run, so an unattended escalation never turns into a payout. Every answer is saved.

What needs a yes

The calls that should not be automatic

issueRefund(orderId, amount)
Money leaving the account is the one support action with no clean undo. A confidence score is not the same as a person agreeing to spend it.
applyAccountCredit(userId, amount)
Goodwill credits are where an agent that wants to please the customer gets expensive fastest. They are also where the policy in a prompt drifts furthest from the one in finance's spreadsheet.
cancelSubscription(userId)
A cancellation the customer did not clearly ask for is a support failure. It shows up weeks later as a chargeback rather than a reply.
updateBillingEmail(userId, email)
Changing where invoices and password resets go is a common way to take over an account. That is why a person is usually supposed to confirm it.
escalate(ticketId, reason)
A handoff only counts if somebody receives it. Most escalation paths assume a person is watching a console at that moment.

The code

One call inside the step you already have

Wrap the action, not the whole agent. Everything the agent does that is safe keeps running without asking anyone.

bash
npm i @pushary/server
one call
import { createPusharyServer } from "@pushary/server"

const px = createPusharyServer({ apiKey: process.env.PUSHARY_API_KEY! })

async function resolveTicket(ticket: Ticket, proposed: RefundPlan) {
  // Small refunds inside policy do not need a person.
  if (proposed.amount <= POLICY.autoRefundCeiling) {
    return issueRefund(ticket.orderId, proposed.amount)
  }

  const decision = await px.decisions.ask({
    externalId: ticket.assignedAgentId,
    type: "confirm",
    question: `Refund $${proposed.amount} on order #${ticket.orderId}? ${proposed.reason}`,
  })

  if (!decision.approved) return replyWithAlternative(ticket)
  return issueRefund(ticket.orderId, proposed.amount)
}

Who answers

The approver is not at a desk

In support the approver is a team lead, a duty manager or the account owner. None of them sit in your admin console. They are on shift, between calls or away from a desk. An approval sent to an inbox becomes a six hour delay: the refund is correctly blocked, for the rest of the afternoon. Pushary reaches the phone they carry, by the user id you already store.

Our agent already hands off to a human. Why add anything?

A handoff and a decision are different things. A handoff moves the ticket into a queue and ends the agent's run. The customer waits for someone to pick it up and start again from the beginning. A decision keeps the run going. The agent has already pulled the order, the history and the fix it wants to make. It needs one person to say yes before it finishes the job. That is faster for the customer and cheaper for you, because nobody re-reads the thread. It only works if the person can answer from wherever they are. And if they cannot answer in time, the refund must not run. Pushary covers both: the question goes to their phone, and no answer means no.

Worth reading: LangGraph on interrupts and resuming a paused run.

$99/ month, Partner plan

Add it to your product. Your users never make a Pushary account or pay us.

What the Partner plan covers

FAQ

Questions, answered

Can the approver send back a different amount instead of just yes or no?
Yes. Use the input type instead of confirm, and the person types a value that comes back to your code as the answer. A common support pattern is a yes or no inside policy and a typed amount above it. The lead can offer a smaller credit instead of rejecting outright and starting the thread over. Approve and Deny work on the lock screen. A typed answer opens the Pushary app.
Does the customer see that a human was asked?
Only if you tell them. Pushary sends the question to your approver and returns the answer to your code. The customer sees nothing unless your agent says something while it waits. On anything that takes more than a few seconds, saying something is usually the right call.
What happens to the ticket if nobody answers?
The refund does not run, and your agent decides what happens next. Most support teams send the ticket back to the normal queue. So the worst case is what you have today, and never an unapproved refund. Pushary keeps the request, so a deploy during the wait does not lose it. Save the decision id and pick the ticket back up from the signed webhook or by polling.
Can different approvers handle different queues?
Yes. You pass your own user id for whoever should decide. Send a billing question to the finance owner and a technical escalation to the lead on shift, just by passing a different id. Each person installs the free Pushary app and connects their phone once with a link. They never sign up with Pushary or pay us.

Put a person on the step that needs one.

Connect a user once, ask with one call, and run the action only on a yes. Every answer is saved.

Start free