fix(agents): skip empty allowlist guard for modelRun#73031
Conversation
The infer model run flow sets modelRun=true and disableTools=true so toolsRaw is intentionally empty. The empty-allowlist guard still ran with the global tools.alsoAllow expanded as an explicit allowlist, so the run failed before any provider request was made. Skip the guard when modelRun is true so text-only model smokes succeed even when tools.alsoAllow is configured. Fixes openclaw#73024.
Greptile SummaryThis PR fixes a false-positive error in Confidence Score: 5/5Safe to merge — targeted one-line guard bypass, single call site updated, well-tested. The change is minimal and correct: a single early-exit added before the guard logic, only one production call site, and the new parameter is optional so no other callers are affected. The test suite covers both the new bypass and the existing fail-closed paths. No files require special attention. Reviews (1): Last reviewed commit: "fix(agents): skip empty allowlist guard ..." | Re-trigger Greptile |
|
Codex review: needs maintainer review before merge. Summary Reproducibility: yes. The current-main source path is high-confidence without a live model account: gateway model run sets Next step before merge Security Review detailsBest possible solution: Land this narrow Do we have a high-confidence way to reproduce the issue? Yes. The current-main source path is high-confidence without a live model account: gateway model run sets Is this the best way to solve the issue? Yes for the central Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 929df0f5567f. |
Summary
openclaw infer model runaborts before any provider request when~/.openclaw/openclaw.jsonhas a non-emptytools.alsoAllow, because the empty explicit-allowlist guard still evaluates the global tool policy even thoughmodelRun:trueintentionally zeroestoolsRaw.The fix adds a
modelRun?: booleanparameter tobuildEmptyExplicitToolAllowlistErrorand short-circuits tonullwhen it istrue. The embedded attempt path (attempt.ts) now passesmodelRun: params.modelRuninto the guard so model-only call shapes can run text-only without failing on a globaltools.alsoAllow.This keeps the existing fail-closed behavior for runtime
disableToolsconflicts and for ordinary agent runs whose explicit allowlist resolves to no callable tools (the original intent of #71292).Repro
Set in
~/.openclaw/openclaw.json:Run:
openclaw infer model run --local --model openai-codex/gpt-5.5 --prompt 'reply exactly: ok' --jsonBefore this PR, fails with
No callable tools remain after resolving explicit tool allowlist (...). After this PR, the model is reached.Test added
src/agents/tool-allowlist-guard.test.ts— new caseskips the empty-allowlist guard for modelRun call shapes. AssertsbuildEmptyExplicitToolAllowlistErrorreturnsnullwhenmodelRun: trueeven with non-emptysourcesand zero callable tools. The existingdisableTools: truefail-closed test is unchanged.Validation
pnpm test src/agents/tool-allowlist-guard.test.ts— 7/7 passingpnpm check:changed --staged— green (typecheck core/test, lint, import cycles, conflict markers, changelog attributions, etc.)pnpm test:changed— 2521 passing; one unrelated pre-existing failure onsrc/agents/tools/cron-tool.schema.test.ts(job.deliverykeys assertion is missing the newthreadIdintroduced by upstreamb6be422306 fix(cron): accept threaded delivery in gateway schema). Reproduces on bareupstream/mainwith my changes stashed, so it is not blocking.Closes
Fixes #73024
AI assistance
This PR was prepared with Claude Code (Opus 4.7). Lightly tested locally — the unit test covers the guard contract; the end-to-end
infer model runrepro was not exercised live since it requires a live model account.