approvalhuman-in-the-loopsecurityphone

Require a named person to approve selected AI SDK tool calls from their phone before local tool execution. Pushary plugs into toolApproval and fails closed when approval is denied, expires, or goes unanswered.

Installation

pnpm add @pushary/ai-sdk ai zod
# Add to your .env file
PUSHARY_API_KEY=your_api_key_here

Usage

import { generateText, isStepCount, tool } from 'ai';
import { pusharyApproval } from '@pushary/ai-sdk';
import { z } from 'zod';

// Derive this stable ID from the authenticated user on your server.
// Enroll the user once before running the agent; see the Pushary guide below.
const externalId = 'user_123';

const lookupOrder = tool({
  description: 'Look up an order',
  inputSchema: z.object({ orderId: z.string() }),
  execute: async ({ orderId }) => ({
    orderId,
    total: 40,
    refundable: true,
  }),
});

const issueRefund = tool({
  description: 'Refund an order',
  inputSchema: z.object({
    orderId: z.string(),
    amount: z.number().positive(),
  }),
  execute: async ({ orderId, amount }) => ({
    orderId,
    amount,
    refunded: true,
  }),
});

const { text } = await generateText({
  model: 'openai/gpt-5-mini',
  tools: { issueRefund, lookupOrder },
  toolApproval: pusharyApproval({
    apiKey: process.env.PUSHARY_API_KEY!,
    externalId,
    policy: false,
    tools: ['issueRefund'],
  }),
  stopWhen: isStepCount(5),
  prompt: 'Look up order 1234 and refund it in full.',
});

console.log(text);