feat(providers): add per-provider and per-model request_timeout_seconds config#12415
feat(providers): add per-provider and per-model request_timeout_seconds config#12415mvanhorn wants to merge 1 commit into
Conversation
…ds config Adds optional providers.<id>.request_timeout_seconds and providers.<id>.models.<model>.timeout_seconds config, resolved via a new hermes_cli/timeouts.py helper and applied where client_kwargs is built in run_agent.py. Zero default behavior change: when both keys are unset, the openai SDK default takes over. Mirrors the existing _get_task_timeout pattern in agent/auxiliary_client.py for auxiliary tasks - the primary turn path just never got the equivalent knob. Cross-project demand: openclaw/openclaw#43946 (17 reactions) asks for exactly this config - specifically calls out Ollama cold-start hanging the client.
|
Merged via PR #12652 — your resolver + init-hook commit (3143d32) was cherry-picked onto current main with your authorship preserved in the rebase merge. Thank you for the contribution! Follow-up commits on top of yours extended the wiring to every other client path (Anthropic native, fallback chain, switch_model, credential rotation, streaming + non-streaming per-call overrides) after live testing with a 0.5s timeout showed the original init-site hook was being overridden by hardcoded Full details: #12652 |
|
Thanks @teknium1, really appreciate the salvage and the credit. Good catch on the 0.5s test exposing that the init-site hook was getting overridden downstream - I only wired it into the OpenAI-wire init path and missed the Anthropic native, fallback chain, and per-call override sites. Glad the resolver held up. |
Summary
Adds
request_timeout_secondsconfig at provider and per-model level, plumbed into the primary LLM client atrun_agent.py:1036viaclient_kwargs["timeout"]. Zero default behavior change - if neither key is set, the client is built exactly as today and the openai SDK default (600s) takes over.Motivation
Hermes wraps the
openaiPython SDK to call every LLM provider. Today notimeoutis passed when building the primary turn client, so every provider inherits the SDK default. That default is wrong in two directions:Hermes already has the
auxiliary.{task}.timeoutpattern atagent/auxiliary_client.py:2240 _get_task_timeoutfor summarization/vision aux tasks. This PR mirrors that shape for the primary request path.Checked for duplicates before opening. PRs matching
provider timeout,request_timeout,http_timeoutare either about Hindsight memory plugin (#9882, #9985, different concern) or provider concurrency semaphores (#7479, different concern). Cross-project signal from OpenClaw #43946 (17 reactions, open).Example config
```yaml
providers:
ollama-local:
request_timeout_seconds: 300 # cold-start tolerance
anthropic:
request_timeout_seconds: 60
models:
claude-opus-4.7:
timeout_seconds: 600 # extended thinking
```
Resolution order: per-model
timeout_seconds> providerrequest_timeout_seconds> SDK default.Changes
hermes_cli/timeouts.pyget_provider_request_timeout(provider, model)reads config with per-model precedencerun_agent.pyclient_kwargs[\"timeout\"]when resolved value is not Nonecli-config.yaml.examplewebsite/docs/user-guide/configuration.mdtests/hermes_cli/test_timeouts.pyNet diff: +141/-1 across 5 files.
Evidence
Test plan