Summary
The main conversation loop at run_agent.py:4683-4684 constructs its request client from self._client_kwargs (the updated runtime kwargs). However, the auxiliary client (agent/auxiliary_client.py) resolves providers via a completely independent code path (_resolve_task_provider_model() → resolve_provider_client()).
This means any runtime changes to _client_kwargs (e.g., model switch, provider override, base_url update) are not reflected in auxiliary tasks.
Affected Code Paths
All auxiliary consumers go through get_text_auxiliary_client(task) or get_async_text_auxiliary_client(task):
| Purpose / Task |
Entry Point |
| Context compression |
get_text_auxiliary_client("compression") |
| Summarization |
get_text_auxiliary_client("summarization") |
| Memory flush |
get_text_auxiliary_client("memory_flush") |
| Vision analysis |
resolve_vision_provider_client() |
Impact
- Severity: Medium
- Scope: All auxiliary tasks across every platform (CLI, Telegram gateway, cron jobs)
Symptoms
- User switches model/provider mid-session via
/model → main loop picks it up, but compression/summarization/vision still use the original provider from config/env.
- Runtime
_client_kwargs mutations (base_url, api_key changes) are invisible to auxiliary calls.
- Inconsistent behavior: main LLM call succeeds with new provider, but auxiliary task fails or returns stale results because it resolved a different (or unavailable) backend.
Root Cause
Two separate resolution paths:
Main loop (correct — runtime-aware):
# run_agent.py ~L4683-4684
request_client = self._create_request_openai_client(reason="chat_completion_request")
result["response"] = request_client.chat.completions.create(**api_kwargs)
# Uses self._client_kwargs which is updated at runtime
Auxiliary (stale — config-only):
# auxiliary_client.py get_text_auxiliary_client()
provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(task or None)
return resolve_provider_client(provider, model=model, ...)
# Reads from config/env, never sees self._client_kwargs
Suggested Fix Direction
Pass runtime client kwargs (or the resolved client itself) into auxiliary call sites so they reuse the same resolution as the main loop. At minimum:
- Add an optional
runtime_client_kwargs parameter to get_text_auxiliary_client() / get_async_text_auxiliary_client().
- When provided, skip
_resolve_task_provider_model() and build the client directly from the passed kwargs.
- Callers in
run_agent.py pass self._client_kwargs; fallback for external callers (gateway, cron) remains current behavior.
Environment
- Relevant file:
agent/auxiliary_client.py, run_agent.py
- AIAgent class owns
self._client_kwargs which is the source of truth for the main loop
Summary
The main conversation loop at
run_agent.py:4683-4684constructs its request client fromself._client_kwargs(the updated runtime kwargs). However, the auxiliary client (agent/auxiliary_client.py) resolves providers via a completely independent code path (_resolve_task_provider_model()→resolve_provider_client()).This means any runtime changes to
_client_kwargs(e.g., model switch, provider override, base_url update) are not reflected in auxiliary tasks.Affected Code Paths
All auxiliary consumers go through
get_text_auxiliary_client(task)orget_async_text_auxiliary_client(task):get_text_auxiliary_client("compression")get_text_auxiliary_client("summarization")get_text_auxiliary_client("memory_flush")resolve_vision_provider_client()Impact
Symptoms
/model→ main loop picks it up, but compression/summarization/vision still use the original provider from config/env._client_kwargsmutations (base_url, api_key changes) are invisible to auxiliary calls.Root Cause
Two separate resolution paths:
Main loop (correct — runtime-aware):
Auxiliary (stale — config-only):
Suggested Fix Direction
Pass runtime client kwargs (or the resolved client itself) into auxiliary call sites so they reuse the same resolution as the main loop. At minimum:
runtime_client_kwargsparameter toget_text_auxiliary_client()/get_async_text_auxiliary_client()._resolve_task_provider_model()and build the client directly from the passed kwargs.run_agent.pypassself._client_kwargs; fallback for external callers (gateway, cron) remains current behavior.Environment
agent/auxiliary_client.py,run_agent.pyself._client_kwargswhich is the source of truth for the main loop