Hosted OpenAI Agents API
Human in the loop for OpenAI's hosted Agents API. Save the required function call, get phone approval, then submit the exact tool result after checks.
The hosted Agents API keeps the session in OpenAI, but your application still runs the function tools. Put the approval in front of that run: save the required action, ask the right customer on their phone, then read the session again before you submit a result. If the customer denies, or nobody answers, the refund does not run.
git clone https://github.com/Pushary/pushary-openai-agents.git
cd pushary-openai-agents
npm install
npm run test:hostedThis page uses the hosted Agents API. If you run agents yourself with the OpenAI Agents SDK, use the OpenAI Agents SDK adapter instead.
Run the checked example
The public example source has three files: hosted-agent-review.mjs, delayed-review-store.mjs and check-hosted-agent-review.mjs. The commands above clone it and run its check.
The check uses the installed OpenAI SDK against a local transport simulation and a temporary SQLite file. It makes no refund and no live API call. It verifies:
- reopening the saved review
- pending, approve, deny, expiry and cancellation
- a changed native call and a customer mismatch
- concurrent resume attempts and an ambiguous submission
Approve a paused hosted session
You need Node.js 22.18+ within 22.x, or Node.js 24, for node:sqlite. You also need openai 7.15+, zod 4 and @pushary/server 2.1+. Keep the review database on persistent storage. Keep the customer and operation ids your application owns out of the model's control.
import { DatabaseSync } from 'node:sqlite'
import OpenAI from 'openai'
import { createReviewStore, openReview } from './delayed-review-store.mjs'
import { saveHostedReview, resumeHostedReview } from './hosted-agent-review.mjs'
const openai = new OpenAI()
const config = { apiKey: process.env.PUSHARY_API_KEY }
const store = createReviewStore(new DatabaseSync('./reviews.sqlite'))
const target = {
operationId: 'refund-order-1-v1',
externalId: 'customer-1',
framework: 'hosted-agents-v1',
codeVersion: 'refund-v1',
}
const session = await openai.beta.agents.sessions.retrieve(trustedSessionId)
saveHostedReview(store, target, session)
await openReview(config, store, target.operationId)
// Run again from your durable worker after the customer answers.
const result = await resumeHostedReview(config, store, target, openai, async (action, operationId) => {
return { simulated: true, operationId, action }
})trustedSessionId comes from your application's customer-to-session mapping. Connect target.externalId with the builder quickstart before you open the review.
The recipe accepts one pending refund call with orderId, an integer amount in EUR cents, and draftVersion. When you replace the simulation, call an idempotent operation at the real refund service.
What happens on deny, expiry or no answer
Denial, expiry and cancellation submit a failed tool result to the session. The refund never runs.
A changed pending call stops before the refund. Any ambiguous effect or submission leaves the review uncertain for you to reconcile by hand. Nothing retries it automatically.
The saved claim stops two local workers resuming at once. It cannot make an external refund and the OpenAI submission one atomic step.
Recover after a worker crash
A crash during continuation leaves the review resuming. Later workers return busy and never replay the refund.
- Stop every worker that could still own that operation.
- Call
store.recoverInterrupted(target.operationId)once. It moves only aresumingreview touncertainand returns whether it changed the record. Repeat calls are safe. - Reconcile the refund and the hosted session by hand before you choose a new operation.
Never run this recovery while a worker is active, and never reset the review to pending.
Wake the worker, then retrieve the session
The session stream event is agent.session.requires_action. The HTTP webhook is agent.session.action_required. Verify the OpenAI webhook signature, then retrieve the session to read required_actions. Older function_call items in the transcript are not permission to execute.
A Pushary answer callback or a durable poll wakes your worker. The worker still reads the saved decision and checks its customer, question and action binding. The callback alone does not authorize the refund.
OpenAI reference: function tools, session events and session webhooks.
Next steps
Try the approval sandbox
Simulate the phone answer in your browser, with no setup.
Connect your customers
Enroll a customer's phone and ask your first question.
See Pushary for agent builders
Customer enrollment, branding and Partner pricing.