Repository navigation
Description
Description
AgentFactory.create_agent_from_dict() consumes chatToolMode from the caller's model.options.additionalProperties dictionary. Reusing the same definition therefore changes behavior: the first agent has tool_choice="required", while the second has the default "auto". The async factory has the same behavior. The input definition should remain unchanged, and repeated construction should preserve the configured tool choice.
I am taking on a small fix in _parse_chat_options() that copies the additional-properties mapping before extracting the option, with regressions for both factory entry points.
Code Sample
from copy import deepcopy
from unittest.mock import MagicMock
from agent_framework_declarative import AgentFactory
client = MagicMock()
client.model = "test-model"
factory = AgentFactory(client=client)
definition = {
"kind": "Prompt",
"name": "ReusableAgent",
"model": {"options": {"additionalProperties": {
"chatToolMode": "required",
"custom_option": "kept",
}}},
}
original = deepcopy(definition)
first = factory.create_agent_from_dict(definition)
second = factory.create_agent_from_dict(definition)
print(first.default_options["tool_choice"]) # required
print(second.default_options["tool_choice"]) # auto, expected required
assert definition == original # failsError Messages / Stack Traces
No exception is raised; the second agent silently receives a different tool choice.
Package Versions
Reproduced against official main commit 2df61296bb563a95552b18491ad29b1e1a509f81: agent-framework-core 1.20.0 and agent-framework-declarative 1.2.0 source.
Python Version
Python 3.12.14 and 3.14.3 on Windows.
Additional Context
The reproduction uses the public factory entry points with an injected mock client. No model or network call is made. required, none, and auto all remove the key from the caller's definition; required and none also change on the second construction. The change is limited to configuration parsing, with no function-loop or provider transport change.
Metadata
Metadata
Labels
Type
Projects
- StatusShow more project fieldsDone
Activity
github-actions commentedon Oct 5, 2026
🤖 Automated triage reproduction notes (agent-authored — trust but verify)
Agent analysis
Repro:
python/packages/declarative/agent_framework_declarative/_loader.py::AgentFactory._parse_chat_optionsat line 743 mutatesModelOptions.additionalPropertieswhenchatToolModeis present; both dictionary factory entry points exhibit this when called twice with the same definition. Minimal repro: inject aMagicMockclient, configurechatToolMode="required", invoke either factory twice on one dictionary, and compare both tool choices and the dictionary against a deep copy; the observed values are['required', 'auto', False].python/packages/declarative/tests/test_declarative_loader.pyagent-framework-declarative 1.2.0agent-framework-declarative 1.2.0