micro/go-micro · warning
agent run %s paused for approval: %s
Error message
agent run %s paused for approval: %s
What it means
When a tool call requires human approval, the agent pauses the run (agent/agent.go:473), persists the run with status 'paused', and returns this error naming the run ID and the pause message. It signals that execution stopped awaiting an approval decision, not that the run failed permanently.
Source
Thrown at agent/agent.go:473
run.Steps[0].ErrorKind = string(failureKind)
_ = a.saveRun(ctx, run)
return nil, err
}
if a.pause != nil && a.opts.Checkpoint != nil {
run.Status = "paused"
run.State.Stage = agentApprovalStep
run.State.Data = []byte(message)
if a.pause.Tool == toolHumanInput {
run.State.Stage = agentInputStep
_ = run.State.Set(inputPause{OriginalMessage: message, Prompt: a.pause.Message})
}
run.Steps[0].Status = "paused"
run.Steps[0].Error = a.pause.Message
run.Steps[0].Result = a.pause.Tool
if err := a.saveRun(ctx, run); err != nil {
return nil, err
}
return nil, fmt.Errorf("agent run %s paused for approval: %s", run.ID, a.pause.Message)
}
if len(resp.ToolCalls) == 0 {
if calls, answer, ok := a.executeTextToolCalls(ctx, resp.Reply, toolList); ok {
resp.ToolCalls = calls
if resp.Answer == "" {
resp.Answer = answer
}
trimmedReply := strings.TrimSpace(resp.Reply)
if strings.HasPrefix(trimmedReply, "{") || strings.HasPrefix(trimmedReply, "[") || strings.HasPrefix(trimmedReply, "```") {
resp.Reply = ""
}
}
} else if calls, answer, ok := a.executeAdditionalTextToolCalls(ctx, resp.Reply, toolList, resp.ToolCalls); ok {
resp.ToolCalls = append(resp.ToolCalls, calls...)
if answer != "" {
if resp.Answer == "" {
resp.Answer = answerView on GitHub (pinned to 24529f1404)
Solutions
- Parse the run ID from the message and check the checkpointed run status == 'paused'
- Use agent.Resume(ctx, ag, runID) with the recorded human input/approval to continue the run
- Configure approval policies so expected approvals are pre-authorized if pauses are unwanted
- Surface the pause message to a human approver rather than blindly retrying
- Auto-retry is useless: the run only proceeds after approval input
Example fix
// before
resp, err := ag.Ask(ctx, msg)
if err != nil { return err } // treats pause as fatal
// after
resp, err := ag.Ask(ctx, msg)
if err != nil && strings.Contains(err.Error(), "paused for approval") {
runID := extractRunID(err.Error())
resp, err = agent.Resume(ctx, ag, runID) // after approval is granted
}
Defensive patterns
Strategy: validation
Validate before calling
// before calling, check the run's checkpointed status
run, ok, _ := checkpoint.Load(ctx, runID)
if ok && run.Status == "paused" {
// must resume with human input, not re-Ask
} Try / catch
resp, err := ag.Ask(ctx, msg)
if err != nil {
var pe PauseError
if strings.Contains(err.Error(), "paused for approval") {
runID := extractRunID(err.Error())
// notify approver, then: agent.Resume(ctx, ag, runID)
return handleApproval(runID, err)
}
return err
} Prevention
- Always special-case approval-pause errors; never treat them as fatal
- Pre-authorize trusted tools to reduce approval pauses
- Build an approval UI/queue that feeds decisions back via Resume
- Log run IDs from pause errors for later resumption
When it happens
Trigger: A model tool call targets a tool guarded by the approval/pause policy during Ask/Stream; the agent saves the run as paused and returns this error to the caller.
Common situations: Workflows with human-in-the-loop approval on dangerous tools (writes, deployments); automated callers that treat every error as fatal instead of detecting the pause and resuming with an approval decision.
Related errors
- agent: checkpointed run is input-required; resume with Resum
- agent: StreamAsk unsupported by implementation
- agent: ResumeStreamAsk unsupported by implementation
- agent: ResumeStreamAsk requires a checkpoint
- agent: checkpointed run not found
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/988ebb7f01535626.
Report an issue: GitHub.