openclaw - 💡(How to fix) Fix Feature request: optional model override in CommitmentsConfig (mirror active-memory/compaction precedent) [2 pull requests]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

CommitmentsConfig currently exposes only enabled and maxPerDay. Since #75347 merged (#75334 fix), commitments extraction correctly inherits the agent's default model via resolveDefaultModelForAgent(). That fix is great for installs where the agent's default IS appropriate for extraction.

However, when an operator deliberately runs the main agent on a strong-but-slow / expensive model (Codex OAuth openai-codex/gpt-5.5, Anthropic Claude Opus 4, etc.) for high-quality interactive replies, commitments extraction now inherits that same model. Background extraction is a narrow, structured task that doesn't need the most capable model — but is forced onto the hot-path model.

Two adjacent features already expose per-feature model fields (active-memory, compaction). Commitments should follow the same pattern.

Error Message

[diagnostic] liveness warning: reasons=event_loop_delay,event_loop_utilization eventLoopDelayP99Ms=10745.8 eventLoopUtilization=0.992 active=2 ... commitments-XXX(processing/model_call, age=15s last=model_call:started) [diagnostic] lane task error: lane=session:agent:main:commitments:commitments-XXX durationMs=82378 error="CommandLaneTaskTimeoutError: Command lane 'main' task timed out after 75000ms" [agent/embedded] embedded run failover decision: runId=commitments-XXX decision=fallback_model reason=timeout

Root Cause

CommitmentsConfig currently exposes only enabled and maxPerDay. Since #75347 merged (#75334 fix), commitments extraction correctly inherits the agent's default model via resolveDefaultModelForAgent(). That fix is great for installs where the agent's default IS appropriate for extraction.

However, when an operator deliberately runs the main agent on a strong-but-slow / expensive model (Codex OAuth openai-codex/gpt-5.5, Anthropic Claude Opus 4, etc.) for high-quality interactive replies, commitments extraction now inherits that same model. Background extraction is a narrow, structured task that doesn't need the most capable model — but is forced onto the hot-path model.

Two adjacent features already expose per-feature model fields (active-memory, compaction). Commitments should follow the same pattern.

Fix Action

Fix / Workaround

Minimal patch:

AlternativeVerdict
Operator switches agents.defaults.model.primary to a fast modelDefeats the reason main is on a strong/paid model (capability for interactive replies)
Per-agent model override via a hypothetical separate commitments-agentCurrent commitments runtime scopes per-agent automatically; would require new agent entry + larger architectural change
Disable commitments entirelyCurrent workaround. Loses feature.
Throttle commitments to N concurrent at runtimeDoesn't solve root cost — each extraction still slow; just queues differently
Wait for the relevant LLM provider to get fasterOut of operator's control
Upstream switch in extraction to fastMode: true (#78451)Helps when MiniMax-M2.7-highspeed is available; still locks operator to one model. Orthogonal to this request.
  • #75334 closed / #75347 merged — Extractor previously hardcoded direct OpenAI defaults; fixed by routing through resolveDefaultModelForAgent(). This issue is the next logical step: allow override of the resolved default for installs where the agent default is intentionally slow/expensive.
  • #78451 open / #78459 — Extraction hardcodes fastMode: true. Tangentially related (also about extraction model selection) but solves a different axis (fast-mode plan compatibility).
  • #52029 openheartbeat.tools per-feature carve-out for background tasks. Same shape of feature.
  • #55401 open — Per-agent plugin configuration overrides. More general; a commitments.model field is a narrow, concrete subset.
  • #59532 open — Per-agent default model in ACPX plugin config. Same per-feature override pattern.

Code Example

[diagnostic] liveness warning: reasons=event_loop_delay,event_loop_utilization
  eventLoopDelayP99Ms=10745.8 eventLoopUtilization=0.992
  active=2 ... commitments-XXX(processing/model_call, age=15s last=model_call:started)
[diagnostic] lane task error: lane=session:agent:main:commitments:commitments-XXX
  durationMs=82378 error="CommandLaneTaskTimeoutError: Command lane 'main' task timed out after 75000ms"
[agent/embedded] embedded run failover decision:
  runId=commitments-XXX decision=fallback_model reason=timeout

---

type ActiveRecallPluginConfig = {
  enabled?: boolean;
  agents?: string[];
  model?: string;             // ← per-feature override
  modelFallback?: string;
  modelFallbackPolicy?: "default-remote" | "resolved-only";
  // ...
};

---

{
  "agents": {
    "defaults": {
      "compaction": {
        "model": "minimax/MiniMax-M2.7"
      }
    }
  }
}

---

export type CommitmentsConfig = {
   /** Enable inferred follow-up extraction, storage, and heartbeat delivery. Default: false. */
   enabled?: boolean;
   /** Maximum inferred follow-up commitments delivered per agent session in a rolling day. Default: 3. */
   maxPerDay?: number;
+  /**
+   * Optional model override for commitment extraction. Provider-qualified
+   * (e.g. "minimax/MiniMax-M2.7"). When set, extraction uses this model
+   * instead of inheriting the agent's default. Useful when the main agent
+   * runs an expensive/slow model but commitments should be fast/cheap.
+   * Unset: inherits `agents.defaults.model.primary` (current behavior, #75347).
+   */
+  model?: string;
+  /** Optional secondary model when primary fails. */
+  modelFallback?: string;
 };

---

import { resolveDefaultModelForAgent } from "../agents/model-selection.js";
import type { OpenClawConfig } from "../config/config.js";

export function resolveCommitmentDefaultModelRef(params: {
  cfg: OpenClawConfig;
  agentId?: string;
}): { provider: string; model: string } {
  return resolveDefaultModelForAgent(params);
}

---

export function resolveCommitmentDefaultModelRef(params: {
   cfg: OpenClawConfig;
   agentId?: string;
 }): { provider: string; model: string } {
+  const override = params.cfg?.commitments?.model;
+  if (override) {
+    const [provider, ...modelParts] = override.split("/");
+    if (provider && modelParts.length > 0) {
+      return { provider, model: modelParts.join("/") };
+    }
+  }
   return resolveDefaultModelForAgent(params);
 }
RAW_BUFFERClick to expand / collapse

Feature request: optional model override in CommitmentsConfig (mirror active-memory/compaction precedent)

Summary

CommitmentsConfig currently exposes only enabled and maxPerDay. Since #75347 merged (#75334 fix), commitments extraction correctly inherits the agent's default model via resolveDefaultModelForAgent(). That fix is great for installs where the agent's default IS appropriate for extraction.

However, when an operator deliberately runs the main agent on a strong-but-slow / expensive model (Codex OAuth openai-codex/gpt-5.5, Anthropic Claude Opus 4, etc.) for high-quality interactive replies, commitments extraction now inherits that same model. Background extraction is a narrow, structured task that doesn't need the most capable model — but is forced onto the hot-path model.

Two adjacent features already expose per-feature model fields (active-memory, compaction). Commitments should follow the same pattern.

Motivation

A configuration where main agent uses Codex OAuth openai-codex/gpt-5.5 (intentional: paid via ChatGPT Plus, strong reasoning, zero marginal cost) and the operator wants commitments extraction on a fast cheap model (e.g. minimax/MiniMax-M2.7) is currently unrepresentable. The operator must choose:

  • (a) Downgrade main agent to the fast model → defeats the reason main is on Codex OAuth in the first place
  • (b) Disable commitments entirely → loses the feature
  • (c) Live with the cascade — see below

Observed failure mode under heavy traffic

When the main agent's model is slow upstream (transient API latency on the provider's side: 45-150 s per request instead of 5-15 s), inherited extraction inherits that latency. With several user messages arriving in close succession on a single-core Node.js gateway, concurrent commitments extraction runs accumulate:

[diagnostic] liveness warning: reasons=event_loop_delay,event_loop_utilization
  eventLoopDelayP99Ms=10745.8 eventLoopUtilization=0.992
  active=2 ... commitments-XXX(processing/model_call, age=15s last=model_call:started)
[diagnostic] lane task error: lane=session:agent:main:commitments:commitments-XXX
  durationMs=82378 error="CommandLaneTaskTimeoutError: Command lane 'main' task timed out after 75000ms"
[agent/embedded] embedded run failover decision:
  runId=commitments-XXX decision=fallback_model reason=timeout

The gateway event loop saturates (eventLoopUtilization → 1.0), plugin /health endpoints time out (HTTP 000), and a typical watchdog auto-restarts the gateway. Restarts repeat as long as inbound traffic keeps spawning more concurrent extractions than the slow upstream can drain.

The terminal-error cooldown added in #75347 helps when extraction fails, but does not bound concurrency when extraction eventually succeeds slowly. Operators wanting to keep main on the strong model with commitments enabled have no clean path.

If commitments.model were configurable, an operator could pin extraction to a fast model independently of main agent's choice, removing the coupling entirely.

Existing precedent in the codebase

Two adjacent features already accept a per-feature model field:

1. Active Memory (extensions/active-memory/index.ts):

type ActiveRecallPluginConfig = {
  enabled?: boolean;
  agents?: string[];
  model?: string;             // ← per-feature override
  modelFallback?: string;
  modelFallbackPolicy?: "default-remote" | "resolved-only";
  // ...
};

Documented usage (docs/concepts/active-memory.md):

config.model (optional) pins a dedicated recall model; unset inherits the current session model

2. Compaction (agents.defaults.compaction.model):

Operators routinely override compaction model to a cheaper one:

{
  "agents": {
    "defaults": {
      "compaction": {
        "model": "minimax/MiniMax-M2.7"
      }
    }
  }
}

Both features are background/structured tasks (recall, summarization). Commitments extraction has the same shape: short, structured, background. Sharing one schema convention across all three reduces cognitive load for operators tuning model routing.

Proposed schema change

src/config/types.commitments.ts:

 export type CommitmentsConfig = {
   /** Enable inferred follow-up extraction, storage, and heartbeat delivery. Default: false. */
   enabled?: boolean;
   /** Maximum inferred follow-up commitments delivered per agent session in a rolling day. Default: 3. */
   maxPerDay?: number;
+  /**
+   * Optional model override for commitment extraction. Provider-qualified
+   * (e.g. "minimax/MiniMax-M2.7"). When set, extraction uses this model
+   * instead of inheriting the agent's default. Useful when the main agent
+   * runs an expensive/slow model but commitments should be fast/cheap.
+   * Unset: inherits `agents.defaults.model.primary` (current behavior, #75347).
+   */
+  model?: string;
+  /** Optional secondary model when primary fails. */
+  modelFallback?: string;
 };

Implementation hint

src/commitments/model-selection.runtime.ts already isolates model resolution:

import { resolveDefaultModelForAgent } from "../agents/model-selection.js";
import type { OpenClawConfig } from "../config/config.js";

export function resolveCommitmentDefaultModelRef(params: {
  cfg: OpenClawConfig;
  agentId?: string;
}): { provider: string; model: string } {
  return resolveDefaultModelForAgent(params);
}

Minimal patch:

 export function resolveCommitmentDefaultModelRef(params: {
   cfg: OpenClawConfig;
   agentId?: string;
 }): { provider: string; model: string } {
+  const override = params.cfg?.commitments?.model;
+  if (override) {
+    const [provider, ...modelParts] = override.split("/");
+    if (provider && modelParts.length > 0) {
+      return { provider, model: modelParts.join("/") };
+    }
+  }
   return resolveDefaultModelForAgent(params);
 }

extraction.ts (caller of runEmbeddedPiAgent) already receives the resolved ModelRef, so no changes needed downstream. The terminal-error cooldown added in #75347 continues to apply unchanged.

Alternatives considered

AlternativeVerdict
Operator switches agents.defaults.model.primary to a fast modelDefeats the reason main is on a strong/paid model (capability for interactive replies)
Per-agent model override via a hypothetical separate commitments-agentCurrent commitments runtime scopes per-agent automatically; would require new agent entry + larger architectural change
Disable commitments entirelyCurrent workaround. Loses feature.
Throttle commitments to N concurrent at runtimeDoesn't solve root cost — each extraction still slow; just queues differently
Wait for the relevant LLM provider to get fasterOut of operator's control
Upstream switch in extraction to fastMode: true (#78451)Helps when MiniMax-M2.7-highspeed is available; still locks operator to one model. Orthogonal to this request.

The per-feature model override is the smallest, lowest-risk change that mirrors existing precedent.

Acceptance criteria

  • pnpm test src/commitments/model-selection.runtime.test.ts — new test: override takes precedence; absence inherits agent default
  • pnpm test src/commitments/runtime.test.ts — existing tests still pass (no regression in #75347 behavior)
  • pnpm test src/commitments/extraction.test.ts — extraction uses configured override end-to-end
  • pnpm test src/commitments/commitments-full-chain.integration.test.ts — chain test
  • Schema validation accepts commitments.model as optional string
  • Doc update mentioning commitments.model field, mirroring active-memory docs structure
  • Optional: changelog entry

Related issues / PRs

  • #75334 closed / #75347 merged — Extractor previously hardcoded direct OpenAI defaults; fixed by routing through resolveDefaultModelForAgent(). This issue is the next logical step: allow override of the resolved default for installs where the agent default is intentionally slow/expensive.
  • #78451 open / #78459 — Extraction hardcodes fastMode: true. Tangentially related (also about extraction model selection) but solves a different axis (fast-mode plan compatibility).
  • #52029 openheartbeat.tools per-feature carve-out for background tasks. Same shape of feature.
  • #55401 open — Per-agent plugin configuration overrides. More general; a commitments.model field is a narrow, concrete subset.
  • #59532 open — Per-agent default model in ACPX plugin config. Same per-feature override pattern.

Severity

This is a real-world cost/UX issue, not a crash:

  • Operators on Codex OAuth, Claude Opus 4, or any expensive/slow primary model must choose between (a) disabling commitments entirely or (b) downgrading main to a cheaper model.
  • Heavy-traffic installs with slow upstream APIs can hit gateway saturation cascades.
  • Watchdog auto-restart papers over the symptom but creates user-visible plugin flap alerts.

A ~10-line schema + selection-runtime patch resolves it cleanly and follows established precedent.

Environment

  • OpenClaw version: 2026.5.2 (also verified against main as of 2026-05-11)
  • Single-core Node.js gateway, 4 GB host (representative of small-VPS deployment)
  • Main agent configured with agents.defaults.model.primary = openai-codex/gpt-5.5 (Codex OAuth)
  • Commitments enabled, default maxPerDay: 3

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix Feature request: optional model override in CommitmentsConfig (mirror active-memory/compaction precedent) [2 pull requests]