Skip to content

Feature request: per-model request timeout so fallback chain triggers on hangs #64854

Description

@joblas

Feature request: per-model request timeout so fallback chain triggers on hangs

OpenClaw version: 2026.4.9

Problem

If an LLM provider call hangs (no HTTP response, no error), the fallback chain
configured in agents.list[].model.fallbacks never triggers. Fallback is
error-driven — it only activates on an HTTP error from the primary provider.
A stuck TCP connection or a provider that accepts the request but never sends
bytes is indistinguishable from "still thinking" and waits indefinitely.

Observed incident (2026-04-11)

  • Main agent config: primary: "zen/big-<model>", fallbacks: Gemini +
    5 OpenRouter free models (fully valid, tested).
  • User sent a Telegram message to the main agent.
  • Gateway log shows the session received the message, started typing,
    then this line appears ~2 min later:
    typing TTL reached (2m); stopping typing indicator
  • Nothing after. Session updatedAt frozen for 30+ minutes.
  • Gateway was healthy, all providers reachable, no error logged.
  • User had to notice the silence and manually restart the gateway — the
    fallback chain that exists specifically to prevent this never fired
    because the upstream call never errored.

Root cause

grep -r requestTimeoutMs dist/ shows requestTimeoutMs only in MS Teams
webhook handling and Telegram bot API calls. providerTimeoutMs exists but
is scoped to CLI config-provider commands (config-cli-J5ilTjk5.js), not
LLM providers. There is no documented or discoverable config key that
bounds a model inference call.

Requested behavior

Add a per-provider (or per-agent) request-timeout option:

{
  "models": {
    "providers": {
      "zen": {
        "api": "openai-completions",
        "baseUrl": "https://opencode.ai/zen/v1",
        "requestTimeoutMs": 120000
      }
    }
  }
}

Or at the agent level:

{
  "agents": {
    "list": [
      {
        "id": "main",
        "model": {
          "primary": "zen/big-<model>",
          "requestTimeoutMs": 120000,
          "fallbacks": ["google/gemini-3-flash-preview", "..."]
        }
      }
    ]
  }
}

On timeout the call should be aborted and surfaced to the fallback dispatcher
as a normal provider error, so the existing fallback chain takes over.

Why this matters

Silent stalls are the worst failure mode for a 24/7 personal-assistant agent:

  • No alert — user is the detector.
  • Fallbacks, retries, and health checks all look green.
  • The only observable signal is the client-side typing TTL reached log line,
    which is a symptom, not a cause.

A simple per-call timeout makes the existing fallback infrastructure actually
work the way users already assume it works.

Workaround currently in use

An external cron watchdog that greps the gateway log for typing TTL reached
events, sends an alert, and restarts the gateway on stall bursts. This is a
safety net, not a fix — the request never gets a fallback attempt and the
typed reply is lost.

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