OpenClaw EnterpriseDOCSGitHub

Console Agent stop and deletion

Overview

Trace Stop Agent and Delete Agent on Agent detail and Agents list rows, from confirmation to readback. See the parent flow and Agent editing; steps 7 and 8 continue that trace's numbering.

Entry Points

Flow

graph TD
  subgraph Browser["Browser"]
    E["Confirm Agent deletion"]
    S["Confirm Agent stop"]
    L["Agents list row icon"] --> E
    L --> S
  end
  subgraph API["Controller API"]
    E --> G["DELETE exact Agent"]
    S --> T["POST exact Agent stop"]
    T -->|Console accepted or uncertain| U["Console refreshes desired state and selected version"]
    T -->|Console denied| I
    G -->|accepted or uncertain| H["Refresh exact Agent"]
    G -->|denied| I["Show access denied"]
    H -->|exists| J["Show current Agent state"]
    J -->|known deleting and manual request| E
    H -->|not found| K["Return to Agents list"]
  end

The CLI uses a separate request and output path:

graph TD
  CLI["CLI agent stop"] --> READ["Try advisory Agent GET"]
  READ -->|read succeeds or fails| POST["Submit exact Agent stop POST"]
  POST -->|accepted| OUT["Validate and print Agent and advice"]
  OUT -->|write failure| ERR["Exit nonzero without readback or retry"]
  ERR -->|manual operator action| GET["occ --namespace NAMESPACE agent get ID"]

Execution Trace

7. Request a stop and read back the Agent

A negative permission answer hides the Stop or Delete row, and the card when neither remains. If the dialog is open, it disables confirmation, focuses Cancel and keeps the row. A missing answer keeps the rows; late advice cannot recall a request.

apps/controller/src/console/agents/stop.mts:createAgentStop sends a bodyless POST to the Agent’s /stop route. OCC’s packages/occ/src/index.ts:stopAgent checks Agent operate, persists the requested stopped state, and queues reconciliation. Success means admission, not that Compute has shut down. Cancel restores focus to the invoking button; submission focuses Refresh stop status. A 403 about grants shows the Console's refusal with the Agent's name and the Request ID; any other 403 shows the API's text. Either way Stop stays unavailable, described by it, until a permission answer read after the refusal allows operate, such as the one a window refocus rereads. An answer read before the refusal, even one that arrives after it, does not lift it.

For a stopped Agent, Request Stop again confirms a new stop intent, even with no selected version; the Console cannot inspect history or candidate cleanup. Its confirmation says the Agent is already requested to stop and that this sends the request again. With no selected version and no readable versions yet (setNoReadableVersions), the Stop row is hidden unless the viewer just used it. A running Agent keeps Stop regardless of the latest readable deployment outcome (setLatestDeployment), as on the Agents list: a failed readable deployment can hide newer queued work. Agent operate still controls access. The latest readable outcome supplies confirmation text, not visibility. A queued or in-progress one says Stop cancels that deployment. An unreadable deployment or a failed read keeps the confirmation that names both outcomes; a succeeded one read before the Agent reread keeps the running-gateway text. The overview's Runtime row reports a requested stop. After an accepted Stop during a first deployment, the Stop row reports Deployment cancellation requested, not deployment or runtime completion. applyAgent clears that local result when either Stop readback or a detail-page update observes a running request or a selected version. An unchanged stopped read with no selected version keeps it.

Refresh reads desired state and selected version, not live health. Denial stays inline; changed state updates panels in place. If the read finds deletion in progress, Agent detail switches to the deletion recovery controls without sending a write. Focus moves to Refresh deletion status only when the reader stayed on the disappearing Stop control. An uncertain write blocks another Stop until readback succeeds. Deploy to resume; the lifecycle reference covers worker shutdown and preservation of versions, credentials, and state.

8. Confirm deletion and read back the Agent

apps/controller/src/console/agents/deletion.mts:createAgentDeletion

Delete Agent requests confirmation before sending a bodyless DELETE to the exact Agent URL. The controller requires Agent delete. A 403 shows the Console's refusal with the Agent's name and the Request ID, or the API's text when the refusal is not about grants. Delete Agent stays unavailable, described by it, until a permission answer read after the refusal allows delete. Acceptance starts asynchronous cleanup and marks the Agent deleting. The page rereads the exact Agent every few seconds; Refresh deletion status reads it on demand. A read error stops polling. Only a not-found read after an accepted or uncertain request, or when an already-deleting Agent is opened, returns to the Agents list in the selected Namespace. A 403 after the Agent was marked deleting means the caller can no longer follow cleanup. The Console stops polling and closes the repeat confirmation if it is open. If the reader confirmed a repeat while that status read was pending, the Console drops the unsent request. Neither action cancels a DELETE already sent or establishes whether cleanup finished.

An already deleting Agent keeps Request deletion again beside Refresh. It opens a cancel-first confirmation and sends the same bodyless DELETE only when the reader confirms. Queued or claimed work stays unchanged; terminal work can restart under the controller's existing current-permission and retry-ownership checks. The view does not infer a worker outcome from the Agent's deleting state or add a separate status contract.

An uncertain initial or repeated deletion blocks writes until a successful exact Agent read. A deleting read clears that guard even when the view was already deleting; a failed read does not. Cancel returns focus to the repeat-request button, and successful writes retain status refresh. The browser never retries DELETE automatically.

packages/occ/src/index.ts:deleteAgent owns deletion admission. The Agent deletion reference covers worker cleanup and the Namespace-owned resources it preserves.

Stop or delete from an Agents list row

apps/controller/src/console/agents/collection.mts:renderAgentList rows use the same Stop and Delete confirmations. Each row reads permission advice like its deployment, and reads it again when a retained list resumes. Refusal disables the action and explains why; in an open confirmation, it also disables confirmation and focuses Cancel. A stopped Agent without a selected version has no Stop action. A response that confirms the action for the requested Agent updates its row without polling. If the response names a different Agent, the list reports an unknown outcome and keeps the last observed state of both Agents. After 404, 409, or an uncertain outcome, the requested row’s actions stay disabled until Refresh rereads it. After a 403 about grants, the refused icon stays unavailable and the row's note names the grant under it, until a permission answer read later allows that action. Any other 403, such as retry ownership on a stale row, shows the API's text, the row's note points to it, and the row's actions stay unavailable, described by it, until Refresh. A window refocus that rebuilds the list shows that refusal again while the Agent is listed, and keeps focus on the same row control, scrolling only as far as needed to keep its cell and note in view. If that control is gone or disabled, focus goes to the row's name, or to the page heading when the row is gone.

CLI stop output

internal/occcli/cli.go:agentCommand also submits a stop through internal/occclient/client.go:StopAgent. It first tries to read the Agent to choose advice for an idle Agent, an earlier stop request, or a new stop request. After the POST, it validates the returned Agent identity, Namespace, and stopped intent, then prints that Agent to stdout and the advice to stderr.

Each advice branch returns its write error. cmd/occ/main.go:main exits nonzero when stderr cannot receive the notice. The stop has already been admitted and stdout may contain the Agent; this output failure does not undo or retry the stop. The CLI does not automatically read the Agent again after this failure. Run occ --namespace NAMESPACE agent get ID manually to inspect the Agent's state before deciding whether to submit another request. A successful notice still means requested intent, not completed shutdown.

Debugging and Verification

The Go regression TestAgentStopReturnsNoticeDeliveryErrors in internal/occcli/agent_stop_output_test.go covers all three CLI advice branches with an unavailable writer, retained JSON output, and one stop request. Compiled CLI proof can use a synthetic loopback HTTP peer and a read-only stderr descriptor to exercise the OS write failure. This proves output and exit handling, not controller persistence or Compute shutdown.

Search documentation