honcho/tests/live_llm
Alexei Vedernikov d815c8b8dc
fix(llm): support per-request provider timeouts (#832)
* fix(llm): support per-request provider timeouts

* fix(llm): convert Gemini timeout to milliseconds

* fix(llm): validate Gemini HTTP options

* test(llm): type Anthropic stream context args

* test(llm): live per-request timeout coverage for all providers

Two live checks per provider: a generous timeout asserted at the SDK
call boundary, and a tight timeout that must abort well under the 600s
client default. Gemini's async transport can be aiohttp, so its tight
timeout surfaces as asyncio.TimeoutError rather than httpx.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* style(tests): drop extra blank line in anthropic backend test

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(llm): validate provider_params.timeout at config load

Move the timeout coercion into src.config as coerce_provider_timeout and
run it from a field validator on ModelOverrideSettings.provider_params, so
a bad value in config.toml/env fails at startup with the exact config path
instead of surfacing per-request as a retried 500. Good values normalize
to float seconds at load. The per-request guard in src.llm.backend now
delegates to the same coercion (wrapping ValueError in ValidationException)
and continues to cover extra_params passed programmatically.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: document provider_params.timeout load-time validation and gotchas

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor(llm): address review nits on timeout plumbing

Apply eisene's review feedback:
- Rename PROVIDER_TIMEOUT_ERROR → PROVIDER_TIMEOUT_ERROR_TEXT
- Move request_timeout_from_extra_params from backend.py (pure
  dataclasses) to request_builder.py (request assembly)
- Add comment explaining Gemini's ms timeout conversion
- Generalize _normalize_extra_params with _strip_none_params helper

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Aakash Kattelu <aakash@plasticlabs.ai>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-04 12:43:00 -04:00
..
README.md Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
__init__.py Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
conftest.py Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
model_matrix.py feat: add model config option for json_object mode (#820) 2026-06-23 10:42:03 -04:00
test_live_anthropic.py Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
test_live_gemini.py Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
test_live_openai.py feat(llm backend): enable combined tool calling + structured output in the LLM backend transport layer (#907) 2026-07-15 11:47:49 -04:00
test_live_structured_output_unions.py feat(dialectic): optional structured outputs with limited schema for Dialectic calls (#896) 2026-07-20 18:46:49 -04:00
test_live_timeouts.py fix(llm): support per-request provider timeouts (#832) 2026-08-04 12:43:00 -04:00
test_live_tools_structured_output.py feat(llm backend): enable combined tool calling + structured output in the LLM backend transport layer (#907) 2026-07-15 11:47:49 -04:00

README.md

Live LLM Tests

These tests call real provider APIs and are disabled by default.

Run them with:

uv run pytest tests/live_llm -n 0 --live-llm --no-header -q

Required API key env vars:

  • LLM_ANTHROPIC_API_KEY
  • LLM_OPENAI_API_KEY
  • LLM_GEMINI_API_KEY

Model-family env vars:

  • LIVE_LLM_ANTHROPIC_45_PLUS_MODELS
  • LIVE_LLM_OPENAI_GPT4_MODELS
  • LIVE_LLM_OPENAI_GPT5_MODELS
  • LIVE_LLM_OPENAI_OPENROUTER_NON_REASONING_MODELS (OpenAI-transport → OpenRouter-served non-reasoning models)
  • LIVE_LLM_GEMINI_25_MODELS
  • LIVE_LLM_GEMINI_30_MODELS
  • LIVE_LLM_GEMINI_31_MODELS

Each model env var accepts a comma-separated list of bare model ids or provider-qualified ids.

Examples:

export LIVE_LLM_ANTHROPIC_45_PLUS_MODELS="claude-sonnet-4-5,claude-sonnet-4-6"
export LIVE_LLM_OPENAI_GPT4_MODELS="gpt-4.1"
export LIVE_LLM_OPENAI_GPT5_MODELS="gpt-5,gpt-5.4,gpt-5.4-mini"
export LIVE_LLM_OPENAI_OPENROUTER_NON_REASONING_MODELS="inception/mercury-2"
export LIVE_LLM_GEMINI_25_MODELS="gemini-2.5-flash,gemini-2.5-pro"
export LIVE_LLM_GEMINI_30_MODELS="gemini-3-flash-preview"
export LIVE_LLM_GEMINI_31_MODELS="gemini-3.1-pro-preview"

OpenRouter-routed models require additional env for the proxy endpoint:

export OPENROUTER_API_KEY="sk-or-v1-..."
# Per-feature config example:
#   DERIVER_MODEL_CONFIG__TRANSPORT=openai
#   DERIVER_MODEL_CONFIG__MODEL=inception/mercury-2
#   DERIVER_MODEL_CONFIG__OVERRIDES__BASE_URL=https://openrouter.ai/api/v1
#   DERIVER_MODEL_CONFIG__OVERRIDES__API_KEY_ENV=OPENROUTER_API_KEY

Coverage by provider:

  • Anthropic: structured output path, prompt caching metrics, thinking blocks, multi-turn tool replay
  • OpenAI GPT-4 class: structured outputs, prompt caching
  • OpenAI GPT-5 class (incl. gpt-5.x point-releases): structured outputs, prompt caching, reasoning_effort, max_completion_tokens routing
  • OpenAI transport → OpenRouter non-reasoning models (e.g. inception/mercury-2): non-chat / diffusion architectures must stay on max_tokens, no reasoning_effort, tool-calling parameter-schema compatibility is the canary for exotic OR-served providers
  • Gemini 2.5/3.0 classes: structured outputs, cached-content reuse, thought signatures, multi-turn tool replay
  • Gemini 3.1 class: thinking and tool replay coverage by default; structured-output/caching coverage should only be added once Google documents support for that path