OpenClaw EnterpriseDOCSGitHub

Console Agent editing and runtime requests

Overview

Related flows: parent, workspace files, stop and deletion.

Entry Points

Flow

graph TD
  subgraph Browser["Browser"]
    A["Read Agent or version"] -->|readable settings| B["Open detail action"]
    A -->|unreadable settings| AE["Show metadata and read error"]
    AE -->|refresh, retry or browse versions| A
    B --> C["Edit draft or save credential bindings"]
    B --> P["Edit Agent plugin selections"]
    B --> Q["Deploy saved draft"]
    B --> D["Read or write workspace files (workspace files trace)"]
    B --> E["Confirm Agent deletion (stop and deletion trace)"]
    B --> S["Confirm Agent stop (stop and deletion trace)"]
  end
  subgraph API["Controller API"]
    C --> F["Authorize exact request"]
    P --> PA["PATCH exact Agent plugin map"]
    PA --> F
    Q --> Y["Authorize and check deployment"]
    Y -->|missing, no earlier version| Z["Compute creates Agent-owned credentials"]
    Y -->|stored or not required| R["Admit immutable version"]
    Z -->|stored| R
    Z -->|failed or uncertain| N["Show recovery; create no version"]
    Y -->|missing after earlier version| N
    F -->|authentication saved| V["Confirm exact credential grant"]
    V -->|confirmed| W["Reload saved draft"]
    V -->|denied or interrupted| X["Show partial save and grant-only retry"]
    X -->|binding unchanged| V
  end

Execution Trace

4. Render draft, version, or channels

apps/controller/src/console/agents/detail.mts:renderAgentDetail

After reading the Agent, loadDetails settles history and snapshot independently. Rejected history warns beside readable drafts. Deploy stays unavailable. snapshotErrorPanel explains Configuration refusal and hides drafts. Numeric 401 returns to sign-in.

Browsing: packages/occ/src/index.ts:listAgents, listRevisions, getAgentForBrowsing, and getRevisionForBrowsing. packages/occ/src/state/postgres-state.ts:browseSavedConfiguration returns metadata plus configurationReadError on decode failure. Operational reads and queries stay strict. Unreadable drafts block editing and deployment without defaults. Selected for service uses activeRevisionId. Viewing version switches revision=draft/revision=<id> without activation. Load older versions appends, keeps selection and focuses the picker after the last page. deploymentStatus/deploymentErrorCode mark failures after reload, excluding superseded/stopped.

Deployment mounts activity, selected records, and diagnostics (agents/deployment-evidence.mts); polling spans tabs. Activity and label cannot anchor scrolling (console.css). detail.mts:renderTab offers Retry for transient snapshot errors. After FIRST_ACTIVITY_WAIT_MS, completion folds unless cleanup, warnings, repository access, or overview errors need attention; outcomes remain.

createDeploymentStatusPanel polls until completion or refusal; transient errors retain progress. invalidate and fail clear caches and reads. onFreshRecord shares matching GETs; show never republishes. Refusals override success; 401 expires sessions. terminalOverview reconciles outcomes once through shared Agent/history reads, excluding denied records. Retry failures explicitly. readingOverview protects explicit reads; recordGeneration rejects stale payloads. Refresh deployment queues a full reread; Refresh record preserves focus, ignoring repeats. Refusals open details; matching errors share alerts.

Each surface shows revision-specific repositoryAccess.message beside unchanged outcomes. Conditions reveal details without deploying. Missing guidance leaves repository health unknown.

agents/deployment-recovery.mts places failure recovery above the summary; deployment-failure-steps.ts classifies deploy-again, logs or change. Denied log/version reads hide Logs for this sign-in. Open Configuration requires Configuration update, bound Secret operate, and no known read denial. Read-only Open draft and Deploy again (deploy-again) require deploy and readable Configuration; the latter focuses Deploy new version. Credential recovery requires Agent saves. Hidden/unlisted current versions suppress recovery; viewed versions retain their results. Current observations in agents/deployment-diagnostics.mts requests timestamped succeeded, failed, or unknown diagnostics without changing deployment status. Its bodyless POST requires Agent read/operate and exact Agent revision read. Deploy new version admits the saved draft's Configuration and plugins. Edit current Configuration never copies historical values. Deploy stays disabled when the permission answer lists a bound Secret the caller cannot operate or counts one the caller can neither read nor operate. The count names no Secret (D756). After deployment, versions outside the newest page appear unreadable until an audited read (D758).

Before saving, parseEditor(true) rejects numbers parsed as infinity, including nested 1e400. The editor retains text, shows the error, and takes focus. Use a number closer to zero and retry.

detail.mts:saveConfiguration rereads Agent and Configuration before PATCHing { values, expectedGeneration }, preserving secretBindings. Changed IDs, stale generations, or concurrent-save conflicts require Reload draft. Responses must confirm Configuration/Namespace identity, newer generation, and submitted values/bindings. Reload before retrying unknown outcomes. Focus on Save Configuration moves to Checking Configuration…, then Edit Configuration on success unless focus moved. Conflicts retain local text. If focus moved, preserve focus, selection, and scroll. Otherwise, focus Reload draft and reveal the refusal.

Enable gateway password access and Collaboration and safety (agents/gateway-safety.mts) stage edits; Cancel discards them. Password access references Compute's OPENCLAW_GATEWAY_PASSWORD through the default env alias. Unsavable references replace the button with a hint. Deploy shows stored-configuration-rules.ts refusals in order, or Kubernetes-only agents/validate refusals.

Saves preserve scroll and admitted snapshots. Refusals keep edits. Unsaved edits block deployment. Pending saves block tab and version changes. On blocked Back/Forward, apps/controller/src/console/navigation.mts:traverse restores the address without reloading for missing or equal markers or impossible steps. Overflowed markers are untracked. A refused write lists required grants without guessing which; a refused preflight read names read access, a Workspace file save Agent operate. Without Agent update, Configuration read or bound-source grants (operate, and read on a Harness ServiceAccount; the note names both), plugins and repository access are summaries (dropping a kept plugin edit) and authentication is disabled. Reads the answer refuses are skipped. Lacking Configuration update makes Configuration and channels read-only; lacking operate on a bound Secret does too, unless, for channels, each such Secret has a Slack token name; with nothing editable, the draft says so and, without deploy, has no checklist.

agents/plugin-fields.mts:createPluginFields renders Plugins. agents/plugins.mts:savePlugins rereads the Agent before PATCH. If the Agent, Namespace, Configuration, selections, or approvers differ from the editor's baseline, it sends no write. This read does not lock the Agent. The editor clears the draft only when the response confirms that identity and the submitted settings. The page then rebuilds from that response, which also carries a Stop or deployment made since the page loaded. Reload plugin selections discards the local draft and reads the Agent without repeating the PATCH. A successful read rebuilds the editor from saved settings. If the read fails, the Console opens the draft page again. The Plugin Driver validates the selections before deployment snapshots the saved settings.

Repositories uses createRepositoryFields with exact-Agent discovery and PATCHes repositoryAccess. Unsaved edits also block tabs; failed discovery leaves access unverified.

Deployment rereads Agent and Configuration, requires authentication and Slack bindings, and blocks Teams. Reload if association, generation, authentication, plugins, execution mode, Backend, or repository access change. Pending requests lock controls. Snapshot views deploy current settings. Failed reads prevent the bodyless deploy POST. Success opens the version. Read history before retrying an uncertain POST. Browser reads are separate from admission.

apps/controller/src/console/drafts.mts:createDraftStore holds document-local drafts. console.mjs:resetReads and detail.mjs:renderTab capture fields before teardown, excluding passwords. Namespace and Agent keys isolate drafts; session expiry, user change, logout, exit, and reload clear them. Nothing enters browser storage or URLs. Configuration, authentication, and channel baselines prevent stale saves; channel snapshots include controls and staged Secret metadata. Reload draft reapplies only the reader's edits, naming overlaps and skipped choices. Save and Cancel clear captures; pending saves retain recovery guards.

dom.mts:dismissOnBackdrop requires press and click outside the topmost editor. Like Escape, cancellation discards channel drafts, clears Secret inputs, and retains plugin selections. Pending channel saves and Secret creation prevent dismissal.

apps/controller/src/console/channels.mjs:renderChannels renders Slack settings; only Open draft permits editing. The console reference owns Slack requirements and rejected native shapes; Teams remains native JSON.

agents/detail.mts:renderConfigurationTab reads draft Harness authentication from the Agent, or admitted authentication and channel secretBindings from the version. agents/secret-picker.mjs:renderSecretReference checks the source Namespace. Without Installation administrator access, it reads the readable Namespace's Secret list once per Agent view before exact metadata reads. Omitted Secrets show as unavailable without audited exact-read denials (2619). Successful reads show names and IDs. Names link to metadata and consumers at /console/secrets?secret=<id>. Secret fields link listed Secrets. Unlisted Secrets show the same unavailable text (D757). Absent, loading, and unavailable states stay distinct. Failures retain IDs. Stale responses are ignored. Current 401s expire the session. Summaries need neither collection permission nor Secret values.

apps/controller/src/console/channels/slack.mjs:appendFields separates channel senders from DMs. Wildcard, empty, or omitted channel users selects Allow everyone; explicit IDs fill the mutually exclusive input. Mention requirements remain independent. updatedSlack replaces selected channels' users, preserving DM and group policies, unrelated settings, and bindings.

The DM selector preserves omitted policies on existing configurations; new setup starts with Allowlist. validate rejects empty/wildcard DM allowlists and unsupported organization-wide policies. Selecting Open writes allowFrom: ["*"]; leaving it for Allowlist or Pairing clears the wildcard input. Untouched lists and native dm.enabled remain unchanged. Configuration save persists the selection; redeployment applies it. See Slack policies.

apps/controller/src/console/agents/detail.mts:renderAgentDetail supplies Namespace, bindings and Credentials URL to channels/slack.mjs:credentialReferenceField. GET /namespaces/:namespaceId/secrets requires Namespace read. packages/occ/src/index.ts:listSecrets filters exact Secret read without the Secret Driver. agents/secret-picker.mjs:createSecretReferenceField filters names and IDs. Arrows navigate, Enter stages a reference, Escape restores, and Cancel discards. Typing stages nothing. Refresh Secret list rereads metadata without saving and preserves query, focus, staged fields, and highlighted IDs across reordering. Select again if a highlight disappears. Pending reads disable refresh. Refused permission lists clear metadata and prevent pending selections from staging. Refresh clears its loading hint and keeps newer feedback. False Namespace secrets.create disables creation with reasons and existing-only drawer/Preset hints. Save configuration requires changed fields/bindings. GET .../agents/:agentId/permissions/secrets lists readable but inoperable Secrets, disabled with reasons, never staged. Refused binding saves reread it; inline creation rereads before staging. Any listed denial means per-Secret operate: new Secrets have none, disabling picker/Preset creation with reasons and existing-only hints. Failed rereads keep prior answers.

apps/controller/src/console/agents/secret-picker.mjs:openCreateSecretDialog shows an editable Agent-prefixed Name, the Secrets page's secretValueControl (CRLF becomes LF), and optional fixed Slack key. Both meet the API's rules before POST, which stores the Secret and stages returned metadata; cancellation never deletes it. Conflicts retain inputs. Readiness errors differ from name/backend conflicts. Success, cancellation, and uncertain outcomes clear values; uncertain outcomes block retries until refresh. The Secret storage flow owns persistence and recovery. Metadata and Credentials links open new tabs, preserving edits. Values are never retrieved.

Channel saves reread the Agent and Configuration. A changed Configuration, service principal, or generation requires Reload draft before a write or Secret grant. A provisioning reservation explains the refusal. PATCH sends { values, expectedGeneration }, plus every binding after a Secret change; a save keeping a Secret the caller cannot operate is refused before the PATCH, so Disable is offered disabled. A save that rebinds such a Secret rereads the permission answer; Plugins, Repositories and the authentication source follow it without a reload.

After PATCH, apps/controller/src/console/agents/credential-access.mjs:ensureCredentialOperateBinding grants the Agent service principal access to selected Secrets through Namespace IAM. A failed grant leaves Configuration saved; a 403 names the Installation administrator, who selects Retry Secret access; a timeout or 5xx stays unknown. A member's session sends no grant and says access was not verified until Reload draft. An administrator's console checks every bound Secret's grant, as deployment does, with Slack on or off; Deploy waits for those reads and rechecks before its POST, and a save or Retry during one reads again before naming Deploy. With Slack off, the section shows only while a bound Secret's grant waits, with only Retry (3018), whose success names the granted access. A Retry carries no Secret choices into Reload draft (3021). A Retry's warning names only the grant, and a later save's names the Configuration save (3023, 3029); after Reload draft the section waits for its grant read instead of restating that outcome. If it finds nothing outstanding, the section says access is confirmed and focuses that line (3030). agents/credentials.mjs:missingChannelCredentialGroups reads token keys as the Slack Channel Driver does; pickers appear only for standard keys. A 400 that agents/list.mjs:channelBindingRefusal matches shows the API's message. An uncertain PATCH blocks another channel write until Refresh. Disabling a draft channel changes Configuration but does not stop a running Agent.

5. Save authentication and deploy the first version

apps/controller/src/console/agents/detail.mts:renderAgentDetail rereads the Agent and rejects changed bindings before saving authentication. PATCH replaces the prior Harness credentialSources entry, preserving unrelated entries without deleting the old source or revoking grants. After PATCH, apps/controller/src/console/agents/credential-access.mjs:ensureCredentialOperateBinding grants the Agent service principal exact Secret (api_key or imported codex_pat) or CredentialSource operate through the actor's IAM authority. Managed ServiceAccount PATs and runtime authentication skip this grant.

Grant failure preserves saved authentication and freezes controls. credentials.mjs:grantWarning names the outcome; members send no grant and get no retry. Retry credential access rechecks identity and bindings before granting. Uncertain PATCH requires Reload authentication source. Pending access survives navigation and holds deployment until confirmed or reloaded; members' unverified grants do not. Administrator Namespace IAM denials also hold deployment. Admission remains authoritative; confirmed access does not prove provider readiness.

Authentication and JSON Save preflight 403 call detail.mts:retireSaveRead. The shell's onProtectedReadDenied clears that Agent's scoped drafts and retires its view before completion handlers run. The causal receipt and request ID remain; history cannot restore data. Binding preflight uses the same boundary. Retry receipts preserve prior saved-binding success and identify the failed read, without names or identifiers. No write or grant starts on denied preflight. Transient reads and PATCH refusals keep their contextual recovery. Lifecycle polling remains separately owned.

Deployment also authorizes the caller's Secret operate on each bound Secret. When the Agent's permissions/secrets answer lists one, Deploy is disabled with a note naming it; a generic deploy 403 rereads the answer and names them in its alert. A caller with Agent deploy but neither update gets an answer only on the Secrets the draft binds.

Operator-managed credentials saves { "method": "runtime" } without a source, requiring readable version history and an unchanged draft. API authorization and Driver compatibility remain authoritative.

Open draft shows bound Slack Secrets without proving live health.

OpenClawController.deployAgent checks transport credentials before admission. Before the first version, Agent read/operate plus deploy authorize Compute to check ownership/workloads and create missing whole Secrets, preserving matching groups. Bytes enter neither Configuration nor audit. Failure admits no version; retry rechecks status. Missing credentials after an earlier version require operator investigation. Model/channel Secrets stay separate.

6. Read and replace live workspace files

apps/controller/src/console/agents/workspace.mts:renderWorkspaceFiles. Moved to Agent workspace files.

7. Request a stop and read back the Agent

apps/controller/src/console/agents/stop.mts:createAgentStop. Moved to Agent stop and deletion.

8. Confirm deletion and read back the Agent

apps/controller/src/console/agents/deletion.mjs:createAgentDeletion. Moved to Agent stop and deletion.

Debugging and Verification

Search documentation