Human approval
Mark a tool needs_approval: true, or give it a predicate on the
arguments, and the run suspends instead of executing it. Nothing sleeps and
no thread waits: the run returns immediately with the call parked.
reimburse = Mistri::Tool.define( "reimburse", "Issues an expense reimbursement.", needs_approval: ->(args) { args["amount_usd"].to_i > 1000 },) do |args| Expense.reimburse!(args)end
result = agent.run("Reimburse Dana's $1,200 conference travel")result.awaiting_approval? # => true; nothing executedresult.pending # the calls waiting on a decisionSmall reimbursements go straight through; only the ones over the threshold park for a human.
Deciding
The decision is a one-line session write from any process, any time later. A controller action is enough:
session = Mistri::Session.new(store:, id: session_id)session.approve(call_id)session.deny(call_id, note: "receipts don't match the report")Resuming
resume settles the parked calls and carries on. Approved calls execute;
denied calls answer the model with your note, in band, so it can adjust.
Mistri.agent("claude-opus-4-8", tools: tools, session: session) .resumeThe harness renders nothing. It emits an :approval_needed event and your
app draws the buttons, which is exactly the approval demo on the front
page.