Skip to content

Commit bbcd63a

Browse files
committed
refactor(config): centralize agent ModelSettings via resolve_model_settings()
Adding an agent-facing LLM knob previously meant touching every agent builder to read yet another get_*() (extra_headers, timeout_extra_args, parallel_tool_calls, …) — and it was easy to forget one: build_lint_agent never set parallel_tool_calls, so query and lint silently disagreed on it. Add config.resolve_model_settings(), the single place that assembles all agents-SDK ModelSettings kwargs from the process-wide runtime stashes. Both build_query_agent and build_lint_agent now do `ModelSettings(**resolve_model_settings())`, so a new knob is wired in one place and every agent stays in sync. It assembles on read from the existing getters, preserving "set_extra_headers(...) reaches the agent" (used by the compiler and by tests) rather than snapshotting into a separate stash. Note: build_lint_agent now also honors parallel_tool_calls (it didn't before), making lint consistent with query/chat — including needing `null` on Bedrock.
1 parent 2c30d18 commit bbcd63a

4 files changed

Lines changed: 46 additions & 11 deletions

File tree

openkb/agent/linter.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from agents.model_settings import ModelSettings
99

1010
from openkb.agent.tools import list_wiki_files, read_wiki_file
11-
from openkb.config import get_extra_headers, get_timeout_extra_args
11+
from openkb.config import resolve_model_settings
1212
from openkb.schema import get_agents_md
1313

1414
MAX_TURNS = 50
@@ -82,10 +82,7 @@ def read_file(path: str) -> str:
8282
instructions=instructions,
8383
tools=[list_files, read_file],
8484
model=f"litellm/{model}",
85-
model_settings=ModelSettings(
86-
extra_headers=get_extra_headers() or None,
87-
extra_args=get_timeout_extra_args(),
88-
),
85+
model_settings=ModelSettings(**resolve_model_settings()),
8986
)
9087

9188

openkb/agent/query.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
read_wiki_image,
1313
write_kb_file,
1414
)
15-
from openkb.config import get_extra_headers, get_parallel_tool_calls, get_timeout_extra_args
15+
from openkb.config import resolve_model_settings
1616
from openkb.schema import get_agents_md
1717

1818
MAX_TURNS = 50
@@ -95,11 +95,7 @@ def get_image(image_path: str) -> ToolOutputImage | ToolOutputText:
9595
instructions=instructions,
9696
tools=[read_file, get_page_content, get_image],
9797
model=f"litellm/{model}",
98-
model_settings=ModelSettings(
99-
parallel_tool_calls=get_parallel_tool_calls(),
100-
extra_headers=get_extra_headers() or None,
101-
extra_args=get_timeout_extra_args(),
102-
),
98+
model_settings=ModelSettings(**resolve_model_settings()),
10399
)
104100

105101

openkb/config.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,23 @@ def get_parallel_tool_calls() -> bool | None:
300300
return _runtime_parallel_tool_calls
301301

302302

303+
def resolve_model_settings() -> dict[str, Any]:
304+
"""Assemble the agents-SDK ``ModelSettings`` kwargs from the process-wide LLM
305+
runtime settings (populated by ``cli._setup_llm_key``).
306+
307+
This is the single place that maps runtime LLM config onto agent model
308+
settings: every agent builder does ``ModelSettings(**resolve_model_settings())``
309+
rather than enumerating the individual getters, so a new agent-facing knob
310+
is wired in here once and can't be silently forgotten by one builder.
311+
``None`` values are what the agents SDK treats as "unset / provider default".
312+
"""
313+
return {
314+
"extra_headers": get_extra_headers() or None,
315+
"extra_args": get_timeout_extra_args(),
316+
"parallel_tool_calls": get_parallel_tool_calls(),
317+
}
318+
319+
303320
def load_config(config_path: Path) -> dict[str, Any]:
304321
"""Load YAML config from config_path, merged with DEFAULT_CONFIG.
305322

tests/test_config.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
load_config,
99
resolve_extra_headers,
1010
resolve_litellm_settings,
11+
resolve_model_settings,
1112
resolve_parallel_tool_calls,
1213
resolve_timeout,
1314
save_config,
@@ -17,6 +18,30 @@
1718
)
1819

1920

21+
def test_resolve_model_settings_assembles_from_runtime_stashes():
22+
# One place that assembles every agents-SDK ModelSettings kwarg from the
23+
# process-wide runtime stashes, so agent builders don't each enumerate them.
24+
set_extra_headers({"X-A": "1"})
25+
set_timeout(1200.0)
26+
set_parallel_tool_calls(False)
27+
assert resolve_model_settings() == {
28+
"extra_headers": {"X-A": "1"},
29+
"extra_args": {"timeout": 1200.0},
30+
"parallel_tool_calls": False,
31+
}
32+
33+
34+
def test_resolve_model_settings_empty_is_all_omitted():
35+
set_extra_headers({})
36+
set_timeout(None)
37+
set_parallel_tool_calls(None)
38+
assert resolve_model_settings() == {
39+
"extra_headers": None,
40+
"extra_args": None,
41+
"parallel_tool_calls": None,
42+
}
43+
44+
2045
def test_parallel_tool_calls_defaults_to_false():
2146
# Default preserves the historical behavior: force sequential tool calls.
2247
assert DEFAULT_CONFIG["parallel_tool_calls"] is False

0 commit comments

Comments
 (0)