1+ # pylint: disable=line-too-long,useless-suppression
2+ # ------------------------------------
3+ # Copyright (c) Microsoft Corporation.
4+ # Licensed under the MIT License.
5+ # ------------------------------------
6+
7+ """
8+ DESCRIPTION:
9+ This sample demonstrates how to use agent operations with the
10+ OpenAPI tool from the Azure Agents service using a synchronous client.
11+ To learn more about OpenAPI specs, visit https://learn.microsoft.com/openapi
12+
13+ USAGE:
14+ python openapi.py
15+
16+ Before running the sample:
17+
18+ pip install azure-ai-agents azure-identity jsonref
19+
20+ Set these environment variables with your own values:
21+ 1) PROJECT_ENDPOINT - the Azure AI Agents endpoint.
22+ 2) MODEL_DEPLOYMENT_NAME - The deployment name of the AI model, as found under the "Name" column in
23+ the "Models + endpoints" tab in your Azure AI Foundry project.
24+ """
25+ # <initialization>
26+ # Import necessary libraries
27+ import os
28+ import jsonref
29+ from azure .ai .agents import AgentsClient
30+ from azure .identity import DefaultAzureCredential
31+ from azure .ai .agents .models import OpenApiTool , OpenApiAnonymousAuthDetails
32+ from dotenv import load_dotenv
33+ load_dotenv ()
34+
35+ # Initialize the Agents Client using the endpoint and default credentials
36+ agents_client = AgentsClient (
37+ endpoint = os .environ ["PROJECT_ENDPOINT" ],
38+ credential = DefaultAzureCredential (),
39+ )
40+ # </initialization>
41+
42+ # <weather_tool_setup>
43+ # --- Weather OpenAPI Tool Setup ---
44+ # Load the OpenAPI specification for the weather service from a local JSON file using jsonref to handle references
45+ with open (os .path .join (os .path .dirname (__file__ ), "weather_openapi.json" ), "r" ) as f :
46+ openapi_weather = jsonref .loads (f .read ())
47+ # </weather_tool_setup>
48+
49+ # <countries_tool_setup>
50+ # --- Countries OpenAPI Tool Setup ---
51+ # Load the OpenAPI specification for the countries service from a local JSON file
52+ with open (os .path .join (os .path .dirname (__file__ ), "countries.json" ), "r" ) as f :
53+ openapi_countries = jsonref .loads (f .read ())
54+
55+ # Create Auth object for the OpenApiTool (note: using anonymous auth here; connection or managed identity requires additional setup)
56+ auth = OpenApiAnonymousAuthDetails ()
57+
58+ # Initialize the main OpenAPI tool definition for weather
59+ openapi_tool = OpenApiTool (
60+ name = "get_weather" , spec = openapi_weather , description = "Retrieve weather information for a location" , auth = auth
61+ )
62+ # Add the countries API definition to the same tool object
63+ openapi_tool .add_definition (
64+ name = "get_countries" , spec = openapi_countries , description = "Retrieve a list of countries" , auth = auth
65+ )
66+ # </countries_tool_setup>
67+
68+ # Use the agents client context manager
69+ with agents_client :
70+ # <agent_creation>
71+ # --- Agent Creation ---
72+ # Create an agent configured with the combined OpenAPI tool definitions
73+ agent = agents_client .create_agent (
74+ model = os .environ ["MODEL_DEPLOYMENT_NAME" ], # Specify the model deployment
75+ name = "my-agent" , # Give the agent a name
76+ instructions = "You are a helpful agent" , # Define agent's role
77+ tools = openapi_tool .definitions , # Provide the list of tool definitions
78+ )
79+ print (f"Created agent, ID: { agent .id } " )
80+ # </agent_creation>
81+
82+ # <thread_management>
83+ # --- Thread Management ---
84+ # Create a new conversation thread for the interaction
85+ thread = agents_client .create_thread ()
86+ print (f"Created thread, ID: { thread .id } " )
87+
88+ # Create the initial user message in the thread
89+ message = agents_client .create_message (
90+ thread_id = thread .id ,
91+ role = "user" ,
92+ content = "What's the weather in Seattle and What is the name and population of the country that uses currency with abbreviation THB?" ,
93+ )
94+ print (f"Created message, ID: { message .id } " )
95+ # </thread_management>
96+
97+ # <message_processing>
98+ # --- Message Processing (Run Creation and Auto-processing) ---
99+ # Create and automatically process the run, handling tool calls internally
100+ # Note: This differs from the function_tool example where tool calls are handled manually
101+ run = agents_client .create_and_process_run (thread_id = thread .id , agent_id = agent .id )
102+ print (f"Run finished with status: { run .status } " )
103+ # </message_processing>
104+
105+ # <tool_execution_loop> # Note: This section now processes completed steps, as create_and_process_run handles execution
106+ # --- Post-Run Step Analysis ---
107+ if run .status == "failed" :
108+ print (f"Run failed: { run .last_error } " )
109+
110+ # Retrieve the steps taken during the run for analysis
111+ run_steps = agents_client .list_run_steps (thread_id = thread .id , run_id = run .id )
112+
113+ # Loop through each step to display information
114+ for step in run_steps .data :
115+ print (f"Step { step ['id' ]} status: { step ['status' ]} " )
116+
117+ # Check if there are tool calls recorded in the step details
118+ step_details = step .get ("step_details" , {})
119+ tool_calls = step_details .get ("tool_calls" , [])
120+
121+ if tool_calls :
122+ print (" Tool calls:" )
123+ for call in tool_calls :
124+ print (f" Tool Call ID: { call .get ('id' )} " )
125+ print (f" Type: { call .get ('type' )} " )
126+
127+ function_details = call .get ("function" , {})
128+ if function_details :
129+ print (f" Function name: { function_details .get ('name' )} " )
130+ print () # Add an extra newline between steps for readability
131+ # </tool_execution_loop>
132+
133+ # <cleanup>
134+ # --- Cleanup ---
135+ # Delete the agent resource to clean up
136+ agents_client .delete_agent (agent .id )
137+ print ("Deleted agent" )
138+
139+ # Fetch and log all messages exchanged during the conversation thread
140+ messages = agents_client .list_messages (thread_id = thread .id )
141+ print (f"Messages: { messages } " )
142+ # </cleanup>
0 commit comments