In both ToolCallingLLMCaller._resolve_llm and SimpleLLMAgent._resolve_llm,
the options block was merged after top-level keys were applied, causing
llm_kwargs.update(...) to overwrite top-level temperature/max_tokens/
max_retries with any duplicate values from the options block.
Fix: apply build_llm_kwargs_from_options first, then re-apply the
top-level extracted values so they always win.
ISSUES CLOSED: #11243#11223
The PR added resolve_actor_options() to StrategyActor, LLMStrategizeActor,
and LLMExecuteActor, but the three mock lifecycle SimpleNamespace objects
used by tests did not include this method, causing AttributeError at
runtime:
- features/mocks/mock_strategy_llm.py: make_mock_lifecycle() used by
robot/helper_strategy_actor.py (strategy_actor.robot llm-json test)
and features/steps/strategy_actor_llm_steps.py
- features/steps/llm_actors_coverage_steps.py: _make_mock_lifecycle()
used by llm_actors_coverage.feature scenarios
- robot/helper_m5_e2e_context.py: inline lifecycle SimpleNamespace
used by m5_e2e_verification.robot Execute Phase LLM Uses ACMS Context
All three now include resolve_actor_options=MagicMock(return_value=None)
matching the None-return contract the actors use when no custom backend
is configured.
ISSUES CLOSED: #11256
Extract shared build_llm_kwargs_from_options() utility in actor/config.py
that converts actor-level YAML options (openai_api_base, openai_api_key,
temperature, max_tokens, etc.) into kwargs for ProviderRegistry.create_llm().
Add options field to ActorConfigSchema so it survives Pydantic validation
instead of being silently dropped by extra='ignore' default.
Add resolve_actor_options() to PlanLifecycleService and both LifecycleService
and PlanLifecycleProtocol protocols so every call site can retrieve the
actor's config_blob.options dict.
Fix the four call sites that previously called create_llm() with zero extra
kwargs, preventing local/custom LLM backends from working:
- StrategyActor._execute_with_llm() in strategy_actor.py
- LLMStrategizeActor.execute() in llm_actors.py
- LLMExecuteActor.execute() in llm_actors.py
- SessionWorkflow._resolve_llm() in session_workflow.py
Refactor reactive path (stream_router.py, tool_caller.py) to use the
shared build_llm_kwargs_from_options() utility instead of inline copies.
Wire actor_options_resolver through CLI session builder and A2A facade.
ISSUES CLOSED: #11256