openclaw - ✅(Solved) Fix Cron isolated agent turns silently drop runs when payload.model is rejected by the allowlist [1 pull requests, 1 comments, 2 participants]

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…
GitHub stats
openclaw/openclaw#78597Fetched 2026-05-07 03:34:53
View on GitHub
Comments
1
Participants
2
Timeline
3
Reactions
2
Timeline (top)
cross-referenced ×2commented ×1

When a cron job's payload.model (or an inbound /hooks/agent payload's model field) names a model that is not in the agent's agents.defaults.models allowlist, OpenClaw 2026.5.3-1 returns { ok: false, status: "error" } from runIsolatedAgentTurn. The cron firing is silently dropped — no LLM call, no session jsonl, no warning visible from gateway.err.log.

This is a behavior regression from earlier builds that emitted a discoverable warn line and fell back to the agent default model.

Error Message

When a cron job's payload.model (or an inbound /hooks/agent payload's model field) names a model that is not in the agent's agents.defaults.models allowlist, OpenClaw 2026.5.3-1 returns { ok: false, status: "error" } from runIsolatedAgentTurn. The cron firing is silently dropped — no LLM call, no session jsonl, no warning visible from gateway.err.log. This is a behavior regression from earlier builds that emitted a discoverable warn line and fell back to the agent default model.

  • A logHooks.warn line at the rejection point with the rejected model id and the allowlist contents (or a hint to inspect gateway models.list).
  • Optional fallback-to-agent-default behavior (matches pre-2026.5 behavior). The previous warn+fallback line was [cron] payload.model 'X' not allowed, falling back to agent defaults.
  • runIsolatedAgentTurn returning { ok: false, status: 'error' } triggers shouldAnnounceHookRunResult === true, but the surfaced event is too quiet to notice in practice.

Root Cause

When a cron job's payload.model (or an inbound /hooks/agent payload's model field) names a model that is not in the agent's agents.defaults.models allowlist, OpenClaw 2026.5.3-1 returns { ok: false, status: "error" } from runIsolatedAgentTurn. The cron firing is silently dropped — no LLM call, no session jsonl, no warning visible from gateway.err.log.

This is a behavior regression from earlier builds that emitted a discoverable warn line and fell back to the agent default model.

Fix Action

Fixed

PR fix notes

PR #78655: fix: surface hook model rejection diagnostics

Description (problem / solution / changelog)

Summary

  • Problem: /hooks/agent could accept a run whose payload.model was rejected by the cron model allowlist, then only surface a quiet returned error path.
  • Why it matters: operators saw HTTP 200/runId but no transcript, no model call, and no obvious Gateway warning for the rejected model.
  • What changed: hook-triggered isolated-run errors now log a structured gateway/hooks warning, direct failed cron jobs now log a scheduler warning with the diagnostic summary, and hook announcements prefer cron diagnostic summaries.
  • What did NOT change (scope boundary): explicit disallowed payload.model values still fail closed; hook HTTP semantics still return an async run id.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #78597
  • Related #75928
  • This PR fixes a bug or regression

Real behavior proof

  • Behavior or issue addressed: disallowed /hooks/agent payload.model is discoverable at the hook boundary.

  • Real environment tested: local isolated integration Gateway from this branch, workspace issue-78597-fixed, port 54506.

  • Exact steps or command run after this patch: started ./.mem/integ/scripts/run_integ_gateway.mjs issue-78597-fixed 54506, POSTed /hooks/agent with model: "anthropic/claude-sonnet-4-6" while only openai/gpt-5.5 was in agents.defaults.models, then checked the Gateway log.

  • Evidence after fix: .mem/main/integ/issue-78597-fixed.md verifies hook_warning_lines=1 and diagnostic_summary_lines=2. After-fix console output from the real integration Gateway run:

    hook_http_status=200
    hook_returned_run_id=yes
    hook_warning_lines=1
    diagnostic_summary_lines=2
    session_or_transcript_files=1
    issue_fixed=yes
    
    gateway/hooks hook agent run returned non-ok status
    status=error
    model=anthropic/claude-sonnet-4-6
    sessionKey=hook:issue-78597
    summary=cron payload.model 'anthropic/claude-sonnet-4-6' rejected by agents.defaults.models allowlist: anthropic/claude-sonnet-4-6
  • Observed result after fix: Gateway log includes hook agent run returned non-ok status with model, session key, run id, job id, and the cron allowlist rejection summary.

  • What was not tested: real model delivery of the follow-up announcement, because the isolated proof workspace intentionally had no OpenAI auth profile.

  • Before evidence: .mem/main/integ/issue-78597-repro.md records HTTP 200 with run id, zero session/transcript files, and zero hook/model rejection warning lines before the patch.

Root Cause

  • Root cause: /hooks/agent dispatches isolated cron-style work asynchronously and only logged thrown exceptions, while disallowed payload.model is a returned status: "error" result before the agent runner starts.
  • Missing detection / guardrail: hook tests asserted the quiet system event but not logHooks.warn, and cron tests did not pin the preflight diagnostic object for disallowed payload models.
  • Contributing context: #75928 added cron diagnostics, but the hook boundary was still summarizing returned errors without logging them.

Regression Test Plan

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/gateway/server/hooks.agent-trust.test.ts and src/cron/isolated-agent/run.cron-model-override.test.ts.
  • Scenario the test should lock in: returned hook status: "error" uses cron diagnostic summaries for announcements and emits a structured warning; failed cron job results log their diagnostic summary; disallowed cron payload model carries cron-preflight diagnostics.
  • Why this is the smallest reliable guardrail: it exercises the exact returned-error seam without needing live model credentials.
  • Existing test that already covers this (if any): existing hook trust tests covered announcement trust, but not warning visibility or diagnostic-summary precedence.
  • If no new test is added, why not: N/A.

User-visible / Behavior Changes

Rejected hook-triggered cron model overrides now produce a visible Gateway warning and a more specific hook announcement summary. Direct failed cron jobs now also produce a scheduler warning with the stored diagnostic summary.

Diagram

Before:
/hooks/agent -> async isolated run -> payload.model rejection -> quiet returned error

After:
/hooks/agent -> async isolated run -> payload.model rejection -> cron diagnostic summary -> hook warning + announcement summary
cron job -> isolated run -> payload.model rejection -> cron diagnostic summary -> cron warning + job state

Security Impact

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: macOS local development host
  • Runtime/container: Node 25.6.0 via repo scripts
  • Model/provider: configured allowlist openai/gpt-5.5; rejected payload model anthropic/claude-sonnet-4-6
  • Integration/channel: local /hooks/agent
  • Relevant config (redacted): hooks enabled with local token, hooks.defaultSessionKey = "hook:issue-78597", agents.defaults.models["openai/gpt-5.5"] = {}

Steps

  1. Create isolated integration workspace and enable hooks.
  2. Start Gateway on a random loopback port.
  3. POST /hooks/agent with a payload model outside agents.defaults.models.
  4. Inspect Gateway logs and state artifacts.

Expected

  • Rejected payload model is visible in hook diagnostics/logging.

Actual

  • Before patch: HTTP 200/run id, no transcript, no hook/model rejection warning.
  • After patch: HTTP 200/run id, plus a structured gateway/hooks warning with the cron diagnostic summary.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification

  • Verified scenarios: targeted tests, changed checks, changed tests, repro Showboat proof, fixed Showboat proof.
  • Edge cases checked: hook diagnostic summary takes precedence over generic summary/error; cron preflight diagnostic source/severity is preserved.
  • What you did not verify: authenticated delivery of the follow-up announcement in a live channel.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: warning volume increases for non-ok hook runs that were already being announced.
    • Mitigation: only returned non-ok isolated hook results warn; successful delivered and suppressed runs are unchanged.

Verification

  • pnpm test src/cron/isolated-agent/run.cron-model-override.test.ts src/gateway/server/hooks.agent-trust.test.ts -- --reporter=dot
  • pnpm test src/cron/service/timer.regression.test.ts src/cron/isolated-agent/run.cron-model-override.test.ts -- --reporter=dot
  • pnpm exec oxfmt --check --threads=1 src/gateway/server/hooks.ts src/gateway/server/hooks.agent-trust.test.ts src/cron/isolated-agent/run.cron-model-override.test.ts CHANGELOG.md
  • git diff --check
  • uvx showboat verify /Users/kevinlin/code/openclaw/.mem/main/integ/issue-78597-repro.md
  • uvx showboat verify /Users/kevinlin/code/openclaw/.mem/main/integ/issue-78597-fixed.md
  • pnpm check:changed
  • pnpm test:changed

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/cron/isolated-agent/run.cron-model-override.test.ts (modified, +10/-0)
  • src/cron/service/timer.regression.test.ts (modified, +12/-2)
  • src/cron/service/timer.ts (modified, +11/-0)
  • src/gateway/server/hooks.agent-trust.test.ts (modified, +110/-0)
  • src/gateway/server/hooks.ts (modified, +62/-4)
RAW_BUFFERClick to expand / collapse

Summary

When a cron job's payload.model (or an inbound /hooks/agent payload's model field) names a model that is not in the agent's agents.defaults.models allowlist, OpenClaw 2026.5.3-1 returns { ok: false, status: "error" } from runIsolatedAgentTurn. The cron firing is silently dropped — no LLM call, no session jsonl, no warning visible from gateway.err.log.

This is a behavior regression from earlier builds that emitted a discoverable warn line and fell back to the agent default model.

Repro

  1. Configure a cron job whose payload sets model to a provider/model id that is NOT in agents.defaults.models for that agent (e.g. an unregistered version of an existing provider's model — the model id is well-formed, the provider is registered, only the specific version isn't in the allowlist).
  2. Wait for the cron to fire (or hit POST /hooks/agent with the same model field, deliver: true).
  3. Observe: HTTP 200 + a runId is returned. gateway.log shows nothing useful. No session jsonl is written. The run is gone.

Probes without the model field, hitting the same agent and route, produce a session jsonl as expected.

Expected

At minimum:

  • A logHooks.warn line at the rejection point with the rejected model id and the allowlist contents (or a hint to inspect gateway models.list).
  • The rejection reason surfaced in the announce path so it's visible in the agent's main session, not buried in a quiet system event.

Ideally:

  • Optional fallback-to-agent-default behavior (matches pre-2026.5 behavior). The previous warn+fallback line was [cron] payload.model 'X' not allowed, falling back to agent defaults.

Pointers

  • Function name in the current binary: formatCronPayloadModelRejection (in the bundled isolated-agent chunk).
  • runIsolatedAgentTurn returning { ok: false, status: 'error' } triggers shouldAnnounceHookRunResult === true, but the surfaced event is too quiet to notice in practice.
  • The allowlist is loaded from models.providers.<provider>.models in openclaw.json and is not hot-reloadable for that subtree, so a stale allowlist after a gateway upgrade can produce silent failures across many cron-driven flows at once.

Impact

Three days of completely silent cron-driven workflow failures on our setup before we noticed (the cron source kept emitting events, the integration that submitted hooks kept reporting delivered, but no runs were actually executed). Discoverability is the whole game here.

Version

OpenClaw 2026.5.3-1.

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 - ✅(Solved) Fix Cron isolated agent turns silently drop runs when payload.model is rejected by the allowlist [1 pull requests, 1 comments, 2 participants]