feat(agents): enforce one librarian timeout budget

- add LIBRARIAN_TIMEOUT config (default 180s) and enforce it with
  asyncio.wait_for inside delegate_to_librarian, covering the live
  paths (steward direct delegation and SSE streaming) that had no cap
- timeouts fail honestly: success=False with a curated butler sentence,
  detail in logs
- set an explicit timeout on TatlockOllamaProvider's AsyncOpenAI client
  from OLLAMA_TIMEOUT instead of the SDK default (~600s per LLM call)
- remove the contradictory unused 60s default from
  AgentRequest.timeout_seconds; coordination falls back to the
  configured budget

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 10:19:16 +02:00
co-authored by Claude Fable 5
parent 99e1fe33ca
commit 18f2e0efbd
9 changed files with 145 additions and 18 deletions
+9 -5
View File
@@ -42,7 +42,7 @@ class Environment(str, Enum):
class Config(BaseSettings):
"""
Global application configuration.
Loads from environment variables and .env file.
Domain-specific configs should be in their respective modules.
"""
@@ -52,18 +52,18 @@ class Config(BaseSettings):
case_sensitive=True,
extra="ignore",
)
# Application
APP_NAME: str = "OpenAI-Compatible API"
APP_VERSION: str = Field(default_factory=_get_version_from_pyproject)
ENVIRONMENT: Environment = Environment.DEVELOPMENT
DEBUG: bool = Field(default=False, description="Debug mode")
# API Configuration
API_HOST: str = Field(default="0.0.0.0", description="API host")
API_PORT: int = Field(default=8000, description="API port")
API_PREFIX: str = Field(default="/v1", description="API route prefix")
# Anthropic Configuration (Claude - cloud fallback)
ANTHROPIC_API_KEY: str | None = Field(
default=None,
@@ -125,6 +125,10 @@ class Config(BaseSettings):
)
# Library-Desk Configuration (The Librarian backend)
LIBRARIAN_TIMEOUT: int = Field(
default=180,
description="Total time budget for a librarian delegation in seconds"
)
LIBRARY_DESK_HOST: HttpUrl = Field(
default="http://localhost:8089",
description="Library-Desk API URL"
@@ -259,7 +263,7 @@ class Config(BaseSettings):
def get_config() -> Config:
"""
Get cached configuration instance.
Uses lru_cache to ensure config is loaded once and reused.
"""
return Config()