@@ -239,6 +239,62 @@ def test_to_dict(self, weather_tool, component_tool, monkeypatch):
239
239
},
240
240
}
241
241
242
+ def test_to_dict_with_toolset (self , monkeypatch , weather_tool ):
243
+ monkeypatch .setenv ("OPENAI_API_KEY" , "fake-key" )
244
+ toolset = Toolset (tools = [weather_tool ])
245
+ agent = Agent (chat_generator = OpenAIChatGenerator (), tools = toolset )
246
+ serialized_agent = agent .to_dict ()
247
+ assert serialized_agent == {
248
+ "type" : "haystack.components.agents.agent.Agent" ,
249
+ "init_parameters" : {
250
+ "chat_generator" : {
251
+ "type" : "haystack.components.generators.chat.openai.OpenAIChatGenerator" ,
252
+ "init_parameters" : {
253
+ "model" : "gpt-4o-mini" ,
254
+ "streaming_callback" : None ,
255
+ "api_base_url" : None ,
256
+ "organization" : None ,
257
+ "generation_kwargs" : {},
258
+ "api_key" : {"type" : "env_var" , "env_vars" : ["OPENAI_API_KEY" ], "strict" : True },
259
+ "timeout" : None ,
260
+ "max_retries" : None ,
261
+ "tools" : None ,
262
+ "tools_strict" : False ,
263
+ "http_client_kwargs" : None ,
264
+ },
265
+ },
266
+ "tools" : {
267
+ "type" : "haystack.tools.toolset.Toolset" ,
268
+ "data" : {
269
+ "tools" : [
270
+ {
271
+ "type" : "haystack.tools.tool.Tool" ,
272
+ "data" : {
273
+ "name" : "weather_tool" ,
274
+ "description" : "Provides weather information for a given location." ,
275
+ "parameters" : {
276
+ "type" : "object" ,
277
+ "properties" : {"location" : {"type" : "string" }},
278
+ "required" : ["location" ],
279
+ },
280
+ "function" : "test_agent.weather_function" ,
281
+ "outputs_to_string" : None ,
282
+ "inputs_from_state" : None ,
283
+ "outputs_to_state" : None ,
284
+ },
285
+ }
286
+ ]
287
+ },
288
+ },
289
+ "system_prompt" : None ,
290
+ "exit_conditions" : ["text" ],
291
+ "state_schema" : {},
292
+ "max_agent_steps" : 100 ,
293
+ "raise_on_tool_invocation_failure" : False ,
294
+ "streaming_callback" : None ,
295
+ },
296
+ }
297
+
242
298
def test_from_dict (self , weather_tool , component_tool , monkeypatch ):
243
299
monkeypatch .setenv ("OPENAI_API_KEY" , "fake-key" )
244
300
data = {
@@ -318,6 +374,67 @@ def test_from_dict(self, weather_tool, component_tool, monkeypatch):
318
374
"messages" : {"handler" : merge_lists , "type" : List [ChatMessage ]},
319
375
}
320
376
377
+ def test_from_dict_with_toolset (self , monkeypatch ):
378
+ monkeypatch .setenv ("OPENAI_API_KEY" , "fake-key" )
379
+ data = {
380
+ "type" : "haystack.components.agents.agent.Agent" ,
381
+ "init_parameters" : {
382
+ "chat_generator" : {
383
+ "type" : "haystack.components.generators.chat.openai.OpenAIChatGenerator" ,
384
+ "init_parameters" : {
385
+ "model" : "gpt-4o-mini" ,
386
+ "streaming_callback" : None ,
387
+ "api_base_url" : None ,
388
+ "organization" : None ,
389
+ "generation_kwargs" : {},
390
+ "api_key" : {"type" : "env_var" , "env_vars" : ["OPENAI_API_KEY" ], "strict" : True },
391
+ "timeout" : None ,
392
+ "max_retries" : None ,
393
+ "tools" : None ,
394
+ "tools_strict" : False ,
395
+ "http_client_kwargs" : None ,
396
+ },
397
+ },
398
+ "tools" : {
399
+ "type" : "haystack.tools.toolset.Toolset" ,
400
+ "data" : {
401
+ "tools" : [
402
+ {
403
+ "type" : "haystack.tools.tool.Tool" ,
404
+ "data" : {
405
+ "name" : "weather_tool" ,
406
+ "description" : "Provides weather information for a given location." ,
407
+ "parameters" : {
408
+ "type" : "object" ,
409
+ "properties" : {"location" : {"type" : "string" }},
410
+ "required" : ["location" ],
411
+ },
412
+ "function" : "test_agent.weather_function" ,
413
+ "outputs_to_string" : None ,
414
+ "inputs_from_state" : None ,
415
+ "outputs_to_state" : None ,
416
+ },
417
+ }
418
+ ]
419
+ },
420
+ },
421
+ "system_prompt" : None ,
422
+ "exit_conditions" : ["text" ],
423
+ "state_schema" : {},
424
+ "max_agent_steps" : 100 ,
425
+ "raise_on_tool_invocation_failure" : False ,
426
+ "streaming_callback" : None ,
427
+ },
428
+ }
429
+ agent = Agent .from_dict (data )
430
+ assert isinstance (agent , Agent )
431
+ assert isinstance (agent .chat_generator , OpenAIChatGenerator )
432
+ assert agent .chat_generator .model == "gpt-4o-mini"
433
+ assert agent .chat_generator .api_key == Secret .from_env_var ("OPENAI_API_KEY" )
434
+ assert isinstance (agent .tools , Toolset )
435
+ assert agent .tools [0 ].function is weather_function
436
+ assert agent .exit_conditions == ["text" ]
437
+
321
438
def test_serde (self , weather_tool , component_tool , monkeypatch ):
322
439
monkeypatch .setenv ("FAKE_OPENAI_KEY" , "fake-key" )
323
440
generator = OpenAIChatGenerator (api_key = Secret .from_env_var ("FAKE_OPENAI_KEY" ))
@@ -700,59 +817,18 @@ def test_agent_tracing_span_run(self, caplog, monkeypatch, weather_tool):
700
817
expected_tag_values = [
701
818
"chat_generator" ,
702
819
"MockChatGeneratorWithoutRunAsync" ,
703
- {"messages" : "list" , "tools" : "list" },
704
- {},
705
- {},
706
- {
707
- "messages" : [ChatMessage .from_user (text = "What's the weather in Paris?" )],
708
- "tools" : [
709
- Tool (
710
- name = "weather_tool" ,
711
- description = "Provides weather information for a given location." ,
712
- parameters = {
713
- "type" : "object" ,
714
- "properties" : {"location" : {"type" : "string" }},
715
- "required" : ["location" ],
716
- },
717
- function = weather_function ,
718
- outputs_to_string = None ,
719
- inputs_from_state = None ,
720
- outputs_to_state = None ,
721
- )
722
- ],
723
- },
820
+ '{"messages": "list", "tools": "list"}' ,
821
+ "{}" ,
822
+ "{}" ,
823
+ '{"messages": [{"role": "user", "meta": {}, "name": null, "content": [{"text": "What\' s the weather in Paris?"}]}], "tools": [{"type": "haystack.tools.tool.Tool", "data": {"name": "weather_tool", "description": "Provides weather information for a given location.", "parameters": {"type": "object", "properties": {"location": {"type": "string"}}, "required": ["location"]}, "function": "test_agent.weather_function", "outputs_to_string": null, "inputs_from_state": null, "outputs_to_state": null}}]}' ,
724
824
1 ,
725
- {"replies" : [ChatMessage . from_assistant ( text = " Hello")]} ,
825
+ ' {"replies": [{"role": "assistant", "meta": {}, "name": null, "content": [{" text": " Hello"}]}]}' ,
726
826
100 ,
727
- [
728
- Tool (
729
- name = "weather_tool" ,
730
- description = "Provides weather information for a given location." ,
731
- parameters = {
732
- "type" : "object" ,
733
- "properties" : {"location" : {"type" : "string" }},
734
- "required" : ["location" ],
735
- },
736
- function = weather_function ,
737
- outputs_to_string = None ,
738
- inputs_from_state = None ,
739
- outputs_to_state = None ,
740
- )
741
- ],
742
- ["text" ],
743
- {
744
- "messages" : {
745
- "type" : "typing.List[haystack.dataclasses.chat_message.ChatMessage]" ,
746
- "handler" : "haystack.dataclasses.state_utils.merge_lists" ,
747
- }
748
- },
749
- {"messages" : [ChatMessage .from_user (text = "What's the weather in Paris?" )], "streaming_callback" : None },
750
- {
751
- "messages" : [
752
- ChatMessage .from_user (text = "What's the weather in Paris?" ),
753
- ChatMessage .from_assistant (text = "Hello" ),
754
- ]
755
- },
827
+ '[{"type": "haystack.tools.tool.Tool", "data": {"name": "weather_tool", "description": "Provides weather information for a given location.", "parameters": {"type": "object", "properties": {"location": {"type": "string"}}, "required": ["location"]}, "function": "test_agent.weather_function", "outputs_to_string": null, "inputs_from_state": null, "outputs_to_state": null}}]' ,
828
+ '["text"]' ,
829
+ '{"messages": {"type": "typing.List[haystack.dataclasses.chat_message.ChatMessage]", "handler": "haystack.dataclasses.state_utils.merge_lists"}}' ,
830
+ '{"messages": [{"role": "user", "meta": {}, "name": null, "content": [{"text": "What\' s the weather in Paris?"}]}], "streaming_callback": null}' ,
831
+ '{"messages": [{"role": "user", "meta": {}, "name": null, "content": [{"text": "What\' s the weather in Paris?"}]}, {"role": "assistant", "meta": {}, "name": null, "content": [{"text": "Hello"}]}]}' ,
756
832
1 ,
757
833
]
758
834
for idx , record in enumerate (tags_records ):
@@ -801,59 +877,18 @@ async def test_agent_tracing_span_async_run(self, caplog, monkeypatch, weather_t
801
877
expected_tag_values = [
802
878
"chat_generator" ,
803
879
"MockChatGeneratorWithRunAsync" ,
804
- {"messages" : "list" , "tools" : "list" },
805
- {},
806
- {},
807
- {
808
- "messages" : [ChatMessage .from_user (text = "What's the weather in Paris?" )],
809
- "tools" : [
810
- Tool (
811
- name = "weather_tool" ,
812
- description = "Provides weather information for a given location." ,
813
- parameters = {
814
- "type" : "object" ,
815
- "properties" : {"location" : {"type" : "string" }},
816
- "required" : ["location" ],
817
- },
818
- function = weather_function ,
819
- outputs_to_string = None ,
820
- inputs_from_state = None ,
821
- outputs_to_state = None ,
822
- )
823
- ],
824
- },
880
+ '{"messages": "list", "tools": "list"}' ,
881
+ "{}" ,
882
+ "{}" ,
883
+ '{"messages": [{"role": "user", "meta": {}, "name": null, "content": [{"text": "What\' s the weather in Paris?"}]}], "tools": [{"type": "haystack.tools.tool.Tool", "data": {"name": "weather_tool", "description": "Provides weather information for a given location.", "parameters": {"type": "object", "properties": {"location": {"type": "string"}}, "required": ["location"]}, "function": "test_agent.weather_function", "outputs_to_string": null, "inputs_from_state": null, "outputs_to_state": null}}]}' ,
825
884
1 ,
826
- {"replies" : [ChatMessage . from_assistant ( text = " Hello from run_async")]} ,
885
+ ' {"replies": [{"role": "assistant", "meta": {}, "name": null, "content": [{" text": " Hello from run_async"}]}]}' ,
827
886
100 ,
828
- [
829
- Tool (
830
- name = "weather_tool" ,
831
- description = "Provides weather information for a given location." ,
832
- parameters = {
833
- "type" : "object" ,
834
- "properties" : {"location" : {"type" : "string" }},
835
- "required" : ["location" ],
836
- },
837
- function = weather_function ,
838
- outputs_to_string = None ,
839
- inputs_from_state = None ,
840
- outputs_to_state = None ,
841
- )
842
- ],
843
- ["text" ],
844
- {
845
- "messages" : {
846
- "type" : "typing.List[haystack.dataclasses.chat_message.ChatMessage]" ,
847
- "handler" : "haystack.dataclasses.state_utils.merge_lists" ,
848
- }
849
- },
850
- {"messages" : [ChatMessage .from_user (text = "What's the weather in Paris?" )], "streaming_callback" : None },
851
- {
852
- "messages" : [
853
- ChatMessage .from_user (text = "What's the weather in Paris?" ),
854
- ChatMessage .from_assistant (text = "Hello from run_async" ),
855
- ]
856
- },
887
+ '[{"type": "haystack.tools.tool.Tool", "data": {"name": "weather_tool", "description": "Provides weather information for a given location.", "parameters": {"type": "object", "properties": {"location": {"type": "string"}}, "required": ["location"]}, "function": "test_agent.weather_function", "outputs_to_string": null, "inputs_from_state": null, "outputs_to_state": null}}]' ,
888
+ '["text"]' ,
889
+ '{"messages": {"type": "typing.List[haystack.dataclasses.chat_message.ChatMessage]", "handler": "haystack.dataclasses.state_utils.merge_lists"}}' ,
890
+ '{"messages": [{"role": "user", "meta": {}, "name": null, "content": [{"text": "What\' s the weather in Paris?"}]}], "streaming_callback": null}' ,
891
+ '{"messages": [{"role": "user", "meta": {}, "name": null, "content": [{"text": "What\' s the weather in Paris?"}]}, {"role": "assistant", "meta": {}, "name": null, "content": [{"text": "Hello from run_async"}]}]}' ,
857
892
1 ,
858
893
]
859
894
for idx , record in enumerate (tags_records ):
0 commit comments