Skip to content

Commit 27d6c88

Browse files
feat: add utility models and generated session titles (#87643)
* feat: add utility model session titles * docs: clarify utility model calls * fix: budget utility title reasoning * docs: refresh config baseline * docs: refresh plugin sdk baseline * docs: refresh plugin sdk baseline --------- Co-authored-by: Peter Steinberger <[email protected]>
1 parent bbb7442 commit 27d6c88

30 files changed

Lines changed: 587 additions & 170 deletions

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Docs: https://docs.openclaw.ai
1818

1919
### Changes
2020

21+
- **Generated session titles:** name new Control UI sessions from their first message, and add default/per-agent `utilityModel` routing for lower-cost session, topic, and thread title generation. Thanks @Juliangsm and @zhangguiping-xydt.
2122
- **ClawRouter routing and quotas:** add the bundled ClawRouter provider plugin with credential-scoped dynamic model discovery, OpenAI-compatible and native Anthropic/Gemini transports, and managed budget reporting across OpenClaw usage surfaces. (#99658)
2223
- **Model and provider coverage:** add GPT-5.6 support, use Nemotron Super's 1M context window, and preserve explicit OpenRouter authentication headers. (#98333, #98726, #98187) Thanks @steipete-oai, @eleqtrizit, @sunlit-deng, and @laurencebrown.
2324
- **CLI and node workflows:** add `openclaw attach`, node context-path support, actionable device-approval recovery guidance, soft-resume CLI sessions when prompt metadata changes, and clearer plugin install exit diagnostics. (#96454, #97679, #98115, #98146, #98497, #99822) Thanks @anagnorisis2peripeteia, @obviyus, @wm0018, @welfo-beo, @RomneyDa, @Sanjays2402, and @vincentkoc.
@@ -506,6 +507,7 @@ This audited record covers the complete 66e676d29b92d040716376a75aca32bad655cfac
506507
- **PR #99714** perf(usage): shrink durable usage cache entries. Related #99511. Thanks @dexhunter and @wayne524.
507508
- **PR #99838** feat: declutter the Control UI shell — reasoning effort slider, borderless composer controls, version out of the sidebar. Related #99837.
508509
- **PR #93686** fix(weixin): startAccount preserves session routing. Related #93556. Thanks @zhangguiping-xydt and @htkillermax-gif.
510+
509511
## 2026.6.11
510512

511513
We heard the feedback. v2026.6.11 focuses on the rough edges that make OpenClaw feel less dependable, with fixes for misplaced replies, stuck sends, reconnects, model setup failures, and safer admin defaults.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
55ea9b0a302df9328014e2607f65936358cdd301ea8a48046da4a8200cc77746 config-baseline.json
2-
21d36ba961186f567c0505e7443044fe08573ac1125cdd89e2a0e5b0fa93256a config-baseline.core.json
1+
4950ca686f135891c6bd42d4c1eb68945f3167b52cf115e17f8aac10d5388784 config-baseline.json
2+
c48fd78804feef7ff8028477b92bfd18ea252c03c249ef31dfb241a5e191b799 config-baseline.core.json
33
d27ac1e30c6f3ef7292f33ad9737d4372dd140675293cbddc38364e476f06410 config-baseline.channel.json
44
e228f29f17758763a098b0ccd10c6db7fc9df84840437ed3f88a88cf945b8078 config-baseline.plugin.json
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
95e17039bab1ad1dd3294948868740fb0315151b982e8f5c31859ba68fea2c0b plugin-sdk-api-baseline.json
2-
1c936a4d3ffcf00a16df5aa9bbbba109ed856c4adfd6af6118841557e2e4ec88 plugin-sdk-api-baseline.jsonl
1+
01c41d19cf15a0c2759e8f13064ecd5f00360fec467fc8fa47eb1f13907be379 plugin-sdk-api-baseline.json
2+
c331d008ecad33627b4d0f08ddeaa6430c51878d0fcaa36c9d61b4656a5f0c78 plugin-sdk-api-baseline.jsonl

docs/concepts/models.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ OpenClaw selects models in this order:
4444
<AccordionGroup>
4545
<Accordion title="Related model surfaces">
4646
- `agents.defaults.models` is the allowlist/catalog of models OpenClaw can use (plus aliases). Use `provider/*` entries to limit visible providers while keeping provider discovery dynamic.
47+
- `agents.defaults.utilityModel` is an optional lower-cost model for short internal tasks such as generated dashboard session titles and supported channel thread/topic titles. Per-agent `agents.list[].utilityModel` overrides it. When unset, these tasks use the agent's primary model. Utility tasks are separate model calls and may send bounded task content to the selected model provider.
4748
- `agents.defaults.imageModel` is used **only when** the primary model can't accept images.
4849
- `agents.defaults.pdfModel` is used by the `pdf` tool. If omitted, the tool falls back to `agents.defaults.imageModel`, then the resolved session/default model.
4950
- `agents.defaults.imageGenerationModel` is used by the shared image-generation capability. If omitted, `image_generate` can still infer an auth-backed provider default. It tries the current default provider first, then the remaining registered image-generation providers in provider-id order. If you set a specific provider/model, also configure that provider's auth/API key.
@@ -85,6 +86,7 @@ It can set up model + auth for common providers, including **OpenAI Code (Codex)
8586
## Config keys (overview)
8687

8788
- `agents.defaults.model.primary` and `agents.defaults.model.fallbacks`
89+
- `agents.defaults.utilityModel`
8890
- `agents.defaults.imageModel.primary` and `agents.defaults.imageModel.fallbacks`
8991
- `agents.defaults.pdfModel.primary` and `agents.defaults.pdfModel.fallbacks`
9092
- `agents.defaults.imageGenerationModel.primary` and `agents.defaults.imageGenerationModel.fallbacks`

docs/gateway/config-agents.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ Time format in system prompt. Default: `auto` (OS preference).
384384
primary: "anthropic/claude-opus-4-6",
385385
fallbacks: ["minimax/MiniMax-M2.7"],
386386
},
387+
utilityModel: "openai/gpt-5.4-mini",
387388
imageModel: {
388389
primary: "openrouter/qwen/qwen-2.5-vl-72b-instruct:free",
389390
fallbacks: ["openrouter/google/gemini-2.0-flash-vision:free"],
@@ -420,6 +421,8 @@ Time format in system prompt. Default: `auto` (OS preference).
420421
- `model`: accepts either a string (`"provider/model"`) or an object (`{ primary, fallbacks }`).
421422
- String form sets only the primary model.
422423
- Object form sets primary plus ordered failover models.
424+
- `utilityModel`: optional `provider/model` ref or alias for short internal tasks. It currently powers generated Control UI session titles, Telegram DM topic titles, and Discord auto-thread titles. These tasks fall back to the agent's primary model when unset; `agents.list[].utilityModel` overrides the default, and an operation-specific model override wins over both.
425+
Utility tasks make separate model calls and send task-specific content to the selected model provider. Dashboard title generation sends at most the first 1,000 characters of the first non-command message. Choose a provider that matches your cost and data-handling requirements.
423426
- `imageModel`: accepts either a string (`"provider/model"`) or an object (`{ primary, fallbacks }`).
424427
- Used by the `image` tool path as its vision-model config.
425428
- Also used as fallback routing when the selected/default model cannot accept image input.
@@ -1051,6 +1054,7 @@ for provider examples and precedence.
10511054
workspace: "~/.openclaw/workspace",
10521055
agentDir: "~/.openclaw/agents/main/agent",
10531056
model: "anthropic/claude-opus-4-6", // or { primary, fallbacks }
1057+
utilityModel: "openai/gpt-5.4-mini",
10541058
thinkingDefault: "high", // per-agent thinking level override
10551059
reasoningDefault: "on", // per-agent reasoning visibility override
10561060
fastModeDefault: false, // per-agent fast mode override
@@ -1094,6 +1098,7 @@ for provider examples and precedence.
10941098
- `id`: stable agent id (required).
10951099
- `default`: when multiple are set, first wins (warning logged). If none set, first list entry is default.
10961100
- `model`: string form sets a strict per-agent primary with no model fallback; object form `{ primary }` is also strict unless you add `fallbacks`. Use `{ primary, fallbacks: [...] }` to opt that agent into fallback, or `{ primary, fallbacks: [] }` to make strict behavior explicit. Cron jobs that only override `primary` still inherit default fallbacks unless you set `fallbacks: []`.
1101+
- `utilityModel`: optional per-agent override for short internal tasks such as generated session and thread titles. Falls back to `agents.defaults.utilityModel`, then this agent's primary model.
10971102
- `params`: per-agent stream params merged over the selected model entry in `agents.defaults.models`. Use this for agent-specific overrides like `cacheRetention`, `temperature`, or `maxTokens` without duplicating the whole model catalog.
10981103
- `tts`: optional per-agent text-to-speech overrides. The block deep-merges over `messages.tts`, so keep shared provider credentials and fallback policy in `messages.tts` and set only persona-specific values such as provider, voice, model, style, or auto mode here.
10991104
- `skills`: optional per-agent skill allowlist. If omitted, the agent inherits `agents.defaults.skills` when set; an explicit list replaces defaults instead of merging, and `[]` means no skills.

docs/web/control-ui.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ Use **Ctrl + backtick** to toggle the dock. The layout supports bottom and right
231231
- During an active send and the final history refresh, the chat view keeps local optimistic user/assistant messages visible if `chat.history` briefly returns an older snapshot; the canonical transcript replaces those local messages once the Gateway history catches up.
232232
- Live `chat` events are delivery state, while `chat.history` is rebuilt from the durable session transcript. After tool-final events the Control UI reloads history and merges only a small optimistic tail; the transcript boundary is documented in [WebChat](/web/webchat).
233233
- `chat.inject` appends an assistant note to the session transcript and broadcasts a `chat` event for UI-only updates (no agent run, no channel delivery).
234-
- The sidebar lists recent sessions with a New Session action, an All Sessions link, and a session search button that opens the full session picker (scoped by the selected agent, with search and pagination). Switching agents shows only sessions tied to that agent and falls back to that agent's main session when it has no saved dashboard sessions yet.
234+
- The sidebar lists recent sessions with a New Session action, an All Sessions link, and a session search button that opens the full session picker (scoped by the selected agent, with search and pagination). A new dashboard session asynchronously gets a concise generated title from its first non-command message; explicit names are never replaced. Set `agents.defaults.utilityModel` (or `agents.list[].utilityModel`) to route this separate model call to a lower-cost model. Switching agents shows only sessions tied to that agent and falls back to that agent's main session when it has no saved dashboard sessions yet.
235235
- Each session-picker row can rename, pin, or archive the session. An active run and an agent's main session cannot be archived. Archiving the currently selected session switches Chat back to that agent's main session.
236236
- On desktop widths, chat controls stay on one compact row and collapse while scrolling down the transcript; scrolling up, returning to the top, or reaching the bottom restores the controls.
237237
- Consecutive duplicate text-only messages render as one bubble with a count badge. Messages that carry images, attachments, tool output, or canvas previews are left uncollapsed.

extensions/discord/src/monitor/thread-title.generate.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ describe("generateThreadTitle", () => {
101101
expect(prepareSimpleCompletionModelForAgentMock).toHaveBeenCalledWith({
102102
cfg,
103103
agentId: "main",
104+
useUtilityModel: true,
104105
allowMissingApiKeyModes: ["aws-sdk"],
105106
});
106107
});
@@ -118,6 +119,7 @@ describe("generateThreadTitle", () => {
118119
cfg,
119120
agentId: "main",
120121
modelRef: "openai/gpt-4.1-mini@local",
122+
useUtilityModel: true,
121123
allowMissingApiKeyModes: ["aws-sdk"],
122124
});
123125
});

extensions/discord/src/monitor/thread-title.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export async function generateThreadTitle(params: {
3939
cfg: params.cfg,
4040
agentId: params.agentId,
4141
...(params.modelRef ? { modelRef: params.modelRef } : {}),
42+
useUtilityModel: true,
4243
allowMissingApiKeyModes: ["aws-sdk"],
4344
});
4445
if ("error" in prepared) {

packages/model-catalog-core/src/configured-model-refs.test.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,16 @@ describe("configured model refs", () => {
1313
agents: {
1414
defaults: {
1515
model: { primary: "openai/gpt-5.5", fallbacks: ["anthropic/claude-sonnet-4-6"] },
16+
utilityModel: "google/gemini-3.1-flash-lite-preview",
1617
compaction: { memoryFlush: { model: "openai/gpt-5.5-mini" } },
1718
},
18-
list: [{ id: "custom", model: "xai/grok-4-fast" }],
19+
list: [
20+
{
21+
id: "custom",
22+
model: "xai/grok-4-fast",
23+
utilityModel: "openai/gpt-5.5-nano",
24+
},
25+
],
1926
},
2027
hooks: {
2128
mappings: [{ model: "openai/gpt-5.5-nano" }],
@@ -34,8 +41,13 @@ describe("configured model refs", () => {
3441
).toEqual([
3542
{ path: "agents.defaults.model.primary", value: "openai/gpt-5.5" },
3643
{ path: "agents.defaults.model.fallbacks.0", value: "anthropic/claude-sonnet-4-6" },
44+
{
45+
path: "agents.defaults.utilityModel",
46+
value: "google/gemini-3.1-flash-lite-preview",
47+
},
3748
{ path: "agents.defaults.compaction.memoryFlush.model", value: "openai/gpt-5.5-mini" },
3849
{ path: "agents.list.0.model", value: "xai/grok-4-fast" },
50+
{ path: "agents.list.0.utilityModel", value: "openai/gpt-5.5-nano" },
3951
{ path: "channels.modelByChannel.discord.guild", value: "anthropic/claude-opus-4-8" },
4052
{ path: "hooks.mappings.0.model", value: "openai/gpt-5.5-nano" },
4153
{ path: "messages.tts.summaryModel", value: "openai/gpt-5.5-mini" },

packages/model-catalog-core/src/configured-model-refs.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export type ConfiguredModelRef = {
1717
/** Agent config keys that can contain direct model references. */
1818
export const AGENT_MODEL_CONFIG_KEYS = [
1919
"model",
20+
"utilityModel",
2021
"imageModel",
2122
"imageGenerationModel",
2223
"videoGenerationModel",

0 commit comments

Comments
 (0)