Skip to content

infer model run fails before model call when tools.alsoAllow is set and modelRun disables tools #73024

Description

@aa-on-ai

Summary

openclaw infer model run --local --model <id> --prompt <p> can abort before attempting any model call when ~/.openclaw/openclaw.json has a non-empty tools.alsoAllow.

The error is:

No callable tools remain after resolving explicit tool allowlist (tools.allow: *, lobster, llm-task)

This happens even though infer model run sets modelRun:true / disables tools intentionally. The target model and auth are valid. The same model succeeds when tools.alsoAllow is removed in a temp config.

Reproduce

  1. Configure ~/.openclaw/openclaw.json with:

    "tools": {
      "profile": "coding",
      "alsoAllow": ["lobster", "llm-task"]
    }
  2. Run:

    openclaw infer model run --local --model openai-codex/gpt-5.5 --prompt 'reply exactly: ok' --json

Actual

The command aborts with:

No callable tools remain after resolving explicit tool allowlist (tools.allow: *, lobster, llm-task)

No provider request is made. The gateway never reaches the model call.

Expected

Because modelRun:true disables tools for this call shape, tool allowlist validation should not fail the model smoke. The command should attempt the model call and return the model response or a provider/model auth error.

Root cause

Observed in OpenClaw 2026.4.25 bundled output (file hashes will churn between builds; locations cited as observed):

  • runModelRun() sets modelRun:true and promptMode:"none" (capability CLI module).
  • The execution attempt path propagates disableTools: params.opts.modelRun === true.
  • The selection module zeroes toolsRaw when disableTools || modelRun is true, but then still calls buildEmptyExplicitToolAllowlistError(...) because the global tools.alsoAllow has been expanded into an explicit allowlist of the form ["*", ...alsoAllow] by the sandbox tool-policy module.

So the modelRun path intentionally disables tools, but the empty-explicit-allowlist guard still evaluates the global tool policy and fails closed.

Observed source locations (bundled)

  • dist/capability-cli-*.jsrunModelRun()
  • dist/attempt-execution-*.js — propagates disableTools
  • dist/selection-*.jstoolsRaw zeroing + buildEmptyExplicitToolAllowlistError call
  • dist/sandbox-tool-policy-*.jstools.alsoAllow → explicit allowlist expansion

Suggested fix

Skip the empty-explicit-allowlist guard when tools are intentionally disabled:

if (!params.modelRun && !params.disableTools && /* existing condition */) {
  throw buildEmptyExplicitToolAllowlistError(...);
}

Alternatively, do not pass the global tool-policy block into that guard for modelRun/disableTools executions.

Impact

This breaks model/routing smoke tests and can produce false negatives during migrations.

We hit it during a gpt-5.5 routing cleanup on 2026-04-27 and initially rolled back a correct config patch because infer model run failed before making a provider call.

Workarounds

These production-path checks are unaffected:

  • openclaw cron run <id>
  • openclaw agent --agent <id> ...

A temp config that removes tools.alsoAllow also allows the same model/auth combo to succeed.

Environment

  • OpenClaw: 2026.4.25
  • Install: ~/homebrew/lib/node_modules/openclaw
  • macOS: Darwin 25.3.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions