DocsHuman-in-the-Loop

Human-in-the-Loop

Insert human approval steps into your agent workflows for sensitive operations.

The Safety Problem#

You don't want an agent to delete a production database or send an email to the CEO without checking first. Akios allows tools to pause execution and wait for permission.

1

Flag Tool as 'Requires Approval'

tools/email.ts
const sendEmail = new Tool({
  name: 'send_email',
  description: 'Sends an email to a user.',
  schema: z.object({ 
    to: z.string(), 
    subject: z.string(), 
    body: z.string() 
  }),
  // CRITICAL: This flag pauses the agent
  requiresApproval: true, 
  
  execute: async ({ to, subject, body }) => {
    await mailer.send({ to, subject, body })
    return "Email sent successfully."
  }
})
2

Handle the Interruption

When the agent tries to call this tool, `run()` will return early with a status of `paused`.

server.ts
const result = await agent.run("Send an email to boss@corp.com saying 'I quit'")

if (result.status === 'paused' && result.pendingToolCall) {
  const { tool, input } = result.pendingToolCall
  
  // 1. Show UI to user
  console.log(`Agent wants to ${tool} with inputs:`, input)
  console.log("Approve? (y/n)")
  
  // 2. Wait for user input (mocked here)
  const userApproved = true 
  
  // 3. Resume execution
  if (userApproved) {
    const finalResult = await agent.resume(result.id, { approved: true })
    console.log(finalResult.output)
  } else {
    const finalResult = await agent.resume(result.id, { 
      approved: false, 
      feedback: "Don't do that. Be polite." 
    })
    console.log(finalResult.output) // Agent will likely apologize and retry
  }
}

Persistent State

For this to work in a web app, you need a persistent `MemoryStore` so the agent can be rehydrated when the user approves (which might be hours later).