Skip to content

Human In The Loop

Human-in-the-loop confirmation is handled by the agent runtime.

Custom provider implementations do not prompt the user directly. Instead, they attach a safety_decision payload to a ToolCall.

Tool Call Shape

from uisurf_agent import ModelTurn, ToolCall


return ModelTurn(
    tool_calls=[
        ToolCall(
            id="call_1",
            name="run_terminal_command",
            args={
                "command": "rm -rf ./tmp",
                "press_enter": True,
                "safety_decision": {
                    "decision": "require_confirmation",
                    "explanation": "This command deletes files from ./tmp.",
                },
            },
        )
    ]
)

Runtime Flow

Model emits ToolCall with safety_decision.require_confirmation
  -> BrowserAgent, DesktopAgent, or MobileAgent calls resolve_safety_prompt(...)
  -> CLI, A2A, or a custom UI asks the human
  -> approved: the action runs
  -> denied: the agent terminates with a denial message

Auto Mode

When --auto-mode or a Python API constructor sets auto_mode=True, safety-gated actions are approved automatically for that local run. A2A servers also read AUTO_MODE=true as their shared default.

Per-agent A2A environment overrides:

  • BROWSER_AGENT_AUTO_MODE
  • DESKTOP_AGENT_AUTO_MODE
  • MOBILE_AGENT_AUTO_MODE

Important Detail

The agent strips safety_decision before dispatching the actual tool:

args.pop("safety_decision", None)

This keeps controller methods focused on real action arguments.