Skip to content

feat(webui): reintroduce opt-in AI purpose titles for tool calls#103989

Merged
steipete merged 2 commits into
mainfrom
claude/tool-titles-opt-in-04de3c
Jul 11, 2026
Merged

feat(webui): reintroduce opt-in AI purpose titles for tool calls#103989
steipete merged 2 commits into
mainfrom
claude/tool-titles-opt-in-04de3c

Conversation

@steipete

@steipete steipete commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes #103987.

PR #103748 shipped AI purpose titles for tool calls; #103821 removed them because the feature was always-on — rendering a chat could trigger model calls, route tool arguments to a provider, spend utility-model tokens, and persist a cache purely for decorative labels. The titles themselves remain wanted (#103554): long agent sessions read far better when complex calls say "Ran linked list tests" instead of a raw command.

Why This Change Was Made

Reintroduces the titles path with the #103821 objections answered by an explicit opt-in: default behavior is exactly what main ships today — fully deterministic tool rendering with zero background model calls.

User Impact

  • New gateway.controlUi.toolTitles config key, default false (schema, types, help/labels/tags, and configuration-reference docs included).
  • With the default off: chat.toolTitles answers { titles: {}, disabled: true } without loading the completion runtime, and the Control UI stops asking for the rest of the session (one lightweight probe per connection, no retries).
  • When enabled: complex calls (long shell commands, argument-heavy plugin/MCP tools) get short purpose titles rendered as the primary row text with the command dimmed beside it. Model selection delegates to the canonical utility-model resolver (resolveUtilityModelRefForAgent): the agent's utilityModel, else the primary provider's declared small-model default (OpenAI → gpt-5.6-luna, Anthropic → claude-haiku-4-5) — same provider as the session, so no new egress destination — and the documented utilityModel: "" opt-out disables titles like every other utility task. Titles never fall back to the primary model. Results cache in the per-agent SQLite cache_entries (scope tool-call-titles), so repeat views never re-bill. All errors fail closed to deterministic labels.
  • The restored code is the final reviewed state from feat(webui): redesign tool-call rendering with inline diffs, group summaries, and cheap-model purpose titles #103748 (11 structured review rounds: bounded batches, split-pane session/agent/client capture at schedule time, lit-guard repaint on title arrival, capped inputs), adapted to the reworked rendering from fix(webui): keep tool activity paired without model calls #103821 (outcome-based rows) without touching its deterministic pairing/diff behavior.

Protocol surface is additive: ChatToolTitlesParams/ChatToolTitlesResult (result gains the disabled flag), validator, operator.write descriptor (spends tokens on cache misses when enabled), regenerated dist/protocol.schema.json + Swift GatewayModels.swift.

Evidence

  • Unit tests green: src/gateway/chat-tool-titles.test.ts (title generation, SQLite cache hit, fail-closed preparation, canonical utility-model ref selection, disabled/no-default skip) and ui/src/pages/chat/tool-titles.test.ts (eligibility, digest stability, session/agent capture across pane reconfiguration, and the new disabled-gateway stop test), plus the adjacent renderer/protocol/config suites (chat-tool-cards, chat-message, chat-thread, gateway-protocol index, config-misc) — 210+ assertions locally, full gates re-run by PR CI.
  • Scoped oxlint clean across changed areas; protocol JSON + Swift regenerated in the same commit (protocol:check parity).
  • Structured second-model review (Codex gpt-5.5) run on the branch before landing; see PR review artifacts.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation app: web-ui App: web-ui gateway Gateway runtime size: XL maintainer Maintainer-authored PR labels Jul 10, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8724051654

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/gateway/chat-tool-titles.ts Outdated
Comment on lines +197 to +198
resolveAgentConfig(cfg, agentId)?.utilityModel?.trim() ||
cfg.agents?.defaults?.utilityModel?.trim(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Honor empty utility-model opt-outs

In configs where an agent sets utilityModel: "" (or an empty per-agent value to override a default utility model), this || treats the empty string as absent and either falls back to agents.defaults.utilityModel or to the Luna default in generateMissingTitles. That bypasses the existing utility-model contract in src/agents/utility-model.ts that an empty value is an explicit opt-out, so enabling gateway.controlUi.toolTitles can still send tool arguments to a utility/OpenAI model for agents that explicitly disabled utility routing; use readUtilityModelSetting or otherwise preserve the disabled state before preparing a title model.

Useful? React with 👍 / 👎.

@clawsweeper

clawsweeper Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 10, 2026, 10:14 PM ET / July 11, 2026, 02:14 UTC.

Summary
Adds default-off AI-generated purpose titles for complex Control UI tool calls through a gateway RPC, utility-model routing, per-agent SQLite caching, UI rendering, tests, docs, and generated protocol models.

PR surface: Source +801, Tests +460, Docs +4, Other +40. Total +1305 across 24 files.

Reproducibility: yes. for the patch defects: the stale-cache, global-failure, profile-routing, and pre-redaction truncation paths are directly reproducible from the exact merged source. The requested capability itself is a feature rather than a broken-behavior reproduction.

Review metrics: 3 noteworthy metrics.

  • Config/default surfaces: 1 added, default off. The new setting expands the supported configuration contract and requires upgrade-safe documentation and proof.
  • Protocol methods: 1 additive write-scoped RPC. The method can spend utility-model tokens and write persistent cache state, so authorization and compatibility matter beyond UI tests.
  • Persistent cache scopes: 1 added. Generated labels become per-agent SQLite state that must obey opt-out, credential, and lifecycle boundaries.

Stored data model
Persistent data-model change detected: serialized state: src/gateway/chat-tool-titles.test.ts, serialized state: ui/src/pages/chat/tool-titles.test.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #103987
Summary: This PR is the implementation candidate for the open opt-in tool-title issue; the earlier merged PRs document the feature's introduction and intentional removal.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🦪 silver shellfish
Result: blocked until real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Fix all five context, routing, and redaction findings with focused regression coverage.
  • Attach redacted exact-head Control UI proof for default-off, enabled, and gateway/profile switching behavior.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body has tests and CI claims but no exact-head after-fix real Control UI run showing default-off behavior, enabled title generation, or gateway/profile switching. Add redacted screenshots, a recording, live output, or logs; updating the PR body should trigger a fresh review, or a maintainer can comment @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Mantis proof suggestion
After the source blockers are repaired, web UI chat proof can directly demonstrate deterministic default-off rows, enabled purpose titles, and state changes across a gateway switch. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis web UI chat proof: verify default-off deterministic tool rows, enabled AI purpose titles, and title removal after switching to a disabled gateway; return redacted transcript and diagnostics.

Risk before merge

  • [P1] Even after the concrete defects are repaired, maintainers must explicitly decide whether decorative provider egress, utility-model spend, persistent generated-title state, and the new public config/protocol surfaces are acceptable.
  • [P1] Fresh-install and upgrade behavior for the new setting and RPC has no exact-head real setup proof, and any force-push or rebase will require a fresh review of the resulting head.

Maintainer options:

  1. Repair and prove the opt-in path (recommended)
    Fix browser context state, provider/profile routing, and first-boundary redaction, then provide fresh-install, upgrade, and live switching proof before maintainer acceptance.
  2. Retain deterministic rendering
    Pause or close the proposal if decorative model egress and persistent title caching are not worth the additional public surfaces.

Next step before merge

  • [P1] The protected maintainer label and unresolved product decision require human handling; the contributor can repair the concrete findings, but ClawSweeper should not automatically promote a fix job.

Maintainer decision needed

  • Question: Should OpenClaw accept a new default-off Control UI setting and gateway RPC that sends bounded tool arguments to utility-model providers and persists generated titles?
  • Rationale: The implementation defects can be repaired mechanically, but accepting decorative provider egress, token spend, persistent cache state, and new public configuration and protocol surfaces requires explicit product ownership.
  • Likely owner: steipete — The related issue, original implementation, intentional removal, and current shared-path history all point to this person as the best available decision owner.
  • Options:
    • Accept after repair (recommended): Keep the opt-in design, but require all source findings, upgrade evidence, and exact-head real behavior proof before merge.
    • Retain deterministic UI: Decline the model-backed title path and keep current main's deterministic tool rendering without decorative provider calls.

Security
Needs attention: Tool-argument provider egress and persistent caching are intentional, but pre-redaction browser truncation and provider-incompatible credential rewriting remain concrete security concerns.

Review findings

  • [P2] Clear cached titles when the gateway client changes — ui/src/pages/chat/tool-titles.ts:119-121
  • [P2] Scope failed title keys to the fetch context — ui/src/pages/chat/tool-titles.ts:150
  • [P2] Drop inherited profiles for provider-overridden sessions — src/gateway/chat-tool-titles.ts:339-341
Review details

Best possible solution:

Keep the feature default-off, scope all browser state to the active client/session/agent, preserve provider-correct credential profiles, redact before the first truncation boundary, and prove fresh and switched-gateway behavior before explicit maintainer acceptance.

Do we have a high-confidence way to reproduce the issue?

Yes for the patch defects: the stale-cache, global-failure, profile-routing, and pre-redaction truncation paths are directly reproducible from the exact merged source. The requested capability itself is a feature rather than a broken-behavior reproduction.

Is this the best way to solve the issue?

No, not yet. A default-off opt-in is the narrowest plausible product shape, but the submitted implementation still violates client-context, credential, and redaction boundaries and lacks exact-head live proof.

Full review comments:

  • [P2] Clear cached titles when the gateway client changes — ui/src/pages/chat/tool-titles.ts:119-121
    getToolCallTitle returns a process-global cached title before a newly selected gateway can report disabled: true, while configureToolTitleFetcher resets only the disabled flag. Switching from an enabled gateway to a disabled one therefore keeps showing AI labels; clear or context-key cached titles when the client changes.
    Confidence: 0.99
  • [P2] Scope failed title keys to the fetch context — ui/src/pages/chat/tool-titles.ts:150
    A missing result or transient request error adds the digest to the process-global failedKeys, and changing client, session, or agent never clears it. The same call can remain permanently untitled after switching to a context with a valid utility route; scope or reset failures with the fetch context.
    Confidence: 0.99
  • [P2] Drop inherited profiles for provider-overridden sessions — src/gateway/chat-tool-titles.ts:339-341
    When no session profile exists, this keeps resolvedRef verbatim even though the utility resolver can append the agent primary model's @profile. A session override to another provider can therefore prepare that provider with a stale profile suffix; strip the inherited profile when the effective provider differs.
    Confidence: 0.96
  • [P2] Do not apply a session profile to another provider — src/gateway/chat-tool-titles.ts:339-341
    When an explicit utility model uses a different provider, this unconditionally replaces its profile with the session provider's auth profile. That can lock the request to a nonexistent or wrong credential; apply session profiles only to provider-compatible derived refs and preserve explicit cross-provider profiles.
    Confidence: 0.97
  • [P1] Redact tool input before the UI truncates it — ui/src/pages/chat/tool-titles.ts:71-75
    Late discovery: this browser code is byte-identical to the prior reviewed head. It slices strings and serialized arguments before the gateway redactor sees them, so secrets or contextual patterns crossing that first cutoff can arrive as unrecognizable fragments; redact before the first slice or send the full protocol-bounded input for gateway redaction.
    Confidence: 0.94
    Late finding: first raised on code an earlier review cycle already covered.

Overall correctness: patch is incorrect
Overall confidence: 0.97

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against b7156ce68884.

Label changes

Label justifications:

  • P2: This is an optional Control UI improvement with meaningful but bounded compatibility, privacy, and provider-routing impact.
  • merge-risk: 🚨 compatibility: The PR adds a public setting, gateway method, generated client models, and persistent cache behavior requiring fresh-install and upgrade proof.
  • merge-risk: 🚨 auth-provider: The current model-reference rewrite can preserve or attach an auth profile belonging to the wrong provider during session overrides.
  • merge-risk: 🚨 security-boundary: The feature sends tool arguments to model providers and persists derived labels, making redaction and credential boundaries merge-critical.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🦪 silver shellfish.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body has tests and CI claims but no exact-head after-fix real Control UI run showing default-off behavior, enabled title generation, or gateway/profile switching. Add redacted screenshots, a recording, live output, or logs; updating the PR body should trigger a fresh review, or a maintainer can comment @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source +801, Tests +460, Docs +4, Other +40. Total +1305 across 24 files.

View PR surface stats
Area Files Added Removed Net
Source 18 801 0 +801
Tests 2 460 0 +460
Docs 3 4 0 +4
Config 0 0 0 0
Generated 0 0 0 0
Other 1 40 0 +40
Total 24 1305 0 +1305

Security concerns:

  • [high] Pre-redaction truncation can expose secret fragments — ui/src/pages/chat/tool-titles.ts:71
    The browser's first 2,000-character slice occurs before the gateway redactor, so a secret or context-dependent pattern spanning the cutoff can be transmitted and cached as an unrecognized fragment.
    Confidence: 0.94
  • [medium] Profile rewriting can select the wrong credential — src/gateway/chat-tool-titles.ts:339
    The resolved utility model can inherit or receive an auth profile belonging to another provider, causing failed or unintended credential selection for tool-title egress.
    Confidence: 0.97

What I checked:

  • Actual merge result: GitHub's synthetic merge commit combines current main with the exact PR head, and the reviewed defects survive that three-way merge rather than arising from stale-base drift. (ui/src/pages/chat/tool-titles.ts:119, 026af4292d66)
  • Cached-title lifecycle: The UI returns a process-global cached title before a newly selected gateway can report that titles are disabled, while client changes reset only the disabled flag. (ui/src/pages/chat/tool-titles.ts:119, eae25df377da)
  • Failed-key lifecycle: Missing results and transient request errors enter one process-global failedKeys set that is not cleared or scoped when the client, session, or agent changes. (ui/src/pages/chat/tool-titles.ts:150, eae25df377da)
  • Credential routing: The exact head preserves an inherited profile when no session profile exists and unconditionally attaches the session profile when one exists, without checking provider compatibility. (src/gateway/chat-tool-titles.ts:339, eae25df377da)
  • First truncation precedes redaction: The browser slices commands and serialized arguments to 2,000 characters before the gateway redactor receives them; the shared redactor explicitly recognizes that complete tokens or contextual patterns can cross boundaries. (ui/src/pages/chat/tool-titles.ts:71, eae25df377da)
  • Feature provenance: The behavior was introduced by the merged tool-rendering redesign and intentionally removed less than an hour later by the deterministic follow-up; current main does not contain the model-backed title path. (ui/src/pages/chat/components/chat-tool-cards.ts:1, 5aea34ad8c21)

Likely related people:

  • steipete: Merged history shows this person introduced the original title path, authored its deterministic removal, and recently maintained the shared utility-model and redaction paths used by this proposal. (role: feature owner; confidence: high; commits: fc2afc83da4d, 5aea34ad8c21, 31703debcb; files: ui/src/pages/chat/components/chat-tool-cards.ts, src/agents/utility-model.ts, src/logging/redact.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (5 earlier review cycles)
  • reviewed 2026-07-11T00:23:59.545Z sha 7151d6f :: needs real behavior proof before merge. :: [P1] Enforce the documented same-provider title route | [P2] Clear or scope titles when the Gateway changes | [P2] Notify every pane waiting on a shared title
  • reviewed 2026-07-11T00:41:04.869Z sha a69d824 :: needs real behavior proof before merge. :: [P1] Enforce or disclose cross-provider title routing | [P2] Clear cached titles when the active gateway changes | [P2] Retain every pane waiting on the same title key | [P2] Strip stale agent profiles for session provider overrides
  • reviewed 2026-07-11T00:48:09.467Z sha 56edd03 :: needs real behavior proof before merge. :: [P2] Reset cached titles when the active gateway changes | [P2] Scope failed title keys to the active fetch context | [P2] Drop inherited agent profiles for session provider overrides
  • reviewed 2026-07-11T01:06:33.331Z sha 1edb9b0 :: needs real behavior proof before merge. :: [P2] Reset cached titles when the active gateway changes | [P2] Scope failed title keys to the fetch context | [P2] Drop inherited profiles for session provider overrides | [P2] Do not apply a session profile to another provider
  • reviewed 2026-07-11T01:14:01.177Z sha 1edb9b0 :: needs real behavior proof before merge. :: [P2] Clear cached titles when the gateway client changes | [P2] Scope failed title keys to the active fetch context | [P2] Drop inherited profiles for session provider overrides | [P2] Do not apply a session profile to another provider | [P1] Redact tool-title input before truncating it

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 346002d9e7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +149 to +151
pendingKeys.has(request.key) ||
failedKeys.has(request.key) ||
queue.has(request.key)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Notify every pane waiting on a title

When two split panes render the same eligible tool call before the first title request completes, the second pane hits pendingKeys/queue.has and returns without recording its own notify callback. The title is then stored globally, but only the first queued item's head.notify?.() runs, so the other pane's guarded chat subtree never re-renders and keeps the deterministic row until some unrelated update occurs. Track waiters per key or notify all affected panes when a shared title lands.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4a20e719d2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +3393 to +3397
const titles = await generateToolCallTitles({
cfg: sessionCfg,
agentId: sessionAgentId,
sessionPrimaryProvider: sessionModel.provider,
items: params.items,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve session auth profiles for title calls

When a session is using a session-scoped auth profile (entry.authProfileOverride, e.g. a model selection with @profile), this call only forwards the resolved provider. generateToolCallTitles then prepares the utility model without the session profile, while the normal run path does carry authProfileOverride into model execution, so enabling tool titles can send tool arguments through the provider's default credential/account or fail even though the chat session itself has working auth. Please thread the loaded session profile through the title generation path before making the utility-model call.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 821b7fceb0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +300 to +304
const resolvedRef = resolveUtilityModelRefForAgent({
cfg: params.cfg,
agentId: params.agentId,
primaryProvider: params.sessionPrimaryProvider,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Enforce the same-provider title route

When an agent has an explicit utilityModel on a different provider than the session primary, resolveUtilityModelRefForAgent returns that explicit ref before using sessionPrimaryProvider, so this new path sends tool names and bounded inputs to a provider the session was not using despite the in-code/docs guarantee that title generation stays on the session provider. In that configuration, either reject/skip cross-provider utility refs for tool titles or update the contract so operators know enabling this can add a new egress destination for tool arguments.

Useful? React with 👍 / 👎.

Comment on lines +119 to +121
const cached = titlesByKey.get(request.key);
if (cached) {
return cached;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clear cached titles when the gateway disables them

Because cached titles are returned before checking the current gateway/client disabled state, a browser that previously viewed an enabled gateway can reconnect to, or switch to, a gateway with gateway.controlUi.toolTitles off and still render the old AI title for the same tool input without ever probing chat.toolTitles for the disabled response. This breaks the opt-out/deterministic rendering contract after restarts or config changes; clear/key the client cache on client changes or suppress cached titles once the active gateway is disabled.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7151d6f859

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +327 to +329
const modelRef = params.sessionAuthProfile
? `${strippedRef}@${params.sessionAuthProfile}`
: resolvedRef;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Drop stale agent-profile suffixes for session overrides

When a session switches to another provider without an authProfileOverride, this branch keeps resolvedRef verbatim. resolveUtilityModelRefForAgent can append the agent primary model's trailing @profile even when primaryProvider was supplied, so an agent default like openai/gpt@work plus a session override to Anthropic will prepare anthropic/<utility>@work even though the chat session itself uses the default Anthropic credential. Fresh evidence beyond the earlier session-profile issue: the fixed sessionAuthProfile branch rewrites profiles, but the no-session-profile branch still preserves the stale agent-primary profile.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 11, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a69d824c57

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

!activeSessionKey ||
titlesByKey.has(request.key) ||
pendingKeys.has(request.key) ||
failedKeys.has(request.key) ||

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Scope failed title keys to the active fetch context

When one request returns no title for an item, this process-global failedKeys guard blocks the same tool-name/input digest for every later client, session, and agent. For example, if agent A has no usable utility route (or a transient disconnect/older gateway makes the batch fail), the key is marked failed; opening the same command in agent B after reconnect or after fixing config will return here and never ask the gateway that could now generate the title, leaving that call stuck on deterministic labels until a page reload. Key failures by client/session/agent or clear them when the fetch context changes.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 56edd037e3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +331 to +333
const modelRef = params.sessionAuthProfile
? `${strippedRef}@${params.sessionAuthProfile}`
: resolvedRef;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid applying session profiles to other providers

Fresh evidence beyond the earlier session-profile comments: the new rewrite now applies the session auth profile even when the resolved utility ref is an explicit different provider. In a session using authProfileOverride: "work" for Anthropic with utilityModel: "openai/gpt-5.6-luna", this turns the utility ref into openai/gpt-5.6-luna@work; prepareSimpleCompletionModelForAgent then treats that suffix as a locked profile, and the profile-id path in src/agents/model-auth.ts:1149 resolves it before generic OpenAI fallback, so title generation can fail or attempt the wrong credential despite the docs allowing explicit cross-provider utility models. Only replace the embedded profile for same-provider/derived refs, or preserve the explicit utility model's own profile.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. labels Jul 11, 2026
@clawsweeper clawsweeper Bot removed merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 11, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1edb9b08a2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/gateway/chat-tool-titles.ts Outdated
// args can carry raw tokens/signed URLs, and titles must not become a new
// secret egress path. Redaction runs in tools mode regardless of logging
// config.
const input = redactToolPayloadText(item.input.slice(0, TOOL_TITLE_INPUT_MAX_CHARS));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Redact tool-title input before truncating

When a secret-bearing tool input crosses the 2,000-character cutoff, slicing first can turn a registered secret or prefix-pattern token into an unrecognized fragment before redactToolPayloadText runs, so that fragment can still be cached and sent to the utility model despite the redaction contract. The protocol already bounds each input, so redact the received string first and then truncate the redacted result (and keep the UI cap aligned) to avoid boundary leaks.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jul 11, 2026
Restores the chat.toolTitles path removed in #103821, gated behind the new
gateway.controlUi.toolTitles opt-in (default false) so tool rendering stays
fully deterministic with no background model calls unless an operator enables
it. Disabled gateways answer { titles: {}, disabled: true } without loading
the completion runtime, and clients stop asking for the session.

When enabled, titles use canonical utility-model routing: an explicit
utilityModel (operator-chosen provider, like every utility task), else the
session provider's declared small-model default, honoring per-session model
overrides and auth profiles; utilityModel "" disables titles and malformed
refs fail closed — never the primary model. Tool inputs are redacted with the
tools-mode redactor before cache keys or prompts, caller ids are bounded and
never reach the model, and results cache in the per-agent SQLite
cache_entries so repeat views never re-bill.

Also completes two crestodian model-input mock factories that leaked into
sibling tests under shared-registry CI shards.

Fixes #103987
@steipete
steipete force-pushed the claude/tool-titles-opt-in-04de3c branch from 1edb9b0 to 3560594 Compare July 11, 2026 02:03

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eae25df377

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (command.length < MIN_COMMAND_CHARS_FOR_TITLE) {
return null;
}
const input = command.slice(0, MAX_TITLE_INPUT_CHARS);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Redact UI tool-title inputs before slicing

Fresh evidence beyond the earlier server-side truncation concern: this browser path still slices the raw command before the gateway redactor sees it. When a secret-bearing command crosses the 2,000-character UI cutoff (for example an Authorization token beginning near the boundary), only an unrecognizable prefix is sent in chat.toolTitles, so redactToolPayloadText cannot match the full token and that fragment can still be cached and sent to the utility model; redact before this slice or send the bounded raw input to the gateway for redact-then-truncate handling.

Useful? React with 👍 / 👎.

@steipete
steipete merged commit 7b5854b into main Jul 11, 2026
100 checks passed
@steipete
steipete deleted the claude/tool-titles-opt-in-04de3c branch July 11, 2026 02:18
@steipete

Copy link
Copy Markdown
Contributor Author

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 11, 2026
…nclaw#103989)

* feat(webui): reintroduce opt-in AI purpose titles for tool calls

Restores the chat.toolTitles path removed in openclaw#103821, gated behind the new
gateway.controlUi.toolTitles opt-in (default false) so tool rendering stays
fully deterministic with no background model calls unless an operator enables
it. Disabled gateways answer { titles: {}, disabled: true } without loading
the completion runtime, and clients stop asking for the session.

When enabled, titles use canonical utility-model routing: an explicit
utilityModel (operator-chosen provider, like every utility task), else the
session provider's declared small-model default, honoring per-session model
overrides and auth profiles; utilityModel "" disables titles and malformed
refs fail closed — never the primary model. Tool inputs are redacted with the
tools-mode redactor before cache keys or prompts, caller ids are bounded and
never reach the model, and results cache in the per-agent SQLite
cache_entries so repeat views never re-bill.

Also completes two crestodian model-input mock factories that leaked into
sibling tests under shared-registry CI shards.

Fixes openclaw#103987

* fix(webui): redact tool-title inputs before truncation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: web-ui App: web-ui docs Improvements or additions to documentation gateway Gateway runtime maintainer Maintainer-authored PR merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: XL status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Control UI: reintroduce AI tool-call purpose titles behind an explicit opt-in

1 participant