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 = answer

View on GitHub (pinned to 24529f1404)

Solutions

  1. Parse the run ID from the message and check the checkpointed run status == 'paused'
  2. Use agent.Resume(ctx, ag, runID) with the recorded human input/approval to continue the run
  3. Configure approval policies so expected approvals are pre-authorized if pauses are unwanted
  4. Surface the pause message to a human approver rather than blindly retrying
  5. 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

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


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/988ebb7f01535626. Report an issue: GitHub.