@@ -37,6 +37,7 @@ To report an issue with the client library, or request additional features, plea
37
37
- [ Azure Function Call] ( #create-agent-with-azure-function-call )
38
38
- [ OpenAPI] ( #create-agent-with-openapi )
39
39
- [ Fabric data] ( #create-an-agent-with-fabric )
40
+ - [ Connected agents] ( #create-an-agent-using-another-agents )
40
41
- [ Deep Research] ( #create-agent-with-deep-research )
41
42
- [ Create thread] ( #create-thread ) with
42
43
- [ Tool resource] ( #create-thread-with-tool-resource )
@@ -801,6 +802,178 @@ with project_client:
801
802
802
803
<!-- END SNIPPET -->
803
804
805
+ ### Create an Agent using another agents
806
+
807
+ We can use ` ConnectedAgentTool ` to call specialized agents. In the example below we will create two agents, one is returning the Microsoft stock price and another returns weather. Note that the ` ConnectedAgentTool ` does not support local functions, we will use Azure function to return weather. The code of that function is given below; please see [ Azure Function Call] ( #create-agent-with-azure-function-call ) section for the instructions on how to deploy Azure Function.
808
+
809
+ ``` python
810
+ import azure.functions as func
811
+ import datetime
812
+ import json
813
+ import logging
814
+
815
+ app = func.FunctionApp()
816
+
817
+ @app.function_name (name = " GetWeather" )
818
+ @app.queue_trigger (
819
+ arg_name = " arguments" ,
820
+ queue_name = " weather-input" ,
821
+ connection = " AzureWebJobsStorage" )
822
+ @app.queue_output (
823
+ arg_name = " outputQueue" ,
824
+ queue_name = " weather-output" ,
825
+ connection = " AzureWebJobsStorage" )
826
+ def foo (arguments : func.QueueMessage, outputQueue : func.Out[str ]) -> None :
827
+ """
828
+ The function, answering question about weather.
829
+
830
+ :param arguments: The arguments, containing json serialized request.
831
+ :param outputQueue: The output queue to write messages to.
832
+ """
833
+
834
+ parsed_args = json.loads(arguments.get_body().decode(' utf-8' ))
835
+ location = parsed_args.get(" Location" )
836
+ try :
837
+ response = {
838
+ " Value" : " 60 degrees and cloudy" if location == " Seattle" else " 10 degrees and sunny" ,
839
+ " CorrelationId" : parsed_args[' CorrelationId' ]
840
+ }
841
+ outputQueue.set(json.dumps(response))
842
+ logging.info(f ' The function returns the following message: { json.dumps(response)} ' )
843
+ except Exception as e:
844
+ logging.error(f " Error processing message: { e} " )
845
+ raise
846
+ ```
847
+ We will define two agents that has descriptions, explaining when they need to be called.
848
+
849
+ <!-- SNIPPET:sample_agents_multiple_connected_agents.create_two_toy_agents -->
850
+
851
+ ``` python
852
+ connected_agent_name = " stock_price_bot"
853
+ weather_agent_name = " weather_bot"
854
+
855
+ stock_price_agent = agents_client.create_agent(
856
+ model = os.environ[" MODEL_DEPLOYMENT_NAME" ],
857
+ name = connected_agent_name,
858
+ instructions = (
859
+ " Your job is to get the stock price of a company. If asked for the Microsoft stock price, always return $350."
860
+ ),
861
+ )
862
+
863
+ azure_function_tool = AzureFunctionTool(
864
+ name = " GetWeather" ,
865
+ description = " Get answers from the weather bot." ,
866
+ parameters = {
867
+ " type" : " object" ,
868
+ " properties" : {
869
+ " Location" : {" type" : " string" , " description" : " The location to get the weather for." },
870
+ },
871
+ },
872
+ input_queue = AzureFunctionStorageQueue(
873
+ queue_name = " weather-input" ,
874
+ storage_service_endpoint = storage_service_endpoint,
875
+ ),
876
+ output_queue = AzureFunctionStorageQueue(
877
+ queue_name = " weather-output" ,
878
+ storage_service_endpoint = storage_service_endpoint,
879
+ ),
880
+ )
881
+
882
+ weather_agent = agents_client.create_agent(
883
+ model = os.environ[" MODEL_DEPLOYMENT_NAME" ],
884
+ name = weather_agent_name,
885
+ instructions = (
886
+ " Your job is to get the weather for a given location. "
887
+ " Use the provided function to get the weather in the given location."
888
+ ),
889
+ tools = azure_function_tool.definitions,
890
+ )
891
+
892
+ # Initialize Connected Agent tools with the agent id, name, and description
893
+ connected_agent = ConnectedAgentTool(
894
+ id = stock_price_agent.id, name = connected_agent_name, description = " Gets the stock price of a company"
895
+ )
896
+ connected_weather_agent = ConnectedAgentTool(
897
+ id = weather_agent.id, name = weather_agent_name, description = " Gets the weather for a given location"
898
+ )
899
+ ```
900
+
901
+ <!-- END SNIPPET -->
902
+
903
+ Add the ` ConnectedAgentTool ` -s to main agent.
904
+
905
+ <!-- SNIPPET:sample_agents_multiple_connected_agents.create_agent_with_connected_agent_tool -->
906
+
907
+ ``` python
908
+ # Create agent with the Connected Agent tool and process assistant run
909
+ agent = agents_client.create_agent(
910
+ model = os.environ[" MODEL_DEPLOYMENT_NAME" ],
911
+ name = " my-assistant" ,
912
+ instructions = " You are a helpful assistant, and use the connected agents to get stock prices and weather." ,
913
+ tools = [
914
+ connected_agent.definitions[0 ],
915
+ connected_weather_agent.definitions[0 ],
916
+ ],
917
+ )
918
+ ```
919
+
920
+ <!-- END SNIPPET -->
921
+
922
+ Create thread and run.
923
+
924
+ <!-- SNIPPET:sample_agents_multiple_connected_agents.run_agent_with_connected_agent_tool -->
925
+
926
+ ``` python
927
+ # Create thread for communication
928
+ thread = agents_client.threads.create()
929
+ print (f " Created thread, ID: { thread.id} " )
930
+
931
+ # Create message to thread
932
+ message = agents_client.messages.create(
933
+ thread_id = thread.id,
934
+ role = MessageRole.USER ,
935
+ content = " What is the stock price of Microsoft and the weather in Seattle?" ,
936
+ )
937
+ print (f " Created message, ID: { message.id} " )
938
+
939
+ # Create and process Agent run in thread with tools
940
+ run = agents_client.runs.create_and_process(thread_id = thread.id, agent_id = agent.id)
941
+ print (f " Run finished with status: { run.status} " )
942
+ ```
943
+
944
+ <!-- END SNIPPET -->
945
+
946
+ To understand what calls were made by the main agent to the connected ones, we will list run steps.
947
+
948
+ <!-- SNIPPET:sample_agents_multiple_connected_agents.list_tool_calls -->
949
+
950
+ ``` python
951
+ for run_step in agents_client.run_steps.list(thread_id = thread.id, run_id = run.id, order = ListSortOrder.ASCENDING ):
952
+ if isinstance (run_step.step_details, RunStepToolCallDetails):
953
+ for tool_call in run_step.step_details.tool_calls:
954
+ print (f " \t Agent: { tool_call._data[' connected_agent' ][' name' ]} "
955
+ f " query: { tool_call._data[' connected_agent' ][' arguments' ]} " ,
956
+ f " output: { tool_call._data[' connected_agent' ][' output' ]} " )
957
+ ```
958
+
959
+ <!-- END SNIPPET -->
960
+
961
+ The messages contain references, marked by unicode opening and closing brackets, which cannot be printed by python ` print ` command. To fix this issue we will replace them by ASCII brackets.
962
+
963
+ <!-- SNIPPET:sample_agents_multiple_connected_agents.list_messages -->
964
+
965
+ ``` python
966
+ # Fetch and log all messages
967
+ messages = agents_client.messages.list(thread_id = thread.id, order = ListSortOrder.ASCENDING )
968
+ for msg in messages:
969
+ if msg.text_messages:
970
+ last_text = msg.text_messages[- 1 ]
971
+ text = last_text.text.value.replace(' \u3010 ' , ' [' ).replace(' \u3011 ' , ' ]' )
972
+ print (f " { msg.role} : { text} " )
973
+ ```
974
+
975
+ <!-- END SNIPPET -->
976
+
804
977
805
978
### Create Thread
806
979
0 commit comments