Human-in-the-loop for Mastra
Human-in-the-loop for Mastra agents and workflows.
Ask customers on their phone, with Mastra enforcing which actions require approval.
The integration
Add it to your Mastra agent
Pushary brings confirm, select and input questions to an enrolled customer in the native app. createPusharyAskTool collects an optional answer during a bounded request; it does not gate other tools. Use Mastra's native approval boundary for protected actions and its configured persistent storage for delayed reviews. Your backend validates the recorded response and resumes the intended run. Updated agent approval and deferred-review helpers are awaiting a forthcoming package release.
npm i @pushary/mastraimport { createPusharyAskTool, connect } from "@pushary/mastra"
await connect({ apiKey: process.env.PUSHARY_API_KEY! }, "user_123")
export const askHuman = createPusharyAskTool(
{ apiKey: process.env.PUSHARY_API_KEY! },
{ externalId: "user_123" },
)Why you need it
Mastra pauses the agent. Pushary reaches the human.
Mastra owns execution and persisted run state. Pushary reaches the customer and records their answer. Your application owns the decision-to-run mapping, response validation, resume trigger and recovery after an uncertain action. A webhook is a notification to your application, not automatic successful resumption. Follow the tested agent and workflow examples in the package README for the exact installed release and confirm its persistent storage requirements.
What Mastra already gives you
suspend() and run.resume()
A workflow step can suspend, and application code can later call run.resume(). Recovery across processes requires configured persistent Mastra storage and saved run identity. Validate resumeData against the expected review and authorized customer before using it to permit an action.
const approval = createStep({
id: "approval",
execute: async ({ suspend, resumeData }) => {
if (!resumeData) return await suspend({})
return { approved: resumeData.approved }
},
})Where it stops
- A suspended step is silent. Storage knows the run is waiting and no human does.
- run.resume() has to be called by something. You build the route that receives the answer and maps it back to the right runId.
- The snapshot holds workflow state, not an audit record of who approved and what they were shown.
Before you ship it
Things that bite on Mastra
- You need a correlationId to runId map
- The answer arrives on a webhook that knows about a decision, not about your workflow. Store the mapping when you suspend, or you will have an answer and no idea which suspended run it belongs to. This is the piece people forget until the first real approval comes back.
- resumeData is undefined on the first pass
- The step executes once to suspend and again to resume, through the same execute function. Forgetting the undefined branch on the first pass throws before it ever suspends.
- Agent tools and workflow steps are different tools for different waits
- The blocking ask tool suits a short question. Delayed agent reviews and workflow suspensions need persisted Mastra state plus application-owned response handling. An optional question is not enforcement, regardless of how long it waits.
How it works
From ask to resume
Connect the phone once, then ask a human from the tool or step that guards the action. The waiting, the delivery, and the record are handled for you.
- 01
Install the adapter
Run npm i @pushary/mastra and set your Pushary API key in the environment.
- 02
Connect the phone
Create an enrollment link for the authorized customer and have them complete it in the native app. Confirm can offer notification actions; select and input open the app. Bind externalId from trusted application context.
- 03
Add the tool or the step
Add createPusharyAskTool for optional questions. Gate protected actions through Mastra's approval boundary. For deferred work, use the package reference matching your installed version and configure persistent storage.
- 04
Resume on the answer
Your backend retrieves and validates the recorded answer, then resumes the intended Mastra run. Keep a protected action blocked without its required approval. Preserve select/input as data and handle timeout, denial and uncertain continuation separately.
A decision is a yes or no confirm, a multiple-choice select, or a free-text input. Every one is stored with its outcome and kept in the audit log.
The Partner plan
Your agent asks your users, not just you
Ship the agent to real users and let each of them approve their own decisions from their phone, under your brand.
Your users never see a Pushary login or bill.
Your users answer on their own phones
The externalId is your own id for the end-user. Connect their phone once with a keyless one-tap link that opens the Pushary app, and every approval lands with the right person. No account and no key on their side.
Durable, fail-closed waits
Pushary stores the decision; your application persists its own paused workflow and schedules resumption. Require an explicit, verified approval before acting. Pending, expired and cancelled requests are not approval.
Phone-first delivery
Pushary reaches the person on the device they carry: the app first, because it is the only channel that puts Approve and Deny on a lock screen, then PWA push notifications, then Slack if you route it there. You do not build a delivery pipeline.
Signed webhooks and an audit trail
Every decision is written to a durable ledger you can query and export, and resolved decisions post a signed webhook to your callback URL. You have the record of who approved what and when.
FAQ
Questions, answered
Is there a Mastra package for Pushary?
Should I use the tool or the workflow step?
What happens when nobody answers?
Can each of my end-users approve on their own phone?
Does the wait survive a restart or a deploy?
When should I use suspend() instead of a blocking ask tool?
Let your Mastra agent ask a human.
Connect a user with one tap, ask a human with one call, and act on a fail-closed decision. Every decision is saved to a durable ledger you can audit.
Start with PusharyPartner plan, $99 a month. Your users never see a Pushary login or bill.