From c87d80e8fef5345f000c5d667766b82080ddcc1f Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Fri, 6 Mar 2026 10:41:34 +0100 Subject: [PATCH 01/22] Created OpenAPISample --- .../models/OpenApiFunctionDefinition.java | 17 +++ .../azure/ai/agents/tools/OpenApiSample.java | 108 ++++++++++++++++++ .../resources/assets/httpbin_openapi.json | 39 +++++++ 3 files changed, 164 insertions(+) create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java create mode 100644 sdk/ai/azure-ai-agents/src/samples/resources/assets/httpbin_openapi.json diff --git a/sdk/ai/azure-ai-agents/src/main/java/com/azure/ai/agents/models/OpenApiFunctionDefinition.java b/sdk/ai/azure-ai-agents/src/main/java/com/azure/ai/agents/models/OpenApiFunctionDefinition.java index 2eedcbc561cf..b102fd0768b0 100644 --- a/sdk/ai/azure-ai-agents/src/main/java/com/azure/ai/agents/models/OpenApiFunctionDefinition.java +++ b/sdk/ai/azure-ai-agents/src/main/java/com/azure/ai/agents/models/OpenApiFunctionDefinition.java @@ -6,11 +6,13 @@ import com.azure.core.annotation.Fluent; import com.azure.core.annotation.Generated; import com.azure.core.util.BinaryData; +import com.azure.json.JsonProviders; import com.azure.json.JsonReader; import com.azure.json.JsonSerializable; import com.azure.json.JsonToken; import com.azure.json.JsonWriter; import java.io.IOException; +import java.nio.file.Path; import java.util.List; import java.util.Map; @@ -197,6 +199,21 @@ public OpenApiFunctionDefinition(String name, Map spec, Open this.auth = auth; } + /** + * Reads an OpenAPI specification from a JSON file and returns it as a {@code Map} + * suitable for the {@code spec} parameter of + * {@link #OpenApiFunctionDefinition(String, Map, OpenApiAuthDetails)}. + * + * @param path the path to the OpenAPI spec JSON file. + * @return the spec as a map of top-level keys to their serialized values. + * @throws IOException if the file cannot be read or parsed. + */ + public static Map readSpecFromFile(Path path) throws IOException { + BinaryData fileData = BinaryData.fromFile(path); + JsonReader reader = JsonProviders.createReader(fileData.toBytes()); + return reader.readMap(r -> r.getNullable(nonNullReader -> BinaryData.fromObject(nonNullReader.readUntyped()))); + } + /* * List of OpenAPI spec parameters that will use user-provided defaults */ diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java new file mode 100644 index 000000000000..b02b7f4e5222 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ConversationsClient; +import com.azure.ai.agents.ResponsesClient; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.OpenApiAnonymousAuthDetails; +import com.azure.ai.agents.models.OpenApiFunctionDefinition; +import com.azure.ai.agents.models.OpenApiTool; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.BinaryData; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.conversations.Conversation; +import com.openai.models.conversations.items.ItemCreateParams; +import com.openai.models.responses.EasyInputMessage; +import com.openai.models.responses.Response; +import com.openai.models.responses.ResponseCreateParams; + +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Map; + +/** + * This sample demonstrates how to create an agent with an OpenAPI tool that calls + * an external API defined by an OpenAPI specification file. + * + *

Before running the sample, set these environment variables:

+ *
    + *
  • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
  • + *
  • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
  • + *
+ * + *

Also place an OpenAPI spec JSON file at {@code src/samples/resources/assets/httpbin_openapi.json}.

+ */ +public class OpenApiSample { + public static void main(String[] args) throws Exception { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsClient agentsClient = builder.buildAgentsClient(); + ResponsesClient responsesClient = builder.buildResponsesClient(); + ConversationsClient conversationsClient = builder.buildConversationsClient(); + + // Load the OpenAPI spec from a JSON file + Map spec = OpenApiFunctionDefinition.readSpecFromFile( + Paths.get("src/samples/resources/assets/httpbin_openapi.json")); + + OpenApiFunctionDefinition toolDefinition = new OpenApiFunctionDefinition( + "httpbin_get", + spec, + new OpenApiAnonymousAuthDetails()) + .setDescription("Get request metadata from an OpenAPI endpoint."); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("Use the OpenAPI tool for HTTP request metadata.") + .setTools(Arrays.asList(new OpenApiTool(toolDefinition))); + + AgentVersionDetails agentVersion = agentsClient.createAgentVersion("openapi-agent", agentDefinition); + System.out.println("Agent: " + agentVersion.getName() + ", version: " + agentVersion.getVersion()); + + // Create a conversation and add a user message + Conversation conversation = conversationsClient.getConversationService().create(); + conversationsClient.getConversationService().items().create( + ItemCreateParams.builder() + .conversationId(conversation.id()) + .addItem(EasyInputMessage.builder() + .role(EasyInputMessage.Role.USER) + .content("Use the OpenAPI tool and summarize the returned URL and origin in one sentence.") + .build()) + .build()); + + try { + AgentReference agentReference = new AgentReference(agentVersion.getName()) + .setVersion(agentVersion.getVersion()); + + ResponseCreateParams.Builder options = ResponseCreateParams.builder() + .maxOutputTokens(300L); + + Response response = responsesClient.createWithAgentConversation( + agentReference, conversation.id(), options); + + String text = response.output().stream() + .filter(item -> item.isMessage()) + .map(item -> item.asMessage().content() + .get(item.asMessage().content().size() - 1) + .asOutputText() + .text()) + .reduce((first, second) -> second) + .orElse(""); + + System.out.println("Status: " + response.status().map(Object::toString).orElse("unknown")); + System.out.println("Response: " + text); + } finally { + agentsClient.deleteAgentVersion(agentVersion.getName(), agentVersion.getVersion()); + System.out.println("Agent deleted"); + } + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/resources/assets/httpbin_openapi.json b/sdk/ai/azure-ai-agents/src/samples/resources/assets/httpbin_openapi.json new file mode 100644 index 000000000000..92b037313537 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/resources/assets/httpbin_openapi.json @@ -0,0 +1,39 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "httpbin", + "version": "1.0.0", + "description": "A simple HTTP request/response service" + }, + "servers": [ + { + "url": "https://httpbin.org" + } + ], + "paths": { + "/get": { + "get": { + "operationId": "httpbin_get", + "summary": "Returns the GET request data including headers, origin IP, and URL", + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "args": { "type": "object" }, + "headers": { "type": "object" }, + "origin": { "type": "string" }, + "url": { "type": "string" } + } + } + } + } + } + } + } + } + } +} From b87b1684057b3a5015304e749bf1eca7fdbbbd76 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Fri, 6 Mar 2026 11:27:15 +0100 Subject: [PATCH 02/22] File utils for sample --- .../java/com/azure/ai/agents/SampleUtils.java | 29 +++++++++++++++++++ .../azure/ai/agents/tools/OpenApiSample.java | 9 ++---- 2 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/SampleUtils.java diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/SampleUtils.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/SampleUtils.java new file mode 100644 index 000000000000..bdfa7bad1229 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/SampleUtils.java @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents; + +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class SampleUtils { + + /** + * Gets the path to a file in the sample resource folder. + * @param fileName the name of the file in the sample resource folder + * @return Path to the sample resource file + */ + public static Path getResourcePath(String fileName) { + try { + URL resourceUrl = SampleUtils.class.getClassLoader().getResource(fileName); + if (resourceUrl == null) { + throw new RuntimeException("Sample resource file not found: " + fileName); + } + return Paths.get(resourceUrl.toURI()); + } catch (URISyntaxException e) { + throw new RuntimeException("Invalid URI for sample resource: " + fileName, e); + } + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java index b02b7f4e5222..e9be0702f87e 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java @@ -3,10 +3,7 @@ package com.azure.ai.agents.tools; -import com.azure.ai.agents.AgentsClient; -import com.azure.ai.agents.AgentsClientBuilder; -import com.azure.ai.agents.ConversationsClient; -import com.azure.ai.agents.ResponsesClient; +import com.azure.ai.agents.*; import com.azure.ai.agents.models.AgentReference; import com.azure.ai.agents.models.AgentVersionDetails; import com.azure.ai.agents.models.OpenApiAnonymousAuthDetails; @@ -22,7 +19,6 @@ import com.openai.models.responses.Response; import com.openai.models.responses.ResponseCreateParams; -import java.nio.file.Paths; import java.util.Arrays; import java.util.Map; @@ -51,9 +47,10 @@ public static void main(String[] args) throws Exception { ResponsesClient responsesClient = builder.buildResponsesClient(); ConversationsClient conversationsClient = builder.buildConversationsClient(); + // Load the OpenAPI spec from a JSON file Map spec = OpenApiFunctionDefinition.readSpecFromFile( - Paths.get("src/samples/resources/assets/httpbin_openapi.json")); + SampleUtils.getResourcePath("assets/httpbin_openapi.json")); OpenApiFunctionDefinition toolDefinition = new OpenApiFunctionDefinition( "httpbin_get", From 99c93f861b1dfe0a771b712073420b31264f4cb7 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Fri, 6 Mar 2026 11:33:16 +0100 Subject: [PATCH 03/22] PR copilot feedback --- .../azure/ai/agents/models/OpenApiFunctionDefinition.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sdk/ai/azure-ai-agents/src/main/java/com/azure/ai/agents/models/OpenApiFunctionDefinition.java b/sdk/ai/azure-ai-agents/src/main/java/com/azure/ai/agents/models/OpenApiFunctionDefinition.java index b102fd0768b0..085e214d84b1 100644 --- a/sdk/ai/azure-ai-agents/src/main/java/com/azure/ai/agents/models/OpenApiFunctionDefinition.java +++ b/sdk/ai/azure-ai-agents/src/main/java/com/azure/ai/agents/models/OpenApiFunctionDefinition.java @@ -12,6 +12,7 @@ import com.azure.json.JsonToken; import com.azure.json.JsonWriter; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.Map; @@ -209,9 +210,10 @@ public OpenApiFunctionDefinition(String name, Map spec, Open * @throws IOException if the file cannot be read or parsed. */ public static Map readSpecFromFile(Path path) throws IOException { - BinaryData fileData = BinaryData.fromFile(path); - JsonReader reader = JsonProviders.createReader(fileData.toBytes()); - return reader.readMap(r -> r.getNullable(nonNullReader -> BinaryData.fromObject(nonNullReader.readUntyped()))); + try (JsonReader reader = JsonProviders.createReader(Files.readAllBytes(path))) { + return reader + .readMap(r -> r.getNullable(nonNullReader -> BinaryData.fromObject(nonNullReader.readUntyped()))); + } } /* From b8fb5b5a0809f64870f6eefde3a159955136209a Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Fri, 6 Mar 2026 11:49:08 +0100 Subject: [PATCH 04/22] Added OpenAPITool as unit test --- sdk/ai/azure-ai-agents/assets.json | 2 +- .../azure/ai/agents/tools/OpenApiSample.java | 8 +- .../com/azure/ai/agents/OpenAPIToolTests.java | 93 +++++++++++++++++++ .../resources/assets/httpbin_openapi.json | 39 ++++++++ 4 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/OpenAPIToolTests.java create mode 100644 sdk/ai/azure-ai-agents/src/test/resources/assets/httpbin_openapi.json diff --git a/sdk/ai/azure-ai-agents/assets.json b/sdk/ai/azure-ai-agents/assets.json index 08d8cb4c7c20..42ea9478529a 100644 --- a/sdk/ai/azure-ai-agents/assets.json +++ b/sdk/ai/azure-ai-agents/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "java", "TagPrefix": "java/ai/azure-ai-agents", - "Tag": "java/ai/azure-ai-agents_34d0d1c5d4" + "Tag": "java/ai/azure-ai-agents_69bc682982" } \ No newline at end of file diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java index e9be0702f87e..1823d374c882 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java @@ -3,7 +3,11 @@ package com.azure.ai.agents.tools; -import com.azure.ai.agents.*; +import com.azure.ai.agents.AgentsClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ConversationsClient; +import com.azure.ai.agents.ResponsesClient; +import com.azure.ai.agents.SampleUtils; import com.azure.ai.agents.models.AgentReference; import com.azure.ai.agents.models.AgentVersionDetails; import com.azure.ai.agents.models.OpenApiAnonymousAuthDetails; @@ -50,7 +54,7 @@ public static void main(String[] args) throws Exception { // Load the OpenAPI spec from a JSON file Map spec = OpenApiFunctionDefinition.readSpecFromFile( - SampleUtils.getResourcePath("assets/httpbin_openapi.json")); + SampleUtils.getResourcePath("assets/httpbin_openapi.json")); OpenApiFunctionDefinition toolDefinition = new OpenApiFunctionDefinition( "httpbin_get", diff --git a/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/OpenAPIToolTests.java b/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/OpenAPIToolTests.java new file mode 100644 index 000000000000..c1d814a798b8 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/OpenAPIToolTests.java @@ -0,0 +1,93 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents; + +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.OpenApiAnonymousAuthDetails; +import com.azure.ai.agents.models.OpenApiFunctionDefinition; +import com.azure.ai.agents.models.OpenApiTool; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.http.HttpClient; +import com.azure.core.util.BinaryData; +import com.openai.models.conversations.Conversation; +import com.openai.models.conversations.items.ItemCreateParams; +import com.openai.models.responses.EasyInputMessage; +import com.openai.models.responses.Response; +import com.openai.models.responses.ResponseCreateParams; +import com.openai.models.responses.ResponseStatus; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Map; + +import static com.azure.ai.agents.TestUtils.DISPLAY_NAME_WITH_ARGUMENTS; +import static org.junit.jupiter.api.Assertions.*; + +public class OpenAPIToolTests extends ClientTestBase { + + private static final String AGENT_NAME = "openapi-tool-test-agent-java"; + + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.agents.TestUtils#getTestParameters") + public void openApiToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serviceVersion) throws IOException { + AgentsClient agentsClient = getAgentsSyncClient(httpClient, serviceVersion); + ResponsesClient responsesClient = getResponsesSyncClient(httpClient, serviceVersion); + ConversationsClient conversationsClient = getConversationsSyncClient(httpClient, serviceVersion); + + // Load the OpenAPI spec from test resources + Map spec + = OpenApiFunctionDefinition.readSpecFromFile(TestUtils.getTestResourcePath("assets/httpbin_openapi.json")); + + OpenApiFunctionDefinition toolDefinition + = new OpenApiFunctionDefinition("httpbin_get", spec, new OpenApiAnonymousAuthDetails()) + .setDescription("Get request metadata from an OpenAPI endpoint."); + + PromptAgentDefinition agentDefinition + = new PromptAgentDefinition("gpt-4o").setInstructions("Use the OpenAPI tool for HTTP request metadata.") + .setTools(Arrays.asList(new OpenApiTool(toolDefinition))); + + AgentVersionDetails agentVersion = agentsClient.createAgentVersion(AGENT_NAME, agentDefinition); + assertNotNull(agentVersion); + assertNotNull(agentVersion.getId()); + assertEquals(AGENT_NAME, agentVersion.getName()); + + try { + // Create a conversation and add a user message + Conversation conversation = conversationsClient.getConversationService().create(); + assertNotNull(conversation); + assertNotNull(conversation.id()); + + conversationsClient.getConversationService() + .items() + .create(ItemCreateParams.builder() + .conversationId(conversation.id()) + .addItem(EasyInputMessage.builder() + .role(EasyInputMessage.Role.USER) + .content("Use the OpenAPI tool and summarize the returned URL and origin in one sentence.") + .build()) + .build()); + + // Create a response using the agent with the conversation + AgentReference agentReference + = new AgentReference(agentVersion.getName()).setVersion(agentVersion.getVersion()); + + ResponseCreateParams.Builder options = ResponseCreateParams.builder().maxOutputTokens(300L); + + Response response = responsesClient.createWithAgentConversation(agentReference, conversation.id(), options); + + assertNotNull(response); + assertTrue(response.id().startsWith("resp")); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); + } finally { + // Clean up + agentsClient.deleteAgentVersion(agentVersion.getName(), agentVersion.getVersion()); + } + } +} diff --git a/sdk/ai/azure-ai-agents/src/test/resources/assets/httpbin_openapi.json b/sdk/ai/azure-ai-agents/src/test/resources/assets/httpbin_openapi.json new file mode 100644 index 000000000000..92b037313537 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/test/resources/assets/httpbin_openapi.json @@ -0,0 +1,39 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "httpbin", + "version": "1.0.0", + "description": "A simple HTTP request/response service" + }, + "servers": [ + { + "url": "https://httpbin.org" + } + ], + "paths": { + "/get": { + "get": { + "operationId": "httpbin_get", + "summary": "Returns the GET request data including headers, origin IP, and URL", + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "args": { "type": "object" }, + "headers": { "type": "object" }, + "origin": { "type": "string" }, + "url": { "type": "string" } + } + } + } + } + } + } + } + } + } +} From 981d95c4fb81916e50466340edf885fa6366b5c5 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Fri, 6 Mar 2026 13:38:29 +0100 Subject: [PATCH 05/22] README and CHANGELOG updates for azure-ai-agents samples - CHANGELOG: Added entries for readSpecFromFile, OpenApiSample, and OpenAPIToolTests - README: Added full tool catalog (15 tools) aligned with Python SDK README structure - All sample links use absolute GitHub URLs for CI link verification - Added MISSING_SAMPLES.md tracking Java vs Python sample parity gaps --- sdk/ai/azure-ai-agents/CHANGELOG.md | 5 + sdk/ai/azure-ai-agents/MISSING_SAMPLES.md | 17 ++ sdk/ai/azure-ai-agents/README.md | 220 ++++++++++++++++++++++ 3 files changed, 242 insertions(+) create mode 100644 sdk/ai/azure-ai-agents/MISSING_SAMPLES.md diff --git a/sdk/ai/azure-ai-agents/CHANGELOG.md b/sdk/ai/azure-ai-agents/CHANGELOG.md index 2232d8e3cd02..7c5f02a40396 100644 --- a/sdk/ai/azure-ai-agents/CHANGELOG.md +++ b/sdk/ai/azure-ai-agents/CHANGELOG.md @@ -4,12 +4,17 @@ ### Features Added +- Added `readSpecFromFile(Path)` static convenience method to `OpenApiFunctionDefinition` for loading OpenAPI specification JSON files as the `Map` required by the constructor, eliminating the need for manual `JsonReader`/`BinaryData` wiring. +- Added new `OpenApiSample` demonstrating end-to-end OpenAPI tool integration: loading a spec file, creating an agent with an `OpenApiTool`, and invoking an external API via conversation. + ### Breaking Changes ### Bugs Fixed ### Other Changes +- Added `OpenAPIToolTests` with recorded end-to-end test coverage for the OpenAPI tool flow. + ## 2.0.0-beta.2 (2026-03-04) ### Features Added diff --git a/sdk/ai/azure-ai-agents/MISSING_SAMPLES.md b/sdk/ai/azure-ai-agents/MISSING_SAMPLES.md new file mode 100644 index 000000000000..87d9e2fd28cc --- /dev/null +++ b/sdk/ai/azure-ai-agents/MISSING_SAMPLES.md @@ -0,0 +1,17 @@ +# Missing Samples — Java vs Python Parity + +Tool samples present in the [Python `azure-ai-projects` README](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/ai/azure-ai-projects) but **missing** from the Java `azure-ai-agents` samples. + +| Tool | Python Sample | Java Status | Notes | +|---|---|---|---| +| **Azure Functions** | `sample_agent_azure_function.py` | ❌ Missing | Requires `AzureFunctionTool` + connection setup | +| **Memory Search (Preview)** | `sample_agent_memory_search.py` | ⚠️ Partial | `MemorySearchAgent.java` exists in root samples but not in `tools/` | +| **Bing Custom Search (Preview)** | `sample_agent_bing_custom_search.py` | ❌ Missing | Requires `BingCustomSearchPreviewTool` | +| **MCP with Project Connection** | `sample_agent_mcp_with_project_connection.py` | ❌ Missing | Connection-authenticated MCP variant | +| **OpenAPI with Project Connection** | `sample_agent_openapi_with_project_connection.py` | ❌ Missing | Uses `OpenApiProjectConnectionAuthDetails` instead of anonymous auth | + +## Java extras not in Python README + +| Tool | Java Sample | Notes | +|---|---|---| +| **Custom Code Interpreter** | `CustomCodeInterpreterSample.java` | Container-based code interpreter variant | diff --git a/sdk/ai/azure-ai-agents/README.md b/sdk/ai/azure-ai-agents/README.md index 8bdaa4b533d7..0833fcc7cf0f 100644 --- a/sdk/ai/azure-ai-agents/README.md +++ b/sdk/ai/azure-ai-agents/README.md @@ -210,6 +210,226 @@ AgentReference agentReference = new AgentReference(agent.getName()).setVersion(a Response response = responsesClient.createWithAgentConversation(agentReference, conversation.id()); ``` +### Using Agent tools + +Agents can be enhanced with specialized tools for various capabilities. For complete working examples, see the `tools/` folder under [samples](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools). + +In the description below, tools are organized by their Foundry connection requirements: "Built-in Tools" (which do not require a Foundry connection) and "Connection-based Tools" (which require a Foundry connection). + +#### Built-in Tools + +These tools work immediately without requiring external connections. + +--- + +##### **Code Interpreter** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/code-interpreter?pivots=java)) + +Write and run Python code in a sandboxed environment, process files and work with diverse data formats. + +```java +CodeInterpreterTool tool = new CodeInterpreterTool(); +``` + +See the full sample in [CodeInterpreterSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterSample.java). + +--- + +##### **File Search** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/file-search?pivots=java)) + +Search through files in a vector store for knowledge retrieval: + +```java +FileSearchTool tool = new FileSearchTool(Arrays.asList(vectorStoreId)); +``` + +See the full sample in [FileSearchSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchSample.java). + +--- + +##### **Image Generation** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/image-generation?pivots=java)) + +Generate images from text descriptions: + +```java +ImageGenTool tool = new ImageGenTool() + .setModel(ImageGenToolModel.fromString(imageModel)) + .setQuality(ImageGenToolQuality.LOW) + .setSize(ImageGenToolSize.fromString("1024x1024")); +``` + +See the full sample in [ImageGenerationSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ImageGenerationSample.java). + +--- + +##### **Web Search (Preview)** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/web-search?pivots=java)) + +Search the web for current information: + +```java +WebSearchPreviewTool tool = new WebSearchPreviewTool(); +``` + +See the full sample in [WebSearchSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchSample.java). + +--- + +##### **Computer Use (Preview)** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/computer-use?pivots=java)) + +Interact with computer interfaces through simulated actions and screenshots: + +```java +ComputerUsePreviewTool tool = new ComputerUsePreviewTool( + ComputerEnvironment.WINDOWS, 1026, 769); +``` + +See the full sample in [ComputerUseSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ComputerUseSync.java). + +--- + +##### **Model Context Protocol (MCP)** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/model-context-protocol?pivots=java)) + +Connect agents to external MCP servers: + +```java +McpTool tool = new McpTool("api-specs") + .setServerUrl("https://gitmcp.io/Azure/azure-rest-api-specs") + .setProjectConnectionId(mcpConnectionId) + .setRequireApproval(BinaryData.fromObject("always")); +``` + +See the full sample in [McpToolSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpToolSample.java). + +--- + +##### **OpenAPI** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/openapi?pivots=java)) + +Call external APIs defined by OpenAPI specifications without additional client-side code: + +```java +Map spec = OpenApiFunctionDefinition.readSpecFromFile( + Paths.get("path/to/openapi_spec.json")); + +OpenApiTool tool = new OpenApiTool( + new OpenApiFunctionDefinition("get_weather", spec, new OpenApiAnonymousAuthDetails()) + .setDescription("Retrieve weather information for a location.")); +``` + +See the full sample in [OpenApiSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java). + +--- + +##### **Function Tool** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/function-calling?pivots=java)) + +Define custom functions that allow agents to interact with external APIs, databases, or application logic: + +```java +Map parameters = new HashMap<>(); +parameters.put("type", BinaryData.fromString("\"object\"")); +parameters.put("properties", BinaryData.fromString( + "{\"location\":{\"type\":\"string\",\"description\":\"The city and state\"}}")); +parameters.put("required", BinaryData.fromString("[\"location\"]")); + +FunctionTool tool = new FunctionTool("get_weather", parameters, true); +``` + +See the full sample in [FunctionCallingSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallingSample.java). + +--- + +#### Connection-Based Tools + +These tools require configuring connections in your Microsoft Foundry project and use a `projectConnectionId`. + +--- + +##### **Azure AI Search** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/ai-search?pivots=java)) + +Integrate with Azure AI Search indexes for powerful knowledge retrieval and semantic search capabilities: + +```java +AzureAISearchTool tool = new AzureAISearchTool( + new AzureAISearchToolResource(Arrays.asList( + new AISearchIndexResource() + .setProjectConnectionId(connectionId) + .setIndexName(indexName) + .setQueryType(AzureAISearchQueryType.SIMPLE)))); +``` + +See the full sample in [AzureAISearchSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchSample.java). + +--- + +##### **Bing Grounding** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/bing-tools?pivots=java)) + +Ground agent responses with real-time web search results from Bing to provide up-to-date information: + +```java +BingGroundingTool tool = new BingGroundingTool( + new BingGroundingSearchToolParameters(Arrays.asList( + new BingGroundingSearchConfiguration(bingConnectionId)))); +``` + +See the full sample in [BingGroundingSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingSample.java). + +--- + +##### **Microsoft Fabric (Preview)** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/fabric?pivots=java)) + +Query data from Microsoft Fabric data sources: + +```java +MicrosoftFabricPreviewTool tool = new MicrosoftFabricPreviewTool( + new FabricDataAgentToolParameters() + .setProjectConnections(Arrays.asList( + new ToolProjectConnection(fabricConnectionId)))); +``` + +See the full sample in [FabricSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricSample.java). + +--- + +##### **Microsoft SharePoint (Preview)** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/sharepoint?pivots=java)) + +Search through SharePoint documents for grounding: + +```java +SharepointPreviewTool tool = new SharepointPreviewTool( + new SharepointGroundingToolParameters() + .setProjectConnections(Arrays.asList( + new ToolProjectConnection(sharepointConnectionId)))); +``` + +See the full sample in [SharePointGroundingSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingSample.java). + +--- + +##### **Browser Automation (Preview)** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/browser-automation?pivots=java)) + +Interact with web pages through browser automation: + +```java +BrowserAutomationPreviewTool tool = new BrowserAutomationPreviewTool( + new BrowserAutomationToolParameters( + new BrowserAutomationToolConnectionParameters(connectionId))); +``` + +See the full sample in [BrowserAutomationSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationSample.java). + +--- + +##### **Agent-to-Agent (A2A) (Preview)** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/agent-to-agent?pivots=java)) + +Enable agent-to-agent communication with remote A2A endpoints: + +```java +A2APreviewTool tool = new A2APreviewTool() + .setProjectConnectionId(a2aConnectionId); +``` + +See the full sample in [AgentToAgentSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AgentToAgentSample.java). + +--- + ### Service API versions The client library targets the latest service API version by default. From 32029965599c04a4351ba6c31884daebebee9a7e Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Fri, 6 Mar 2026 14:11:57 +0100 Subject: [PATCH 06/22] Re-worked samples --- sdk/ai/azure-ai-agents/CHANGELOG.md | 1 + sdk/ai/azure-ai-agents/MISSING_SAMPLES.md | 17 -- sdk/ai/azure-ai-agents/README.md | 2 +- sdk/ai/azure-ai-agents/UPDATE_README_LINKS.md | 133 +++++++++++++++ .../ai/agents/tools/AzureFunctionSample.java | 98 +++++++++++ .../agents/tools/BingCustomSearchSample.java | 85 ++++++++++ .../agents/tools/McpWithConnectionSample.java | 118 +++++++++++++ .../ai/agents/tools/MemorySearchSample.java | 158 ++++++++++++++++++ .../tools/OpenApiWithConnectionSample.java | 92 ++++++++++ 9 files changed, 686 insertions(+), 18 deletions(-) delete mode 100644 sdk/ai/azure-ai-agents/MISSING_SAMPLES.md create mode 100644 sdk/ai/azure-ai-agents/UPDATE_README_LINKS.md create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSample.java create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSample.java create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSample.java create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSample.java create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSample.java diff --git a/sdk/ai/azure-ai-agents/CHANGELOG.md b/sdk/ai/azure-ai-agents/CHANGELOG.md index 7c5f02a40396..69e6ac4c93d0 100644 --- a/sdk/ai/azure-ai-agents/CHANGELOG.md +++ b/sdk/ai/azure-ai-agents/CHANGELOG.md @@ -6,6 +6,7 @@ - Added `readSpecFromFile(Path)` static convenience method to `OpenApiFunctionDefinition` for loading OpenAPI specification JSON files as the `Map` required by the constructor, eliminating the need for manual `JsonReader`/`BinaryData` wiring. - Added new `OpenApiSample` demonstrating end-to-end OpenAPI tool integration: loading a spec file, creating an agent with an `OpenApiTool`, and invoking an external API via conversation. +- Added new tool samples for parity with the Python SDK: `AzureFunctionSample`, `BingCustomSearchSample`, `MemorySearchSample`, `McpWithConnectionSample`, and `OpenApiWithConnectionSample`. ### Breaking Changes diff --git a/sdk/ai/azure-ai-agents/MISSING_SAMPLES.md b/sdk/ai/azure-ai-agents/MISSING_SAMPLES.md deleted file mode 100644 index 87d9e2fd28cc..000000000000 --- a/sdk/ai/azure-ai-agents/MISSING_SAMPLES.md +++ /dev/null @@ -1,17 +0,0 @@ -# Missing Samples — Java vs Python Parity - -Tool samples present in the [Python `azure-ai-projects` README](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/ai/azure-ai-projects) but **missing** from the Java `azure-ai-agents` samples. - -| Tool | Python Sample | Java Status | Notes | -|---|---|---|---| -| **Azure Functions** | `sample_agent_azure_function.py` | ❌ Missing | Requires `AzureFunctionTool` + connection setup | -| **Memory Search (Preview)** | `sample_agent_memory_search.py` | ⚠️ Partial | `MemorySearchAgent.java` exists in root samples but not in `tools/` | -| **Bing Custom Search (Preview)** | `sample_agent_bing_custom_search.py` | ❌ Missing | Requires `BingCustomSearchPreviewTool` | -| **MCP with Project Connection** | `sample_agent_mcp_with_project_connection.py` | ❌ Missing | Connection-authenticated MCP variant | -| **OpenAPI with Project Connection** | `sample_agent_openapi_with_project_connection.py` | ❌ Missing | Uses `OpenApiProjectConnectionAuthDetails` instead of anonymous auth | - -## Java extras not in Python README - -| Tool | Java Sample | Notes | -|---|---|---| -| **Custom Code Interpreter** | `CustomCodeInterpreterSample.java` | Container-based code interpreter variant | diff --git a/sdk/ai/azure-ai-agents/README.md b/sdk/ai/azure-ai-agents/README.md index 0833fcc7cf0f..65df613160f7 100644 --- a/sdk/ai/azure-ai-agents/README.md +++ b/sdk/ai/azure-ai-agents/README.md @@ -314,7 +314,7 @@ OpenApiTool tool = new OpenApiTool( .setDescription("Retrieve weather information for a location.")); ``` -See the full sample in [OpenApiSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java). + --- diff --git a/sdk/ai/azure-ai-agents/UPDATE_README_LINKS.md b/sdk/ai/azure-ai-agents/UPDATE_README_LINKS.md new file mode 100644 index 000000000000..5fe03fa4ce05 --- /dev/null +++ b/sdk/ai/azure-ai-agents/UPDATE_README_LINKS.md @@ -0,0 +1,133 @@ +# README Link Updates — Pending Sample Merge + +These README tool sections need sample links added **after** the corresponding `.java` files are checked into `main`. + +CI rejects `https://github.com/Azure/azure-sdk-for-java/tree/main/...` URLs that point to files not yet on `main`, so these links must be added in a follow-up commit. + +## Samples not yet on `main` + +| Sample File | PR | README Section | +|---|---|---| +| `OpenApiSample.java` | [#48315](https://github.com/Azure/azure-sdk-for-java/pull/48315) | **OpenAPI** (Built-in) | +| `AzureFunctionSample.java` | _not yet opened_ | **Azure Functions** (new Built-in section) | +| `MemorySearchSample.java` | _not yet opened_ | **Memory Search (Preview)** (new Built-in section) | +| `BingCustomSearchSample.java` | _not yet opened_ | **Bing Custom Search (Preview)** (new Connection-Based section) | +| `McpWithConnectionSample.java` | _not yet opened_ | **MCP with Project Connection** (new Connection-Based section) | +| `OpenApiWithConnectionSample.java` | _not yet opened_ | **OpenAPI with Project Connection** (new Connection-Based section) | + +## What to add after merge + +### 1. OpenAPI (existing section — restore link) + +After the `OpenApiTool` code snippet, replace the HTML comment with: + +```markdown +See the full sample in [OpenApiSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java). +``` + +### 2. Azure Functions (new Built-in section) + +Insert before `#### Connection-Based Tools`: + +```markdown +--- + +##### **Azure Functions** + +Call Azure Functions via Storage Queue input/output bindings: + +\```java +AzureFunctionTool tool = new AzureFunctionTool( + new AzureFunctionDefinition( + new AzureFunctionDefinitionDetails("queue_trigger", parameters) + .setDescription("Get weather for a given location"), + new AzureFunctionBinding( + new AzureFunctionStorageQueue(queueServiceEndpoint, inputQueueName)), + new AzureFunctionBinding( + new AzureFunctionStorageQueue(queueServiceEndpoint, outputQueueName)))); +\``` + +See the full sample in [AzureFunctionSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSample.java). +``` + +### 3. Memory Search (Preview) (new Built-in section) + +Insert before `#### Connection-Based Tools`: + +```markdown +--- + +##### **Memory Search (Preview)** ([documentation](https://learn.microsoft.com/azure/foundry/agents/concepts/what-is-memory)) + +Retrieve relevant past user messages using memory stores: + +\```java +MemorySearchPreviewTool tool = new MemorySearchPreviewTool(memoryStoreName, scope) + .setUpdateDelaySeconds(1); +\``` + +See the full sample in [MemorySearchSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSample.java). +``` + +### 4. Bing Custom Search (Preview) (new Connection-Based section) + +Insert after the **Bing Grounding** section: + +```markdown +--- + +##### **Bing Custom Search (Preview)** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/bing-tools?pivots=java#grounding-with-bing-custom-search-preview)) + +Search custom Bing search instances for targeted results: + +\```java +BingCustomSearchPreviewTool tool = new BingCustomSearchPreviewTool( + new BingCustomSearchToolParameters(Arrays.asList( + new BingCustomSearchConfiguration(connectionId, instanceName)))); +\``` + +See the full sample in [BingCustomSearchSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSample.java). +``` + +### 5. MCP with Project Connection (new Connection-Based section) + +Insert after the **Agent-to-Agent (A2A) (Preview)** section: + +```markdown +--- + +##### **MCP with Project Connection** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/model-context-protocol?pivots=java)) + +Connect to MCP servers using project connection authentication, with approval handling: + +\```java +McpTool tool = new McpTool("api-specs") + .setServerUrl("https://api.githubcopilot.com/mcp") + .setProjectConnectionId(mcpConnectionId) + .setRequireApproval(BinaryData.fromObject("always")); +\``` + +See the full sample in [McpWithConnectionSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSample.java). +``` + +### 6. OpenAPI with Project Connection (new Connection-Based section) + +Insert after the **MCP with Project Connection** section: + +```markdown +--- + +##### **OpenAPI with Project Connection** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/openapi?pivots=java)) + +Call external APIs defined by OpenAPI specifications using project connection authentication: + +\```java +OpenApiTool tool = new OpenApiTool( + new OpenApiFunctionDefinition("my_api", spec, + new OpenApiProjectConnectionAuthDetails( + new OpenApiProjectConnectionSecurityScheme(connectionId))) + .setDescription("Call an authenticated API endpoint.")); +\``` + +See the full sample in [OpenApiWithConnectionSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSample.java). +``` diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSample.java new file mode 100644 index 000000000000..100d8e470266 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSample.java @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ResponsesClient; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.AzureFunctionBinding; +import com.azure.ai.agents.models.AzureFunctionDefinition; +import com.azure.ai.agents.models.AzureFunctionDefinitionDetails; +import com.azure.ai.agents.models.AzureFunctionStorageQueue; +import com.azure.ai.agents.models.AzureFunctionTool; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.BinaryData; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.Response; +import com.openai.models.responses.ResponseCreateParams; +import com.openai.models.responses.ToolChoiceOptions; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * This sample demonstrates how to create an agent with an Azure Function tool + * that calls an Azure Function via Storage Queue input/output bindings. + * + *

Before running the sample, set these environment variables:

+ *
    + *
  • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
  • + *
  • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
  • + *
  • STORAGE_INPUT_QUEUE_NAME - The Azure Storage Queue name for input.
  • + *
  • STORAGE_OUTPUT_QUEUE_NAME - The Azure Storage Queue name for output.
  • + *
  • STORAGE_QUEUE_SERVICE_ENDPOINT - The Azure Storage Queue service endpoint.
  • + *
+ */ +public class AzureFunctionSample { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String inputQueueName = Configuration.getGlobalConfiguration().get("STORAGE_INPUT_QUEUE_NAME"); + String outputQueueName = Configuration.getGlobalConfiguration().get("STORAGE_OUTPUT_QUEUE_NAME"); + String queueServiceEndpoint = Configuration.getGlobalConfiguration().get("STORAGE_QUEUE_SERVICE_ENDPOINT"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsClient agentsClient = builder.buildAgentsClient(); + ResponsesClient responsesClient = builder.buildResponsesClient(); + + // Define function parameters + Map parameters = new HashMap<>(); + parameters.put("type", BinaryData.fromString("\"object\"")); + parameters.put("properties", BinaryData.fromString( + "{\"location\":{\"type\":\"string\",\"description\":\"location to determine weather for\"}}")); + + // Create Azure Function tool with Storage Queue bindings + AzureFunctionTool azureFunctionTool = new AzureFunctionTool( + new AzureFunctionDefinition( + new AzureFunctionDefinitionDetails("queue_trigger", parameters) + .setDescription("Get weather for a given location"), + new AzureFunctionBinding( + new AzureFunctionStorageQueue(queueServiceEndpoint, inputQueueName)), + new AzureFunctionBinding( + new AzureFunctionStorageQueue(queueServiceEndpoint, outputQueueName)) + ) + ); + + // Create agent with Azure Function tool + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a helpful assistant.") + .setTools(Collections.singletonList(azureFunctionTool)); + + AgentVersionDetails agent = agentsClient.createAgentVersion("azure-function-agent", agentDefinition); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + try { + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + Response response = responsesClient.createWithAgent( + agentReference, + ResponseCreateParams.builder() + .toolChoice(ToolChoiceOptions.REQUIRED) + .input("What is the weather in Seattle?")); + + System.out.println("Response: " + response.output()); + } finally { + agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); + System.out.println("Agent deleted"); + } + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSample.java new file mode 100644 index 000000000000..61c21fc99e16 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSample.java @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ResponsesClient; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.BingCustomSearchConfiguration; +import com.azure.ai.agents.models.BingCustomSearchPreviewTool; +import com.azure.ai.agents.models.BingCustomSearchToolParameters; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.Response; +import com.openai.models.responses.ResponseCreateParams; + +import java.util.Arrays; +import java.util.Collections; + +/** + * This sample demonstrates how to create an agent with the Bing Custom Search tool + * to search custom search instances and provide responses with relevant results. + * + *

Warning: Grounding with Bing Custom Search tool uses Grounding with Bing, + * which has additional costs and terms. + * See Terms of use and + * Privacy statement.

+ * + *

Before running the sample, set these environment variables:

+ *
    + *
  • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
  • + *
  • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
  • + *
  • BING_CUSTOM_SEARCH_PROJECT_CONNECTION_ID - The Bing Custom Search project connection ID.
  • + *
  • BING_CUSTOM_SEARCH_INSTANCE_NAME - The Bing Custom Search instance name.
  • + *
+ */ +public class BingCustomSearchSample { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String connectionId = Configuration.getGlobalConfiguration().get("BING_CUSTOM_SEARCH_PROJECT_CONNECTION_ID"); + String instanceName = Configuration.getGlobalConfiguration().get("BING_CUSTOM_SEARCH_INSTANCE_NAME"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsClient agentsClient = builder.buildAgentsClient(); + ResponsesClient responsesClient = builder.buildResponsesClient(); + + // Create Bing Custom Search tool with connection and instance configuration + BingCustomSearchPreviewTool bingCustomSearchTool = new BingCustomSearchPreviewTool( + new BingCustomSearchToolParameters(Arrays.asList( + new BingCustomSearchConfiguration(connectionId, instanceName) + )) + ); + + // Create agent with Bing Custom Search tool + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a helpful agent that can use Bing Custom Search tools to assist users. " + + "Use the available Bing Custom Search tools to answer questions and perform tasks.") + .setTools(Collections.singletonList(bingCustomSearchTool)); + + AgentVersionDetails agent = agentsClient.createAgentVersion("bing-custom-search-agent", agentDefinition); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + try { + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + Response response = responsesClient.createWithAgent( + agentReference, + ResponseCreateParams.builder() + .input("Search for the latest Azure AI documentation")); + + System.out.println("Response: " + response.output()); + } finally { + agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); + System.out.println("Agent deleted"); + } + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSample.java new file mode 100644 index 000000000000..4b22e5547ac7 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSample.java @@ -0,0 +1,118 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ConversationsClient; +import com.azure.ai.agents.ResponsesClient; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.McpTool; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.BinaryData; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.conversations.Conversation; +import com.openai.models.responses.Response; +import com.openai.models.responses.ResponseCreateParams; +import com.openai.models.responses.ResponseInputItem; +import com.openai.models.responses.ResponseOutputItem; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * This sample demonstrates how to create an agent with a Model Context Protocol (MCP) tool + * using a project connection for authentication, and how to handle MCP approval requests. + * + *

The sample shows the full approval loop: the agent sends an MCP approval request, + * the client approves it, and the agent continues its work.

+ * + *

Before running the sample, set these environment variables:

+ *
    + *
  • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
  • + *
  • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
  • + *
  • MCP_PROJECT_CONNECTION_ID - The MCP project connection ID (Custom Keys connection + * with key "Authorization" and value "Bearer <your GitHub PAT token>").
  • + *
+ */ +public class McpWithConnectionSample { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String mcpConnectionId = Configuration.getGlobalConfiguration().get("MCP_PROJECT_CONNECTION_ID"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsClient agentsClient = builder.buildAgentsClient(); + ResponsesClient responsesClient = builder.buildResponsesClient(); + ConversationsClient conversationsClient = builder.buildConversationsClient(); + + // Create MCP tool with project connection authentication + McpTool mcpTool = new McpTool("api-specs") + .setServerUrl("https://api.githubcopilot.com/mcp") + .setProjectConnectionId(mcpConnectionId) + .setRequireApproval(BinaryData.fromObject("always")); + + // Create agent with MCP tool + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("Use MCP tools as needed") + .setTools(Collections.singletonList(mcpTool)); + + AgentVersionDetails agent = agentsClient.createAgentVersion("mcp-connection-agent", agentDefinition); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + try { + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + // Create a conversation for context + Conversation conversation = conversationsClient.getConversationService().create(); + + // Send initial request that triggers the MCP tool + Response response = responsesClient.createWithAgentConversation( + agentReference, conversation.id(), + ResponseCreateParams.builder() + .input("What is my username in Github profile?")); + + // Process MCP approval requests: approve each one so the agent can proceed + List approvals = new ArrayList<>(); + for (ResponseOutputItem item : response.output()) { + if (item.isMcpApprovalRequest()) { + ResponseOutputItem.McpApprovalRequest request = item.asMcpApprovalRequest(); + System.out.printf("MCP approval requested: server=%s, id=%s%n", + request.serverLabel(), request.id()); + + approvals.add(ResponseInputItem.ofMcpApprovalResponse( + ResponseInputItem.McpApprovalResponse.builder() + .approvalRequestId(request.id()) + .approve(true) + .build())); + } + } + + if (!approvals.isEmpty()) { + System.out.println("Sending " + approvals.size() + " approval(s)..."); + + // Send approvals back to continue the agent's work + Response followUp = responsesClient.createWithAgentConversation( + agentReference, conversation.id(), + ResponseCreateParams.builder() + .inputOfResponse(approvals) + .previousResponseId(response.id())); + + System.out.println("Response: " + followUp.output()); + } else { + System.out.println("Response: " + response.output()); + } + } finally { + agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); + System.out.println("Agent deleted"); + } + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSample.java new file mode 100644 index 000000000000..c55fcb6d6d88 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSample.java @@ -0,0 +1,158 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ConversationsClient; +import com.azure.ai.agents.ResponsesClient; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.MemorySearchPreviewTool; +import com.azure.ai.agents.models.MemoryStoreDefaultDefinition; +import com.azure.ai.agents.models.MemoryStoreDefaultOptions; +import com.azure.ai.agents.models.MemoryStoreDetails; +import com.azure.ai.agents.MemoryStoresClient; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.exception.ResourceNotFoundException; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.conversations.Conversation; +import com.openai.models.responses.Response; +import com.openai.models.responses.ResponseCreateParams; + +import java.util.Collections; +import java.util.concurrent.TimeUnit; + +/** + * This sample demonstrates how to integrate memory into a prompt agent + * using the Memory Search tool to retrieve relevant past user messages. + * + *

Before running the sample, set these environment variables:

+ *
    + *
  • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
  • + *
  • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
  • + *
  • AZURE_AI_CHAT_MODEL_DEPLOYMENT_NAME - The chat model deployment name for memory.
  • + *
  • AZURE_AI_EMBEDDING_MODEL_DEPLOYMENT_NAME - The embedding model deployment name for memory.
  • + *
+ */ +public class MemorySearchSample { + private static final long MEMORY_WRITE_DELAY_SECONDS = 60; + + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String chatModel = Configuration.getGlobalConfiguration().get("AZURE_AI_CHAT_MODEL_DEPLOYMENT_NAME"); + String embeddingModel = Configuration.getGlobalConfiguration().get("AZURE_AI_EMBEDDING_MODEL_DEPLOYMENT_NAME"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsClient agentsClient = builder.buildAgentsClient(); + MemoryStoresClient memoryStoresClient = builder.buildMemoryStoresClient(); + ConversationsClient conversationsClient = builder.buildConversationsClient(); + ResponsesClient responsesClient = builder.buildResponsesClient(); + + String memoryStoreName = "my_memory_store"; + String scope = "user_123"; + AgentVersionDetails agent = null; + String firstConversationId = null; + String followUpConversationId = null; + + try { + // Delete memory store if it already exists + deleteMemoryStoreQuietly(memoryStoresClient, memoryStoreName); + + // Create a memory store + MemoryStoreDefaultDefinition definition = new MemoryStoreDefaultDefinition(chatModel, embeddingModel) + .setOptions(new MemoryStoreDefaultOptions(true, true)); + + MemoryStoreDetails memoryStore = memoryStoresClient.createMemoryStore( + memoryStoreName, definition, "Example memory store for conversations", null); + System.out.printf("Created memory store: %s (%s)%n", memoryStore.getName(), memoryStore.getId()); + + // Create memory search tool + MemorySearchPreviewTool tool = new MemorySearchPreviewTool(memoryStore.getName(), scope) + .setUpdateDelaySeconds(1); + + // Create agent with memory search tool + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a helpful assistant that answers general questions.") + .setTools(Collections.singletonList(tool)); + + agent = agentsClient.createAgentVersion("memory-search-agent", agentDefinition); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + // First conversation: teach the agent a preference + Conversation conversation = conversationsClient.getConversationService().create(); + firstConversationId = conversation.id(); + System.out.println("Created conversation (id: " + firstConversationId + ")"); + + Response response = responsesClient.createWithAgentConversation( + agentReference, firstConversationId, + ResponseCreateParams.builder().input("I prefer dark roast coffee")); + System.out.println("Response: " + getResponseText(response)); + + // Wait for memories to be extracted and stored + System.out.println("Waiting for memories to be stored..."); + TimeUnit.SECONDS.sleep(MEMORY_WRITE_DELAY_SECONDS); + + // Second conversation: test memory recall + Conversation newConversation = conversationsClient.getConversationService().create(); + followUpConversationId = newConversation.id(); + System.out.println("Created new conversation (id: " + followUpConversationId + ")"); + + Response followUpResponse = responsesClient.createWithAgentConversation( + agentReference, followUpConversationId, + ResponseCreateParams.builder().input("Please order my usual coffee")); + System.out.println("Response: " + getResponseText(followUpResponse)); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Sleep interrupted", e); + } finally { + deleteConversationQuietly(conversationsClient, firstConversationId); + deleteConversationQuietly(conversationsClient, followUpConversationId); + if (agent != null) { + agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); + System.out.println("Agent deleted"); + } + deleteMemoryStoreQuietly(memoryStoresClient, memoryStoreName); + } + } + + private static void deleteMemoryStoreQuietly(MemoryStoresClient client, String name) { + try { + client.deleteMemoryStore(name); + System.out.println("Memory store deleted: " + name); + } catch (ResourceNotFoundException ignored) { + // no-op + } + } + + private static void deleteConversationQuietly(ConversationsClient client, String id) { + if (id == null) { + return; + } + try { + client.getConversationService().delete(id); + } catch (Exception ignored) { + // best-effort cleanup + } + } + + private static String getResponseText(Response response) { + if (response == null || response.output().isEmpty()) { + return ""; + } + try { + return response.output().get(0).asMessage().content().get(0).asOutputText().text(); + } catch (RuntimeException ex) { + return ""; + } + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSample.java new file mode 100644 index 000000000000..454ee2118391 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSample.java @@ -0,0 +1,92 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ResponsesClient; +import com.azure.ai.agents.SampleUtils; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.OpenApiFunctionDefinition; +import com.azure.ai.agents.models.OpenApiProjectConnectionAuthDetails; +import com.azure.ai.agents.models.OpenApiProjectConnectionSecurityScheme; +import com.azure.ai.agents.models.OpenApiTool; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.BinaryData; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.Response; +import com.openai.models.responses.ResponseCreateParams; + +import java.util.Collections; +import java.util.Map; + +/** + * This sample demonstrates how to create an agent with an OpenAPI tool + * using project connection authentication. The agent can call external APIs + * defined by OpenAPI specifications, using credentials stored in an Azure AI + * Project connection. + * + *

Before running the sample, set these environment variables:

+ *
    + *
  • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
  • + *
  • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
  • + *
  • OPENAPI_PROJECT_CONNECTION_ID - The OpenAPI project connection ID.
  • + *
+ * + *

This sample uses the httpbin OpenAPI spec bundled at + * {@code src/samples/resources/assets/httpbin_openapi.json}. Replace it with your + * own spec to call a different API.

+ */ +public class OpenApiWithConnectionSample { + public static void main(String[] args) throws Exception { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String connectionId = Configuration.getGlobalConfiguration().get("OPENAPI_PROJECT_CONNECTION_ID"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsClient agentsClient = builder.buildAgentsClient(); + ResponsesClient responsesClient = builder.buildResponsesClient(); + + // Load the OpenAPI spec from a JSON file + Map spec = OpenApiFunctionDefinition.readSpecFromFile( + SampleUtils.getResourcePath("assets/httpbin_openapi.json")); + + // Create OpenAPI tool with project connection authentication + OpenApiTool openApiTool = new OpenApiTool( + new OpenApiFunctionDefinition( + "httpbin_get", + spec, + new OpenApiProjectConnectionAuthDetails( + new OpenApiProjectConnectionSecurityScheme(connectionId))) + .setDescription("Get request metadata from an OpenAPI endpoint.")); + + // Create agent with OpenAPI tool + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a helpful assistant.") + .setTools(Collections.singletonList(openApiTool)); + + AgentVersionDetails agent = agentsClient.createAgentVersion("openapi-connection-agent", agentDefinition); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + try { + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + Response response = responsesClient.createWithAgent( + agentReference, + ResponseCreateParams.builder() + .input("Call the API and summarize the returned URL and origin.")); + + System.out.println("Response: " + response.output()); + } finally { + agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); + System.out.println("Agent deleted"); + } + } +} From ce1b83c47c7bcd10f404efe3d6327cd9b9d01247 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Fri, 6 Mar 2026 14:38:42 +0100 Subject: [PATCH 07/22] Normalized samples --- sdk/ai/azure-ai-agents/UPDATE_README_LINKS.md | 182 +++++++----------- .../ai/agents/tools/AgentToAgentAsync.java | 82 ++++++++ ...AgentSample.java => AgentToAgentSync.java} | 2 +- .../ai/agents/tools/AzureAISearchAsync.java | 95 +++++++++ ...archSample.java => AzureAISearchSync.java} | 2 +- .../ai/agents/tools/AzureFunctionAsync.java | 108 +++++++++++ ...tionSample.java => AzureFunctionSync.java} | 2 +- .../agents/tools/BingCustomSearchAsync.java | 91 +++++++++ ...hSample.java => BingCustomSearchSync.java} | 2 +- .../ai/agents/tools/BingGroundingAsync.java | 88 +++++++++ ...dingSample.java => BingGroundingSync.java} | 2 +- .../agents/tools/BrowserAutomationAsync.java | 87 +++++++++ ...Sample.java => BrowserAutomationSync.java} | 2 +- ...ntAsync.java => CodeInterpreterAsync.java} | 42 ++-- .../agents/tools/CodeInterpreterSample.java | 75 -------- ...terAgent.java => CodeInterpreterSync.java} | 38 ++-- .../tools/CustomCodeInterpreterAsync.java | 87 +++++++++ ...le.java => CustomCodeInterpreterSync.java} | 2 +- .../azure/ai/agents/tools/FabricAsync.java | 89 +++++++++ .../{FabricSample.java => FabricSync.java} | 2 +- .../ai/agents/tools/FileSearchAsync.java | 172 +++++++++++++++++ .../ai/agents/tools/FileSearchSample.java | 74 ------- ...leSearchAgent.java => FileSearchSync.java} | 70 ++++--- ...AgentAsync.java => FunctionCallAsync.java} | 54 +++--- ...onCallAgent.java => FunctionCallSync.java} | 44 ++--- .../agents/tools/FunctionCallingSample.java | 79 -------- .../ai/agents/tools/ImageGenerationAsync.java | 87 +++++++++ ...onSample.java => ImageGenerationSync.java} | 2 +- .../{McpAgentAsync.java => McpAsync.java} | 55 +++--- .../tools/{McpAgent.java => McpSync.java} | 44 ++--- .../azure/ai/agents/tools/McpToolSample.java | 75 -------- .../agents/tools/McpWithConnectionAsync.java | 121 ++++++++++++ ...Sample.java => McpWithConnectionSync.java} | 2 +- .../ai/agents/tools/MemorySearchAsync.java | 151 +++++++++++++++ ...earchSample.java => MemorySearchSync.java} | 2 +- .../azure/ai/agents/tools/OpenApiAsync.java | 90 +++++++++ .../{OpenApiSample.java => OpenApiSync.java} | 2 +- .../tools/OpenApiWithConnectionAsync.java | 96 +++++++++ ...le.java => OpenApiWithConnectionSync.java} | 2 +- .../tools/SharePointGroundingAsync.java | 89 +++++++++ ...mple.java => SharePointGroundingSync.java} | 2 +- ...rchAgentAsync.java => WebSearchAsync.java} | 56 +++--- .../ai/agents/tools/WebSearchSample.java | 69 ------- ...WebSearchAgent.java => WebSearchSync.java} | 45 ++--- 44 files changed, 1823 insertions(+), 740 deletions(-) create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AgentToAgentAsync.java rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{AgentToAgentSample.java => AgentToAgentSync.java} (98%) create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchAsync.java rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{AzureAISearchSample.java => AzureAISearchSync.java} (99%) create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionAsync.java rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{AzureFunctionSample.java => AzureFunctionSync.java} (99%) create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchAsync.java rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{BingCustomSearchSample.java => BingCustomSearchSync.java} (99%) create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingAsync.java rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{BingGroundingSample.java => BingGroundingSync.java} (98%) create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationAsync.java rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{BrowserAutomationSample.java => BrowserAutomationSync.java} (98%) rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{CodeInterpreterAgentAsync.java => CodeInterpreterAsync.java} (77%) delete mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterSample.java rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{CodeInterpreterAgent.java => CodeInterpreterSync.java} (75%) create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CustomCodeInterpreterAsync.java rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{CustomCodeInterpreterSample.java => CustomCodeInterpreterSync.java} (98%) create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricAsync.java rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{FabricSample.java => FabricSync.java} (99%) create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchAsync.java delete mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchSample.java rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{FileSearchAgent.java => FileSearchSync.java} (78%) rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{FunctionCallAgentAsync.java => FunctionCallAsync.java} (71%) rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{FunctionCallAgent.java => FunctionCallSync.java} (73%) delete mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallingSample.java create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ImageGenerationAsync.java rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{ImageGenerationSample.java => ImageGenerationSync.java} (99%) rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{McpAgentAsync.java => McpAsync.java} (69%) rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{McpAgent.java => McpSync.java} (72%) delete mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpToolSample.java create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionAsync.java rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{McpWithConnectionSample.java => McpWithConnectionSync.java} (99%) create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchAsync.java rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{MemorySearchSample.java => MemorySearchSync.java} (99%) create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiAsync.java rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{OpenApiSample.java => OpenApiSync.java} (99%) create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionAsync.java rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{OpenApiWithConnectionSample.java => OpenApiWithConnectionSync.java} (98%) create mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingAsync.java rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{SharePointGroundingSample.java => SharePointGroundingSync.java} (98%) rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{WebSearchAgentAsync.java => WebSearchAsync.java} (65%) delete mode 100644 sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchSample.java rename sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/{WebSearchAgent.java => WebSearchSync.java} (67%) diff --git a/sdk/ai/azure-ai-agents/UPDATE_README_LINKS.md b/sdk/ai/azure-ai-agents/UPDATE_README_LINKS.md index 5fe03fa4ce05..09f3ed36e0e5 100644 --- a/sdk/ai/azure-ai-agents/UPDATE_README_LINKS.md +++ b/sdk/ai/azure-ai-agents/UPDATE_README_LINKS.md @@ -6,128 +6,82 @@ CI rejects `https://github.com/Azure/azure-sdk-for-java/tree/main/...` URLs that ## Samples not yet on `main` -| Sample File | PR | README Section | -|---|---|---| -| `OpenApiSample.java` | [#48315](https://github.com/Azure/azure-sdk-for-java/pull/48315) | **OpenAPI** (Built-in) | -| `AzureFunctionSample.java` | _not yet opened_ | **Azure Functions** (new Built-in section) | -| `MemorySearchSample.java` | _not yet opened_ | **Memory Search (Preview)** (new Built-in section) | -| `BingCustomSearchSample.java` | _not yet opened_ | **Bing Custom Search (Preview)** (new Connection-Based section) | -| `McpWithConnectionSample.java` | _not yet opened_ | **MCP with Project Connection** (new Connection-Based section) | -| `OpenApiWithConnectionSample.java` | _not yet opened_ | **OpenAPI with Project Connection** (new Connection-Based section) | - -## What to add after merge - -### 1. OpenAPI (existing section — restore link) - -After the `OpenApiTool` code snippet, replace the HTML comment with: - -```markdown -See the full sample in [OpenApiSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java). -``` - -### 2. Azure Functions (new Built-in section) - -Insert before `#### Connection-Based Tools`: - -```markdown ---- - -##### **Azure Functions** - -Call Azure Functions via Storage Queue input/output bindings: - -\```java -AzureFunctionTool tool = new AzureFunctionTool( - new AzureFunctionDefinition( - new AzureFunctionDefinitionDetails("queue_trigger", parameters) - .setDescription("Get weather for a given location"), - new AzureFunctionBinding( - new AzureFunctionStorageQueue(queueServiceEndpoint, inputQueueName)), - new AzureFunctionBinding( - new AzureFunctionStorageQueue(queueServiceEndpoint, outputQueueName)))); -\``` - -See the full sample in [AzureFunctionSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSample.java). -``` - -### 3. Memory Search (Preview) (new Built-in section) - -Insert before `#### Connection-Based Tools`: - -```markdown ---- - -##### **Memory Search (Preview)** ([documentation](https://learn.microsoft.com/azure/foundry/agents/concepts/what-is-memory)) +All tool samples were renamed from `*Sample.java` / `*Agent.java` to `*Sync.java` / `*Async.java`. +This means **every** README sample link will need updating once the new files land on `main`. -Retrieve relevant past user messages using memory stores: +### Renamed samples (exist on `main` under old names) -\```java -MemorySearchPreviewTool tool = new MemorySearchPreviewTool(memoryStoreName, scope) - .setUpdateDelaySeconds(1); -\``` +| Old Name (on `main`) | New Name | README Section | +|---|---|---| +| `CodeInterpreterSample.java` | `CodeInterpreterSync.java` | **Code Interpreter** | +| `FileSearchSample.java` | `FileSearchSync.java` | **File Search** | +| `ImageGenerationSample.java` | `ImageGenerationSync.java` | **Image Generation** | +| `WebSearchSample.java` | `WebSearchSync.java` | **Web Search (Preview)** | +| `ComputerUseSync.java` | `ComputerUseSync.java` | **Computer Use** (unchanged) | +| `McpToolSample.java` | `McpSync.java` | **MCP** | +| `FunctionCallingSample.java` | `FunctionCallSync.java` | **Function Tool** | +| `AzureAISearchSample.java` | `AzureAISearchSync.java` | **Azure AI Search** | +| `BingGroundingSample.java` | `BingGroundingSync.java` | **Bing Grounding** | +| `FabricSample.java` | `FabricSync.java` | **Microsoft Fabric** | +| `SharePointGroundingSample.java` | `SharePointGroundingSync.java` | **Microsoft SharePoint** | +| `BrowserAutomationSample.java` | `BrowserAutomationSync.java` | **Browser Automation** | +| `AgentToAgentSample.java` | `AgentToAgentSync.java` | **Agent-to-Agent (A2A)** | + +### Brand-new samples (not on `main` at all) + +| Sample File | README Section | +|---|---| +| `OpenApiSync.java` | **OpenAPI** (restore link — currently HTML comment) | +| `AzureFunctionSync.java` | **Azure Functions** (new Built-in section) | +| `MemorySearchSync.java` | **Memory Search (Preview)** (new Built-in section) | +| `BingCustomSearchSync.java` | **Bing Custom Search (Preview)** (new Connection-Based section) | +| `McpWithConnectionSync.java` | **MCP with Project Connection** (new Connection-Based section) | +| `OpenApiWithConnectionSync.java` | **OpenAPI with Project Connection** (new Connection-Based section) | + +### Deleted files (remove old links from `main`) + +| Old Name (on `main`) | Replaced By | +|---|---| +| `CodeInterpreterAgent.java` | `CodeInterpreterSync.java` | +| `CodeInterpreterAgentAsync.java` | `CodeInterpreterAsync.java` | +| `FunctionCallAgent.java` | `FunctionCallSync.java` | +| `FunctionCallAgentAsync.java` | `FunctionCallAsync.java` | +| `McpAgent.java` | `McpSync.java` | +| `McpAgentAsync.java` | `McpAsync.java` | +| `WebSearchAgent.java` | `WebSearchSync.java` | +| `WebSearchAgentAsync.java` | `WebSearchAsync.java` | +| `FileSearchAgent.java` | `FileSearchSync.java` | +| `FunctionCallingSample.java` | `FunctionCallSync.java` | +| `McpToolSample.java` | `McpSync.java` | + +## What to update in README + +### 1. Update all existing sample links (renamed files) + +Replace each `*Sample.java` / `*Agent.java` link with the corresponding `*Sync.java`: -See the full sample in [MemorySearchSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSample.java). ``` - -### 4. Bing Custom Search (Preview) (new Connection-Based section) - -Insert after the **Bing Grounding** section: - -```markdown ---- - -##### **Bing Custom Search (Preview)** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/bing-tools?pivots=java#grounding-with-bing-custom-search-preview)) - -Search custom Bing search instances for targeted results: - -\```java -BingCustomSearchPreviewTool tool = new BingCustomSearchPreviewTool( - new BingCustomSearchToolParameters(Arrays.asList( - new BingCustomSearchConfiguration(connectionId, instanceName)))); -\``` - -See the full sample in [BingCustomSearchSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSample.java). +CodeInterpreterSample.java → CodeInterpreterSync.java +FileSearchSample.java → FileSearchSync.java +ImageGenerationSample.java → ImageGenerationSync.java +WebSearchSample.java → WebSearchSync.java +McpToolSample.java → McpSync.java +FunctionCallingSample.java → FunctionCallSync.java +AzureAISearchSample.java → AzureAISearchSync.java +BingGroundingSample.java → BingGroundingSync.java +FabricSample.java → FabricSync.java +SharePointGroundingSample.java → SharePointGroundingSync.java +BrowserAutomationSample.java → BrowserAutomationSync.java +AgentToAgentSample.java → AgentToAgentSync.java ``` -### 5. MCP with Project Connection (new Connection-Based section) - -Insert after the **Agent-to-Agent (A2A) (Preview)** section: +### 2. Restore OpenAPI link +Replace the `` comment with: ```markdown ---- - -##### **MCP with Project Connection** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/model-context-protocol?pivots=java)) - -Connect to MCP servers using project connection authentication, with approval handling: - -\```java -McpTool tool = new McpTool("api-specs") - .setServerUrl("https://api.githubcopilot.com/mcp") - .setProjectConnectionId(mcpConnectionId) - .setRequireApproval(BinaryData.fromObject("always")); -\``` - -See the full sample in [McpWithConnectionSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSample.java). +See the full sample in [OpenApiSync.java](...tools/OpenApiSync.java). ``` -### 6. OpenAPI with Project Connection (new Connection-Based section) - -Insert after the **MCP with Project Connection** section: - -```markdown ---- - -##### **OpenAPI with Project Connection** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/openapi?pivots=java)) - -Call external APIs defined by OpenAPI specifications using project connection authentication: +### 3. Add 5 new tool sections -\```java -OpenApiTool tool = new OpenApiTool( - new OpenApiFunctionDefinition("my_api", spec, - new OpenApiProjectConnectionAuthDetails( - new OpenApiProjectConnectionSecurityScheme(connectionId))) - .setDescription("Call an authenticated API endpoint.")); -\``` - -See the full sample in [OpenApiWithConnectionSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSample.java). -``` +See previous version of this file for the exact markdown snippets. Update file names from `*Sample.java` to `*Sync.java`. diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AgentToAgentAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AgentToAgentAsync.java new file mode 100644 index 000000000000..f256bb5bc2df --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AgentToAgentAsync.java @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsAsyncClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ResponsesAsyncClient; +import com.azure.ai.agents.models.A2APreviewTool; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.ResponseCreateParams; +import java.time.Duration; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicReference; +import reactor.core.publisher.Mono; + +/** + * This sample demonstrates (using the async client) how to create an agent with an Agent-to-Agent (A2A) tool + * that can communicate with remote A2A endpoints. + * + *

Before running the sample, set these environment variables:

+ *
    + *
  • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
  • + *
  • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
  • + *
  • A2A_PROJECT_CONNECTION_ID - The A2A project connection ID.
  • + *
+ */ +public class AgentToAgentAsync { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String a2aConnectionId = Configuration.getGlobalConfiguration().get("A2A_PROJECT_CONNECTION_ID"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); + ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); + + AtomicReference agentRef = new AtomicReference<>(); + + // Create agent-to-agent tool with connection ID + A2APreviewTool a2aTool = new A2APreviewTool() + .setProjectConnectionId(a2aConnectionId); + // Create agent with agent-to-agent tool + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a coordinator agent that can communicate with other agents.") + .setTools(Collections.singletonList(a2aTool)); + + agentsAsyncClient.createAgentVersion("a2a-agent", agentDefinition) + .flatMap(agent -> { + agentRef.set(agent); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + return responsesAsyncClient.createWithAgent(agentReference, + ResponseCreateParams.builder() + .input("What can the secondary agent do?")); + }) + .doOnNext(response -> { + System.out.println("Response: " + response.output()); + }) + .then(Mono.defer(() -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) + .doOnSuccess(v -> System.out.println("Agent deleted")); + } + return Mono.empty(); + })) + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(300)) + .block(); + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AgentToAgentSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AgentToAgentSync.java similarity index 98% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AgentToAgentSample.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AgentToAgentSync.java index 178ab9acdc1c..64e4e41f59fe 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AgentToAgentSample.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AgentToAgentSync.java @@ -28,7 +28,7 @@ *
  • A2A_PROJECT_CONNECTION_ID - The A2A project connection ID.
  • * */ -public class AgentToAgentSample { +public class AgentToAgentSync { public static void main(String[] args) { String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchAsync.java new file mode 100644 index 000000000000..d80a63b39bd3 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchAsync.java @@ -0,0 +1,95 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsAsyncClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ResponsesAsyncClient; +import com.azure.ai.agents.models.AISearchIndexResource; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.AzureAISearchQueryType; +import com.azure.ai.agents.models.AzureAISearchTool; +import com.azure.ai.agents.models.AzureAISearchToolResource; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.ResponseCreateParams; +import java.time.Duration; +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicReference; +import reactor.core.publisher.Mono; + +/** + * This sample demonstrates (using the async client) how to create an agent with the Azure AI Search tool + * to search through indexed documents. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    • AZURE_AI_SEARCH_CONNECTION_ID - The Azure AI Search connection ID.
    • + *
    • AI_SEARCH_INDEX_NAME - The name of the search index.
    • + *
    + */ +public class AzureAISearchAsync { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String connectionId = Configuration.getGlobalConfiguration().get("AZURE_AI_SEARCH_CONNECTION_ID"); + String indexName = Configuration.getGlobalConfiguration().get("AI_SEARCH_INDEX_NAME"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); + ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); + + AtomicReference agentRef = new AtomicReference<>(); + + // Create Azure AI Search tool with index configuration + AzureAISearchTool aiSearchTool = new AzureAISearchTool( + new AzureAISearchToolResource(Arrays.asList( + new AISearchIndexResource() + .setProjectConnectionId(connectionId) + .setIndexName(indexName) + .setQueryType(AzureAISearchQueryType.SIMPLE) + )) + ); + // Create agent with AI Search tool + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a helpful assistant that can search through indexed documents. " + + "Always provide citations for answers using the tool.") + .setTools(Collections.singletonList(aiSearchTool)); + + agentsAsyncClient.createAgentVersion("ai-search-agent", agentDefinition) + .flatMap(agent -> { + agentRef.set(agent); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + return responsesAsyncClient.createWithAgent(agentReference, + ResponseCreateParams.builder() + .input("Search for information about Azure AI services")); + }) + .doOnNext(response -> { + System.out.println("Response: " + response.output()); + }) + .then(Mono.defer(() -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) + .doOnSuccess(v -> System.out.println("Agent deleted")); + } + return Mono.empty(); + })) + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(300)) + .block(); + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchSync.java similarity index 99% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchSample.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchSync.java index 0154d2d7cb7f..489cd79cba18 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchSample.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchSync.java @@ -33,7 +33,7 @@ *
  • AI_SEARCH_INDEX_NAME - The name of the search index.
  • * */ -public class AzureAISearchSample { +public class AzureAISearchSync { public static void main(String[] args) { String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionAsync.java new file mode 100644 index 000000000000..b4022eeafe88 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionAsync.java @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsAsyncClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ResponsesAsyncClient; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.AzureFunctionBinding; +import com.azure.ai.agents.models.AzureFunctionDefinition; +import com.azure.ai.agents.models.AzureFunctionDefinitionDetails; +import com.azure.ai.agents.models.AzureFunctionStorageQueue; +import com.azure.ai.agents.models.AzureFunctionTool; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.BinaryData; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.ResponseCreateParams; +import com.openai.models.responses.ToolChoiceOptions; +import reactor.core.publisher.Mono; + +import java.time.Duration; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +/** + * This sample demonstrates (using the async client) how to create an agent with an Azure Function tool + * that calls an Azure Function via Storage Queue input/output bindings. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    • STORAGE_INPUT_QUEUE_NAME - The Azure Storage Queue name for input.
    • + *
    • STORAGE_OUTPUT_QUEUE_NAME - The Azure Storage Queue name for output.
    • + *
    • STORAGE_QUEUE_SERVICE_ENDPOINT - The Azure Storage Queue service endpoint.
    • + *
    + */ +public class AzureFunctionAsync { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String inputQueueName = Configuration.getGlobalConfiguration().get("STORAGE_INPUT_QUEUE_NAME"); + String outputQueueName = Configuration.getGlobalConfiguration().get("STORAGE_OUTPUT_QUEUE_NAME"); + String queueServiceEndpoint = Configuration.getGlobalConfiguration().get("STORAGE_QUEUE_SERVICE_ENDPOINT"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); + ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); + + AtomicReference agentRef = new AtomicReference<>(); + + Map parameters = new HashMap<>(); + parameters.put("type", BinaryData.fromString("\"object\"")); + parameters.put("properties", BinaryData.fromString( + "{\"location\":{\"type\":\"string\",\"description\":\"location to determine weather for\"}}")); + + AzureFunctionTool azureFunctionTool = new AzureFunctionTool( + new AzureFunctionDefinition( + new AzureFunctionDefinitionDetails("queue_trigger", parameters) + .setDescription("Get weather for a given location"), + new AzureFunctionBinding( + new AzureFunctionStorageQueue(queueServiceEndpoint, inputQueueName)), + new AzureFunctionBinding( + new AzureFunctionStorageQueue(queueServiceEndpoint, outputQueueName)) + ) + ); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a helpful assistant.") + .setTools(Collections.singletonList(azureFunctionTool)); + + agentsAsyncClient.createAgentVersion("azure-function-agent", agentDefinition) + .flatMap(agent -> { + agentRef.set(agent); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + return responsesAsyncClient.createWithAgent(agentReference, + ResponseCreateParams.builder() + .toolChoice(ToolChoiceOptions.REQUIRED) + .input("What is the weather in Seattle?")); + }) + .doOnNext(response -> { + System.out.println("Response: " + response.output()); + }) + .then(Mono.defer(() -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) + .doOnSuccess(v -> System.out.println("Agent deleted")); + } + return Mono.empty(); + })) + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(300)) + .block(); + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSync.java similarity index 99% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSample.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSync.java index 100d8e470266..268ba1914618 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSample.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSync.java @@ -38,7 +38,7 @@ *
  • STORAGE_QUEUE_SERVICE_ENDPOINT - The Azure Storage Queue service endpoint.
  • * */ -public class AzureFunctionSample { +public class AzureFunctionSync { public static void main(String[] args) { String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchAsync.java new file mode 100644 index 000000000000..9d1f9bdb73d0 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchAsync.java @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsAsyncClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ResponsesAsyncClient; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.BingCustomSearchConfiguration; +import com.azure.ai.agents.models.BingCustomSearchPreviewTool; +import com.azure.ai.agents.models.BingCustomSearchToolParameters; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.ResponseCreateParams; +import reactor.core.publisher.Mono; + +import java.time.Duration; +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicReference; + +/** + * This sample demonstrates (using the async client) how to create an agent with the Bing Custom Search tool + * to search custom search instances and provide responses with relevant results. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    • BING_CUSTOM_SEARCH_PROJECT_CONNECTION_ID - The Bing Custom Search project connection ID.
    • + *
    • BING_CUSTOM_SEARCH_INSTANCE_NAME - The Bing Custom Search instance name.
    • + *
    + */ +public class BingCustomSearchAsync { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String connectionId = Configuration.getGlobalConfiguration().get("BING_CUSTOM_SEARCH_PROJECT_CONNECTION_ID"); + String instanceName = Configuration.getGlobalConfiguration().get("BING_CUSTOM_SEARCH_INSTANCE_NAME"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); + ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); + + AtomicReference agentRef = new AtomicReference<>(); + + BingCustomSearchPreviewTool bingCustomSearchTool = new BingCustomSearchPreviewTool( + new BingCustomSearchToolParameters(Arrays.asList( + new BingCustomSearchConfiguration(connectionId, instanceName) + )) + ); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a helpful agent that can use Bing Custom Search tools to assist users. " + + "Use the available Bing Custom Search tools to answer questions and perform tasks.") + .setTools(Collections.singletonList(bingCustomSearchTool)); + + agentsAsyncClient.createAgentVersion("bing-custom-search-agent", agentDefinition) + .flatMap(agent -> { + agentRef.set(agent); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + return responsesAsyncClient.createWithAgent(agentReference, + ResponseCreateParams.builder() + .input("Search for the latest Azure AI documentation")); + }) + .doOnNext(response -> { + System.out.println("Response: " + response.output()); + }) + .then(Mono.defer(() -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) + .doOnSuccess(v -> System.out.println("Agent deleted")); + } + return Mono.empty(); + })) + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(300)) + .block(); + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSync.java similarity index 99% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSample.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSync.java index 61c21fc99e16..7f23f41b4941 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSample.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSync.java @@ -37,7 +37,7 @@ *
  • BING_CUSTOM_SEARCH_INSTANCE_NAME - The Bing Custom Search instance name.
  • * */ -public class BingCustomSearchSample { +public class BingCustomSearchSync { public static void main(String[] args) { String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingAsync.java new file mode 100644 index 000000000000..863cd1615e66 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingAsync.java @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsAsyncClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ResponsesAsyncClient; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.BingGroundingSearchConfiguration; +import com.azure.ai.agents.models.BingGroundingSearchToolParameters; +import com.azure.ai.agents.models.BingGroundingTool; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.ResponseCreateParams; +import java.time.Duration; +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicReference; +import reactor.core.publisher.Mono; + +/** + * This sample demonstrates (using the async client) how to create an agent with the Bing Grounding tool + * to find up-to-date information from the web. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    • BING_PROJECT_CONNECTION_ID - The Bing project connection ID.
    • + *
    + */ +public class BingGroundingAsync { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String bingConnectionId = Configuration.getGlobalConfiguration().get("BING_PROJECT_CONNECTION_ID"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); + ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); + + AtomicReference agentRef = new AtomicReference<>(); + + // Create Bing grounding tool with connection configuration + BingGroundingTool bingTool = new BingGroundingTool( + new BingGroundingSearchToolParameters(Arrays.asList( + new BingGroundingSearchConfiguration(bingConnectionId) + )) + ); + // Create agent with Bing grounding tool + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a helpful assistant. Use Bing to find up-to-date information.") + .setTools(Collections.singletonList(bingTool)); + + agentsAsyncClient.createAgentVersion("bing-grounding-agent", agentDefinition) + .flatMap(agent -> { + agentRef.set(agent); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + return responsesAsyncClient.createWithAgent(agentReference, + ResponseCreateParams.builder() + .input("What are the latest developments in AI?")); + }) + .doOnNext(response -> { + System.out.println("Response: " + response.output()); + }) + .then(Mono.defer(() -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) + .doOnSuccess(v -> System.out.println("Agent deleted")); + } + return Mono.empty(); + })) + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(300)) + .block(); + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingSync.java similarity index 98% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingSample.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingSync.java index e55c562fd208..851bad795aae 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingSample.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingSync.java @@ -31,7 +31,7 @@ *
  • BING_PROJECT_CONNECTION_ID - The Bing project connection ID.
  • * */ -public class BingGroundingSample { +public class BingGroundingSync { public static void main(String[] args) { String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationAsync.java new file mode 100644 index 000000000000..4534e8869703 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationAsync.java @@ -0,0 +1,87 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsAsyncClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ResponsesAsyncClient; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.BrowserAutomationPreviewTool; +import com.azure.ai.agents.models.BrowserAutomationToolConnectionParameters; +import com.azure.ai.agents.models.BrowserAutomationToolParameters; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.ResponseCreateParams; +import java.time.Duration; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicReference; +import reactor.core.publisher.Mono; + +/** + * This sample demonstrates (using the async client) how to create an agent with the Browser Automation tool + * to interact with web pages. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    • BROWSER_AUTOMATION_PROJECT_CONNECTION_ID - The browser automation connection ID.
    • + *
    + */ +public class BrowserAutomationAsync { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String connectionId = Configuration.getGlobalConfiguration().get("BROWSER_AUTOMATION_PROJECT_CONNECTION_ID"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); + ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); + + AtomicReference agentRef = new AtomicReference<>(); + + // Create browser automation tool with connection configuration + BrowserAutomationPreviewTool browserTool = new BrowserAutomationPreviewTool( + new BrowserAutomationToolParameters( + new BrowserAutomationToolConnectionParameters(connectionId) + ) + ); + // Create agent with browser automation tool + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a helpful assistant that can interact with web pages.") + .setTools(Collections.singletonList(browserTool)); + + agentsAsyncClient.createAgentVersion("browser-agent", agentDefinition) + .flatMap(agent -> { + agentRef.set(agent); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + return responsesAsyncClient.createWithAgent(agentReference, + ResponseCreateParams.builder() + .input("Navigate to microsoft.com and summarize the main content")); + }) + .doOnNext(response -> { + System.out.println("Response: " + response.output()); + }) + .then(Mono.defer(() -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) + .doOnSuccess(v -> System.out.println("Agent deleted")); + } + return Mono.empty(); + })) + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(300)) + .block(); + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationSync.java similarity index 98% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationSample.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationSync.java index 2104451e21ff..29d224f3818c 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationSample.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationSync.java @@ -30,7 +30,7 @@ *
  • BROWSER_AUTOMATION_PROJECT_CONNECTION_ID - The browser automation connection ID.
  • * */ -public class BrowserAutomationSample { +public class BrowserAutomationSync { public static void main(String[] args) { String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterAgentAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterAsync.java similarity index 77% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterAgentAsync.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterAsync.java index abead1862f48..559a18968699 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterAgentAsync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterAsync.java @@ -23,13 +23,19 @@ import java.util.concurrent.atomic.AtomicReference; /** - * This sample demonstrates how to create an Azure AI Agent with the Code Interpreter tool - * and use it to get responses that involve code execution using the async client. + * This sample demonstrates how to create an agent with the Code Interpreter tool + * for executing Python code, data analysis, and visualization using the async client. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    */ -public class CodeInterpreterAgentAsync { - public static void main(String[] args) throws InterruptedException { - String endpoint = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_ENDPOINT"); - String model = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_MODEL"); +public class CodeInterpreterAsync { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); AgentsClientBuilder builder = new AgentsClientBuilder() .credential(new DefaultAzureCredentialBuilder().build()) @@ -38,33 +44,30 @@ public static void main(String[] args) throws InterruptedException { AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); - // For cleanup AtomicReference agentRef = new AtomicReference<>(); // Create a CodeInterpreterTool with default auto container configuration CodeInterpreterTool tool = new CodeInterpreterTool(); - // Create the agent definition with Code Interpreter tool enabled PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) .setInstructions("You are a helpful assistant that can execute Python code to solve problems. " + "When asked to perform calculations or data analysis, use the code interpreter to run Python code.") .setTools(Collections.singletonList(tool)); - agentsAsyncClient.createAgentVersion("MyAgent", agentDefinition) + agentsAsyncClient.createAgentVersion("code-interpreter-agent", agentDefinition) .flatMap(agent -> { agentRef.set(agent); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); - AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); return responsesAsyncClient.createWithAgent(agentReference, ResponseCreateParams.builder() .input("Calculate the first 10 prime numbers and show me the Python code you used.")); }) .doOnNext(response -> { - // Process and display the response - System.out.println("\n=== Agent Response ==="); for (ResponseOutputItem outputItem : response.output()) { - // Handle message output if (outputItem.message().isPresent()) { ResponseOutputMessage message = outputItem.message().get(); message.content().forEach(content -> { @@ -74,7 +77,6 @@ public static void main(String[] args) throws InterruptedException { }); } - // Handle code interpreter tool call output if (outputItem.codeInterpreterCall().isPresent()) { ResponseCodeInterpreterToolCall codeCall = outputItem.codeInterpreterCall().get(); System.out.println("\n--- Code Interpreter Execution ---"); @@ -85,23 +87,17 @@ public static void main(String[] args) throws InterruptedException { System.out.println("Status: " + codeCall.status()); } } - - System.out.println("\nResponse ID: " + response.id()); - System.out.println("Model Used: " + response.model()); }) - // Cleanup agent .then(Mono.defer(() -> { AgentVersionDetails agent = agentRef.get(); if (agent != null) { return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) - .doOnSuccess(v -> System.out.println("Agent deleted successfully.")); + .doOnSuccess(v -> System.out.println("Agent deleted")); } return Mono.empty(); })) - .doOnError(error -> { - System.err.println("Error: " + error.getMessage()); - error.printStackTrace(); - }).timeout(Duration.ofSeconds(300)) + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(300)) .block(); } } diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterSample.java deleted file mode 100644 index 4a8a934c18d6..000000000000 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterSample.java +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.ai.agents.tools; - -import com.azure.ai.agents.AgentsClient; -import com.azure.ai.agents.AgentsClientBuilder; -import com.azure.ai.agents.ResponsesClient; -import com.azure.ai.agents.models.AgentReference; -import com.azure.ai.agents.models.AgentVersionDetails; -import com.azure.ai.agents.models.CodeInterpreterTool; -import com.azure.ai.agents.models.PromptAgentDefinition; -import com.azure.core.util.Configuration; -import com.azure.identity.DefaultAzureCredentialBuilder; -import com.openai.models.responses.Response; -import com.openai.models.responses.ResponseCreateParams; - -import java.util.Collections; - -/** - * This sample demonstrates how to create an agent with the Code Interpreter tool - * for data visualization and code execution. - * - *

    Before running the sample, set these environment variables:

    - *
      - *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • - *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • - *
    - */ -public class CodeInterpreterSample { - public static void main(String[] args) { - String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); - String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); - - AgentsClientBuilder builder = new AgentsClientBuilder() - .credential(new DefaultAzureCredentialBuilder().build()) - .endpoint(endpoint); - - AgentsClient agentsClient = builder.buildAgentsClient(); - ResponsesClient responsesClient = builder.buildResponsesClient(); - - // Create code interpreter tool - CodeInterpreterTool codeInterpreter = new CodeInterpreterTool(); - - // Create agent with code interpreter for data visualization - PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) - .setInstructions("You are a data visualization assistant. When asked to create charts, " - + "write and run Python code using matplotlib to generate them.") - .setTools(Collections.singletonList(codeInterpreter)); - - AgentVersionDetails agent = agentsClient.createAgentVersion("chart-agent", agentDefinition); - System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); - - try { - // Request a bar chart with inline data - AgentReference agentReference = new AgentReference(agent.getName()) - .setVersion(agent.getVersion()); - - Response response = responsesClient.createWithAgent( - agentReference, - ResponseCreateParams.builder() - .input("Create a bar chart showing quarterly revenue for 2025: " - + "Q1=$2.1M, Q2=$2.8M, Q3=$3.2M, Q4=$2.9M. " - + "Use a blue color scheme, add data labels on each bar, " - + "and title the chart 'Quarterly Revenue 2025'. " - + "Save the chart as a PNG file.")); - - System.out.println("Response: " + response.output()); - } finally { - // Clean up - agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); - System.out.println("Agent deleted"); - } - } -} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterAgent.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterSync.java similarity index 75% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterAgent.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterSync.java index 72d94803588a..897253e761e1 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterAgent.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterSync.java @@ -21,13 +21,19 @@ import java.util.Collections; /** - * This sample demonstrates how to create an Azure AI Agent with the Code Interpreter tool - * and use it to get responses that involve code execution. + * This sample demonstrates how to create an agent with the Code Interpreter tool + * for executing Python code, data analysis, and visualization. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    */ -public class CodeInterpreterAgent { +public class CodeInterpreterSync { public static void main(String[] args) { - String endpoint = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_ENDPOINT"); - String model = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_MODEL"); + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); AgentsClientBuilder builder = new AgentsClientBuilder() .credential(new DefaultAzureCredentialBuilder().build()) @@ -48,18 +54,18 @@ public static void main(String[] args) { + "When asked to perform calculations or data analysis, use the code interpreter to run Python code.") .setTools(Collections.singletonList(tool)); - agent = agentsClient.createAgentVersion("MyAgent", agentDefinition); - System.out.printf("Agent created (id: %s, version: %s)\n", agent.getId(), agent.getVersion()); + agent = agentsClient.createAgentVersion("code-interpreter-agent", agentDefinition); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); - AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); Response response = responsesClient.createWithAgent(agentReference, - ResponseCreateParams.builder().input("Calculate the first 10 prime numbers and show me the Python code you used.")); + ResponseCreateParams.builder() + .input("Calculate the first 10 prime numbers and show me the Python code you used.")); // Process and display the response - System.out.println("\n=== Agent Response ==="); for (ResponseOutputItem outputItem : response.output()) { - // Handle message output if (outputItem.message().isPresent()) { ResponseOutputMessage message = outputItem.message().get(); message.content().forEach(content -> { @@ -69,7 +75,6 @@ public static void main(String[] args) { }); } - // Handle code interpreter tool call output if (outputItem.codeInterpreterCall().isPresent()) { ResponseCodeInterpreterToolCall codeCall = outputItem.codeInterpreterCall().get(); System.out.println("\n--- Code Interpreter Execution ---"); @@ -80,17 +85,10 @@ public static void main(String[] args) { System.out.println("Status: " + codeCall.status()); } } - - System.out.println("\nResponse ID: " + response.id()); - System.out.println("Model Used: " + response.model()); - } catch (Exception e) { - System.err.println("Error: " + e.getMessage()); - e.printStackTrace(); } finally { - // Cleanup agent if (agent != null) { agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); - System.out.println("Agent deleted successfully."); + System.out.println("Agent deleted"); } } } diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CustomCodeInterpreterAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CustomCodeInterpreterAsync.java new file mode 100644 index 000000000000..c29f56fa4ec8 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CustomCodeInterpreterAsync.java @@ -0,0 +1,87 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsAsyncClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ResponsesAsyncClient; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.McpTool; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.BinaryData; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.ResponseCreateParams; +import reactor.core.publisher.Mono; + +import java.time.Duration; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicReference; + +/** + * This sample demonstrates (using the async client) how to create an agent with a Custom Code Interpreter + * backed by an MCP tool pointing to a Container Apps code interpreter session. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    • MCP_SERVER_URL - The MCP server URL for the custom code interpreter.
    • + *
    • MCP_PROJECT_CONNECTION_ID - The MCP project connection ID.
    • + *
    + */ +public class CustomCodeInterpreterAsync { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String mcpServerUrl = Configuration.getGlobalConfiguration().get("MCP_SERVER_URL"); + String connectionId = Configuration.getGlobalConfiguration().get("MCP_PROJECT_CONNECTION_ID"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); + ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); + + AtomicReference agentRef = new AtomicReference<>(); + + McpTool customCodeInterpreter = new McpTool("custom-code-interpreter") + .setServerUrl(mcpServerUrl) + .setProjectConnectionId(connectionId) + .setRequireApproval(BinaryData.fromObject("never")); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a helpful assistant that can run Python code to analyze data and solve problems.") + .setTools(Collections.singletonList(customCodeInterpreter)); + + agentsAsyncClient.createAgentVersion("CustomCodeInterpreterAgent", agentDefinition) + .flatMap(agent -> { + agentRef.set(agent); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + return responsesAsyncClient.createWithAgent(agentReference, + ResponseCreateParams.builder() + .input("Calculate the factorial of 10 using Python.")); + }) + .doOnNext(response -> { + System.out.println("Response: " + response.output()); + }) + .then(Mono.defer(() -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) + .doOnSuccess(v -> System.out.println("Agent deleted")); + } + return Mono.empty(); + })) + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(300)) + .block(); + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CustomCodeInterpreterSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CustomCodeInterpreterSync.java similarity index 98% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CustomCodeInterpreterSample.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CustomCodeInterpreterSync.java index f5d183d74baf..b10a07f0ee1b 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CustomCodeInterpreterSample.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CustomCodeInterpreterSync.java @@ -30,7 +30,7 @@ *
  • MCP_PROJECT_CONNECTION_ID - The MCP project connection ID.
  • * */ -public class CustomCodeInterpreterSample { +public class CustomCodeInterpreterSync { public static void main(String[] args) { String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricAsync.java new file mode 100644 index 000000000000..05ed39b6aab4 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricAsync.java @@ -0,0 +1,89 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsAsyncClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ResponsesAsyncClient; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.FabricDataAgentToolParameters; +import com.azure.ai.agents.models.MicrosoftFabricPreviewTool; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.ai.agents.models.ToolProjectConnection; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.ResponseCreateParams; +import java.time.Duration; +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicReference; +import reactor.core.publisher.Mono; + +/** + * This sample demonstrates (using the async client) how to create an agent with the Microsoft Fabric tool + * to query data from Microsoft Fabric. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    • FABRIC_PROJECT_CONNECTION_ID - The Microsoft Fabric connection ID.
    • + *
    + */ +public class FabricAsync { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String fabricConnectionId = Configuration.getGlobalConfiguration().get("FABRIC_PROJECT_CONNECTION_ID"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); + ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); + + AtomicReference agentRef = new AtomicReference<>(); + + // Create Microsoft Fabric tool with connection configuration + MicrosoftFabricPreviewTool fabricTool = new MicrosoftFabricPreviewTool( + new FabricDataAgentToolParameters() + .setProjectConnections(Arrays.asList( + new ToolProjectConnection(fabricConnectionId) + )) + ); + // Create agent with Fabric tool + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a data assistant that can query Microsoft Fabric data.") + .setTools(Collections.singletonList(fabricTool)); + + agentsAsyncClient.createAgentVersion("fabric-agent", agentDefinition) + .flatMap(agent -> { + agentRef.set(agent); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + return responsesAsyncClient.createWithAgent(agentReference, + ResponseCreateParams.builder() + .input("Query the latest sales data from Microsoft Fabric")); + }) + .doOnNext(response -> { + System.out.println("Response: " + response.output()); + }) + .then(Mono.defer(() -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) + .doOnSuccess(v -> System.out.println("Agent deleted")); + } + return Mono.empty(); + })) + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(300)) + .block(); + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricSync.java similarity index 99% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricSample.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricSync.java index 5bf9af5c6129..3e6460a9730a 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricSample.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricSync.java @@ -31,7 +31,7 @@ *
  • FABRIC_PROJECT_CONNECTION_ID - The Microsoft Fabric connection ID.
  • * */ -public class FabricSample { +public class FabricSync { public static void main(String[] args) { String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchAsync.java new file mode 100644 index 000000000000..ee566c8a380a --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchAsync.java @@ -0,0 +1,172 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsAsyncClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ConversationsAsyncClient; +import com.azure.ai.agents.ResponsesAsyncClient; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.FileSearchTool; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.credential.TokenCredential; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.client.OpenAIClient; +import com.openai.models.files.FileCreateParams; +import com.openai.models.files.FileObject; +import com.openai.models.files.FilePurpose; +import com.openai.models.responses.Response; +import com.openai.models.responses.ResponseCreateParams; +import com.openai.models.responses.ResponseFileSearchToolCall; +import com.openai.models.responses.ResponseOutputItem; +import com.openai.models.responses.ResponseOutputMessage; +import com.openai.models.vectorstores.VectorStore; +import com.openai.models.vectorstores.VectorStoreCreateParams; +import reactor.core.publisher.Mono; + +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Duration; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicReference; + +/** + * This sample demonstrates how to create an agent with the File Search tool + * using the async client. It creates a vector store, uploads a file, and uses + * the agent to search the file within a conversation. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    + */ +public class FileSearchAsync { + public static void main(String[] args) throws Exception { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + + TokenCredential credential = new DefaultAzureCredentialBuilder().build(); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(credential) + .endpoint(endpoint); + + AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); + ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); + ConversationsAsyncClient conversationsAsyncClient = builder.buildConversationsAsyncClient(); + // Vector store and file operations use the sync OpenAI client for setup + OpenAIClient openAIClient = builder.buildOpenAIClient(); + + AtomicReference agentRef = new AtomicReference<>(); + AtomicReference conversationIdRef = new AtomicReference<>(); + + // Create a sample document and upload it + String sampleContent = "The Solar System consists of the Sun and the celestial objects bound to it by gravity. " + + "The eight planets in order from the Sun are: Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, and Neptune. " + + "Earth is the third planet from the Sun and the only known planet to harbor life. " + + "Jupiter is the largest planet, while Mercury is the smallest."; + + Path tempFile = Files.createTempFile("sample_document", ".txt"); + Files.write(tempFile, sampleContent.getBytes(StandardCharsets.UTF_8)); + + FileObject uploadedFile = openAIClient.files().create(FileCreateParams.builder() + .file(tempFile) + .purpose(FilePurpose.ASSISTANTS) + .build()); + System.out.println("Uploaded file: " + uploadedFile.id()); + + VectorStore vectorStore = openAIClient.vectorStores().create(VectorStoreCreateParams.builder() + .name("SampleVectorStore") + .fileIds(Collections.singletonList(uploadedFile.id())) + .build()); + System.out.println("Created vector store: " + vectorStore.id()); + + Thread.sleep(5000); // Wait for vector store to process + + FileSearchTool tool = new FileSearchTool(Collections.singletonList(vectorStore.id())); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a helpful assistant that can search through uploaded files to answer questions.") + .setTools(Collections.singletonList(tool)); + + agentsAsyncClient.createAgentVersion("file-search-agent", agentDefinition) + .flatMap(agent -> { + agentRef.set(agent); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + return Mono.fromFuture(conversationsAsyncClient.getConversationServiceAsync().create()) + .flatMap(conversation -> { + conversationIdRef.set(conversation.id()); + System.out.println("Created conversation: " + conversation.id()); + + return responsesAsyncClient.createWithAgentConversation(agentReference, conversation.id(), + ResponseCreateParams.builder() + .input("What is the largest planet in the Solar System?")); + }); + }) + .doOnNext(response -> { + for (ResponseOutputItem outputItem : response.output()) { + if (outputItem.message().isPresent()) { + ResponseOutputMessage message = outputItem.message().get(); + message.content().forEach(content -> { + content.outputText().ifPresent(text -> { + System.out.println("Assistant: " + text.text()); + }); + }); + } + + if (outputItem.fileSearchCall().isPresent()) { + ResponseFileSearchToolCall fileSearchCall = outputItem.fileSearchCall().get(); + System.out.println("\n--- File Search Execution ---"); + System.out.println("Call ID: " + fileSearchCall.id()); + System.out.println("Status: " + fileSearchCall.status()); + fileSearchCall.results().ifPresent(results -> { + System.out.println("Results found: " + results.size()); + results.forEach(result -> { + System.out.println(" - File ID: " + result.fileId()); + result.filename().ifPresent(name -> System.out.println(" Filename: " + name)); + result.score().ifPresent(score -> System.out.println(" Score: " + score)); + }); + }); + } + } + }) + .then(Mono.defer(() -> { + String convId = conversationIdRef.get(); + if (convId != null) { + return Mono.fromFuture(conversationsAsyncClient.getConversationServiceAsync().delete(convId)) + .then(); + } + return Mono.empty(); + })) + .then(Mono.defer(() -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) + .doOnSuccess(v -> System.out.println("Agent deleted")); + } + return Mono.empty(); + })) + .doFinally(signal -> { + openAIClient.vectorStores().delete(vectorStore.id()); + openAIClient.files().delete(uploadedFile.id()); + try { + Files.deleteIfExists(tempFile); + } catch (Exception ignored) { + // best-effort + } + System.out.println("Vector store and file deleted"); + }) + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(300)) + .block(); + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchSample.java deleted file mode 100644 index 873404c22c1b..000000000000 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchSample.java +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.ai.agents.tools; - -import com.azure.ai.agents.AgentsClient; -import com.azure.ai.agents.AgentsClientBuilder; -import com.azure.ai.agents.ResponsesClient; -import com.azure.ai.agents.models.AgentReference; -import com.azure.ai.agents.models.AgentVersionDetails; -import com.azure.ai.agents.models.FileSearchTool; -import com.azure.ai.agents.models.PromptAgentDefinition; -import com.azure.core.util.Configuration; -import com.azure.identity.DefaultAzureCredentialBuilder; -import com.openai.models.responses.Response; -import com.openai.models.responses.ResponseCreateParams; - -import java.util.Arrays; -import java.util.Collections; - -/** - * This sample demonstrates how to create an agent with the File Search tool - * to search through files in a vector store. - * - *

    Before running the sample, set these environment variables:

    - *
      - *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • - *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • - *
    • VECTOR_STORE_ID - The ID of the vector store containing the files.
    • - *
    - */ -public class FileSearchSample { - public static void main(String[] args) { - String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); - String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); - String vectorStoreId = Configuration.getGlobalConfiguration().get("VECTOR_STORE_ID"); - - AgentsClientBuilder builder = new AgentsClientBuilder() - .credential(new DefaultAzureCredentialBuilder().build()) - .endpoint(endpoint); - - AgentsClient agentsClient = builder.buildAgentsClient(); - ResponsesClient responsesClient = builder.buildResponsesClient(); - - // Create file search tool with vector store IDs - FileSearchTool fileSearchTool = new FileSearchTool( - Arrays.asList(vectorStoreId) - ); - - // Create agent with file search tool - PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) - .setInstructions("You are a helpful assistant that can search through files to answer questions.") - .setTools(Collections.singletonList(fileSearchTool)); - - AgentVersionDetails agent = agentsClient.createAgentVersion("file-search-agent", agentDefinition); - System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); - - try { - // Create a response - AgentReference agentReference = new AgentReference(agent.getName()) - .setVersion(agent.getVersion()); - - Response response = responsesClient.createWithAgent( - agentReference, - ResponseCreateParams.builder() - .input("What information is in the uploaded files?")); - - System.out.println("Response: " + response.output()); - } finally { - // Clean up - agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); - } - } -} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchAgent.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchSync.java similarity index 78% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchAgent.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchSync.java index e5d688def3d9..b84bf3802360 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchAgent.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchSync.java @@ -3,14 +3,8 @@ package com.azure.ai.agents.tools; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Collections; - import com.azure.ai.agents.AgentsClient; import com.azure.ai.agents.AgentsClientBuilder; -import com.azure.ai.agents.AgentsServiceVersion; import com.azure.ai.agents.ConversationsClient; import com.azure.ai.agents.ResponsesClient; import com.azure.ai.agents.models.AgentReference; @@ -33,28 +27,36 @@ import com.openai.models.vectorstores.VectorStore; import com.openai.models.vectorstores.VectorStoreCreateParams; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; + /** - * This sample demonstrates how to create an Azure AI Agent with the File Search tool - * and use it to get responses that involve searching uploaded files. - * It creates a vector store, uploads a file, and then uses the agent to search the file. + * This sample demonstrates how to create an agent with the File Search tool. + * It creates a vector store, uploads a file, and uses the agent to search the file + * within a conversation. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    */ -public class FileSearchAgent { +public class FileSearchSync { public static void main(String[] args) { - String endpoint = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_ENDPOINT"); - String model = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_MODEL"); + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); TokenCredential credential = new DefaultAzureCredentialBuilder().build(); AgentsClientBuilder builder = new AgentsClientBuilder() .credential(credential) - .serviceVersion(AgentsServiceVersion.getLatest()) .endpoint(endpoint); AgentsClient agentsClient = builder.buildAgentsClient(); ResponsesClient responsesClient = builder.buildResponsesClient(); ConversationsClient conversationsClient = builder.buildConversationsClient(); - - // Create OpenAI client for vector store and file operations OpenAIClient openAIClient = builder.buildOpenAIClient(); AgentVersionDetails agent = null; @@ -64,10 +66,11 @@ public static void main(String[] args) { Path tempFile = null; try { + // Create a sample document and upload it String sampleContent = "The Solar System consists of the Sun and the celestial objects bound to it by gravity. " + "The eight planets in order from the Sun are: Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, and Neptune. " + "Earth is the third planet from the Sun and the only known planet to harbor life. " - + "Jupiter is the largest planet, while Mercury is the smallest. "; + + "Jupiter is the largest planet, while Mercury is the smallest."; tempFile = Files.createTempFile("sample_document", ".txt"); Files.write(tempFile, sampleContent.getBytes(StandardCharsets.UTF_8)); @@ -78,6 +81,7 @@ public static void main(String[] args) { .build()); System.out.println("Uploaded file: " + uploadedFile.id()); + // Create a vector store with the uploaded file vectorStore = openAIClient.vectorStores().create(VectorStoreCreateParams.builder() .name("SampleVectorStore") .fileIds(Collections.singletonList(uploadedFile.id())) @@ -85,32 +89,32 @@ public static void main(String[] args) { System.out.println("Created vector store: " + vectorStore.id()); System.out.println("Waiting for vector store to process files..."); - Thread.sleep(5000); // Wait for vector store to be ready + Thread.sleep(5000); // Create a FileSearchTool with the vector store ID FileSearchTool tool = new FileSearchTool(Collections.singletonList(vectorStore.id())); - // Create the agent definition with File Search tool enabled PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) .setInstructions("You are a helpful assistant that can search through uploaded files to answer questions. " + "When asked about information, use the file search tool to find relevant content from the files.") .setTools(Collections.singletonList(tool)); - agent = agentsClient.createAgentVersion("MyFileSearchAgent", agentDefinition); - System.out.printf("Agent created (id: %s, version: %s)\n", agent.getId(), agent.getVersion()); + agent = agentsClient.createAgentVersion("file-search-agent", agentDefinition); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); - AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + // Create a conversation and ask the agent conversation = conversationsClient.getConversationService().create(); - System.out.println("Created Conversation: " + conversation.id()); + System.out.println("Created conversation: " + conversation.id()); Response response = responsesClient.createWithAgentConversation(agentReference, conversation.id(), - ResponseCreateParams.builder().input("What is the largest planet in the Solar System?")); + ResponseCreateParams.builder() + .input("What is the largest planet in the Solar System?")); // Process and display the response - System.out.println("\n=== Agent Response ==="); for (ResponseOutputItem outputItem : response.output()) { - // Handle message output if (outputItem.message().isPresent()) { ResponseOutputMessage message = outputItem.message().get(); message.content().forEach(content -> { @@ -120,7 +124,6 @@ public static void main(String[] args) { }); } - // Handle file search tool call output if (outputItem.fileSearchCall().isPresent()) { ResponseFileSearchToolCall fileSearchCall = outputItem.fileSearchCall().get(); System.out.println("\n--- File Search Execution ---"); @@ -137,36 +140,31 @@ public static void main(String[] args) { }); } } - - System.out.println("\nResponse ID: " + response.id()); - System.out.println("Model Used: " + response.model()); } catch (Exception e) { System.err.println("Error: " + e.getMessage()); e.printStackTrace(); } finally { - // Cleanup created resources if (tempFile != null) { try { Files.deleteIfExists(tempFile); - } catch (Exception e) { - System.err.println("Failed to delete temp file: " + e.getMessage()); + } catch (Exception ignored) { + // best-effort cleanup } } if (conversation != null) { conversationsClient.getConversationService().delete(conversation.id()); - System.out.println("Conversation deleted successfully."); } if (agent != null) { agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); - System.out.println("Agent deleted successfully."); + System.out.println("Agent deleted"); } if (vectorStore != null) { openAIClient.vectorStores().delete(vectorStore.id()); - System.out.println("Vector store deleted successfully."); + System.out.println("Vector store deleted"); } if (uploadedFile != null) { openAIClient.files().delete(uploadedFile.id()); - System.out.println("File deleted successfully."); + System.out.println("File deleted"); } } } diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAgentAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java similarity index 71% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAgentAsync.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java index 37fd8b765ca9..e7641f789d4f 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAgentAsync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java @@ -5,7 +5,6 @@ import com.azure.ai.agents.AgentsAsyncClient; import com.azure.ai.agents.AgentsClientBuilder; -import com.azure.ai.agents.AgentsServiceVersion; import com.azure.ai.agents.ResponsesAsyncClient; import com.azure.ai.agents.models.AgentReference; import com.azure.ai.agents.models.AgentVersionDetails; @@ -27,56 +26,60 @@ import java.util.concurrent.atomic.AtomicReference; /** - * This sample demonstrates how to create an Azure AI Agent with the Function tool - * and use it to get responses that involve function calls using the async client. + * This sample demonstrates how to create an agent with a Function Calling tool + * that defines custom functions the agent can invoke, using the async client. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    */ -public class FunctionCallAgentAsync { - public static void main(String[] args) throws InterruptedException { - String endpoint = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_ENDPOINT"); - String model = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_MODEL"); +public class FunctionCallAsync { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); AgentsClientBuilder builder = new AgentsClientBuilder() .credential(new DefaultAzureCredentialBuilder().build()) - .serviceVersion(AgentsServiceVersion.getLatest()) .endpoint(endpoint); AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); - // For cleanup AtomicReference agentRef = new AtomicReference<>(); // Create a FunctionTool with parameters schema Map parameters = new HashMap(); parameters.put("type", BinaryData.fromString("\"object\"")); - parameters.put("properties", BinaryData.fromString("{\"location\": {\"type\": \"string\", \"description\": \"The city and state, e.g. San Francisco, CA\"}, \"unit\": {\"type\": \"string\", \"enum\": [\"celsius\", \"fahrenheit\"]}}")); + parameters.put("properties", BinaryData.fromString( + "{\"location\":{\"type\":\"string\",\"description\":\"The city and state, e.g. Seattle, WA\"}," + + "\"unit\":{\"type\":\"string\",\"enum\":[\"celsius\",\"fahrenheit\"]}}")); parameters.put("required", BinaryData.fromString("[\"location\", \"unit\"]")); parameters.put("additionalProperties", BinaryData.fromString("false")); FunctionTool tool = new FunctionTool("get_weather", parameters, true) .setDescription("Get the current weather in a given location"); - // Create the agent definition with Function tool enabled PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) .setInstructions("You are a helpful assistant that can get weather information. " + "When asked about the weather, use the get_weather function to retrieve weather data.") .setTools(Collections.singletonList(tool)); - agentsAsyncClient.createAgentVersion("MyAgent", agentDefinition) + agentsAsyncClient.createAgentVersion("function-call-agent", agentDefinition) .flatMap(agent -> { agentRef.set(agent); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); - AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); return responsesAsyncClient.createWithAgent(agentReference, - ResponseCreateParams.builder() - .input("What's the weather like in Seattle?")); + ResponseCreateParams.builder() + .input("What's the weather like in Seattle?")); }) .doOnNext(response -> { - // Process and display the response - System.out.println("\n=== Agent Response ==="); for (ResponseOutputItem outputItem : response.output()) { - // Handle message output if (outputItem.message().isPresent()) { ResponseOutputMessage message = outputItem.message().get(); message.content().forEach(content -> { @@ -86,7 +89,6 @@ public static void main(String[] args) throws InterruptedException { }); } - // Handle function tool call output if (outputItem.functionCall().isPresent()) { ResponseFunctionToolCall functionCall = outputItem.functionCall().get(); System.out.println("\n--- Function Tool Call ---"); @@ -96,23 +98,17 @@ public static void main(String[] args) throws InterruptedException { System.out.println("Status: " + functionCall.status()); } } - - System.out.println("\nResponse ID: " + response.id()); - System.out.println("Model Used: " + response.model()); }) - // Cleanup agent .then(Mono.defer(() -> { AgentVersionDetails agent = agentRef.get(); if (agent != null) { return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) - .doOnSuccess(v -> System.out.println("Agent deleted successfully.")); + .doOnSuccess(v -> System.out.println("Agent deleted")); } return Mono.empty(); })) - .doOnError(error -> { - System.err.println("Error: " + error.getMessage()); - error.printStackTrace(); - }).timeout(Duration.ofSeconds(30)) - .block(); + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(30)) + .block(); } } diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAgent.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallSync.java similarity index 73% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAgent.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallSync.java index d1f8b1bf7a58..155aaf36abe2 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAgent.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallSync.java @@ -5,7 +5,6 @@ import com.azure.ai.agents.AgentsClient; import com.azure.ai.agents.AgentsClientBuilder; -import com.azure.ai.agents.AgentsServiceVersion; import com.azure.ai.agents.ResponsesClient; import com.azure.ai.agents.models.AgentReference; import com.azure.ai.agents.models.AgentVersionDetails; @@ -25,17 +24,22 @@ import java.util.Map; /** - * This sample demonstrates how to create an Azure AI Agent with the Function tool - * and use it to get responses that involve function calls. + * This sample demonstrates how to create an agent with a Function Calling tool + * that defines custom functions the agent can invoke. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    */ -public class FunctionCallAgent { +public class FunctionCallSync { public static void main(String[] args) { - String endpoint = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_ENDPOINT"); - String model = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_MODEL"); + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); AgentsClientBuilder builder = new AgentsClientBuilder() .credential(new DefaultAzureCredentialBuilder().build()) - .serviceVersion(AgentsServiceVersion.getLatest()) .endpoint(endpoint); AgentsClient agentsClient = builder.buildAgentsClient(); @@ -47,7 +51,9 @@ public static void main(String[] args) { // Create a FunctionTool with parameters schema Map parameters = new HashMap(); parameters.put("type", BinaryData.fromString("\"object\"")); - parameters.put("properties", BinaryData.fromString("{\"location\": {\"type\": \"string\", \"description\": \"The city and state, e.g. San Francisco, CA\"}, \"unit\": {\"type\": \"string\", \"enum\": [\"celsius\", \"fahrenheit\"]}}")); + parameters.put("properties", BinaryData.fromString( + "{\"location\":{\"type\":\"string\",\"description\":\"The city and state, e.g. Seattle, WA\"}," + + "\"unit\":{\"type\":\"string\",\"enum\":[\"celsius\",\"fahrenheit\"]}}")); parameters.put("required", BinaryData.fromString("[\"location\", \"unit\"]")); parameters.put("additionalProperties", BinaryData.fromString("false")); @@ -60,18 +66,18 @@ public static void main(String[] args) { + "When asked about the weather, use the get_weather function to retrieve weather data.") .setTools(Collections.singletonList(tool)); - agent = agentsClient.createAgentVersion("MyAgent", agentDefinition); - System.out.printf("Agent created (id: %s, version: %s)\n", agent.getId(), agent.getVersion()); + agent = agentsClient.createAgentVersion("function-call-agent", agentDefinition); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); - AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); Response response = responsesClient.createWithAgent(agentReference, - ResponseCreateParams.builder().input("What's the weather like in Seattle?")); + ResponseCreateParams.builder() + .input("What's the weather like in Seattle?")); // Process and display the response - System.out.println("\n=== Agent Response ==="); for (ResponseOutputItem outputItem : response.output()) { - // Handle message output if (outputItem.message().isPresent()) { ResponseOutputMessage message = outputItem.message().get(); message.content().forEach(content -> { @@ -81,7 +87,6 @@ public static void main(String[] args) { }); } - // Handle function tool call output if (outputItem.functionCall().isPresent()) { ResponseFunctionToolCall functionCall = outputItem.functionCall().get(); System.out.println("\n--- Function Tool Call ---"); @@ -91,17 +96,10 @@ public static void main(String[] args) { System.out.println("Status: " + functionCall.status()); } } - - System.out.println("\nResponse ID: " + response.id()); - System.out.println("Model Used: " + response.model()); - } catch (Exception e) { - System.err.println("Error: " + e.getMessage()); - e.printStackTrace(); } finally { - // Cleanup agent if (agent != null) { agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); - System.out.println("Agent deleted successfully."); + System.out.println("Agent deleted"); } } } diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallingSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallingSample.java deleted file mode 100644 index e097df2e56b4..000000000000 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallingSample.java +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.ai.agents.tools; - -import com.azure.ai.agents.AgentsClient; -import com.azure.ai.agents.AgentsClientBuilder; -import com.azure.ai.agents.ResponsesClient; -import com.azure.ai.agents.models.AgentReference; -import com.azure.ai.agents.models.AgentVersionDetails; -import com.azure.ai.agents.models.FunctionTool; -import com.azure.ai.agents.models.PromptAgentDefinition; -import com.azure.core.util.BinaryData; -import com.azure.core.util.Configuration; -import com.azure.identity.DefaultAzureCredentialBuilder; -import com.openai.models.responses.Response; -import com.openai.models.responses.ResponseCreateParams; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -/** - * This sample demonstrates how to create an agent with a Function Calling tool - * that defines custom functions the agent can invoke. - * - *

    Before running the sample, set these environment variables:

    - *
      - *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • - *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • - *
    - */ -public class FunctionCallingSample { - public static void main(String[] args) { - String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); - String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); - - AgentsClientBuilder builder = new AgentsClientBuilder() - .credential(new DefaultAzureCredentialBuilder().build()) - .endpoint(endpoint); - - AgentsClient agentsClient = builder.buildAgentsClient(); - ResponsesClient responsesClient = builder.buildResponsesClient(); - - // Define function parameters - Map parameters = new HashMap<>(); - parameters.put("type", BinaryData.fromString("\"object\"")); - parameters.put("properties", BinaryData.fromString( - "{\"location\":{\"type\":\"string\",\"description\":\"The city and state, e.g. Seattle, WA\"}," - + "\"unit\":{\"type\":\"string\",\"enum\":[\"celsius\",\"fahrenheit\"]}}")); - parameters.put("required", BinaryData.fromString("[\"location\"]")); - - FunctionTool weatherFunction = new FunctionTool("get_weather", parameters, true); - - // Create agent with function tool - PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) - .setInstructions("You are a weather assistant. Use the get_weather function to retrieve weather information.") - .setTools(Arrays.asList(weatherFunction)); - - AgentVersionDetails agent = agentsClient.createAgentVersion("function-calling-agent", agentDefinition); - System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); - - try { - // Create a response - the agent will call the function - AgentReference agentReference = new AgentReference(agent.getName()) - .setVersion(agent.getVersion()); - - Response response = responsesClient.createWithAgent( - agentReference, - ResponseCreateParams.builder() - .input("What is the weather in Seattle?")); - - System.out.println("Response: " + response.output()); - } finally { - // Clean up - agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); - } - } -} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ImageGenerationAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ImageGenerationAsync.java new file mode 100644 index 000000000000..bbe62710826b --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ImageGenerationAsync.java @@ -0,0 +1,87 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsAsyncClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ResponsesAsyncClient; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.ImageGenTool; +import com.azure.ai.agents.models.ImageGenToolModel; +import com.azure.ai.agents.models.ImageGenToolQuality; +import com.azure.ai.agents.models.ImageGenToolSize; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.ResponseCreateParams; +import java.time.Duration; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicReference; +import reactor.core.publisher.Mono; + +/** + * This sample demonstrates (using the async client) how to create an agent with the Image Generation tool + * to generate images from text descriptions. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    • IMAGE_GENERATION_MODEL_DEPLOYMENT_NAME - The image generation model deployment name.
    • + *
    + */ +public class ImageGenerationAsync { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String imageModel = Configuration.getGlobalConfiguration().get("IMAGE_GENERATION_MODEL_DEPLOYMENT_NAME"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); + ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); + + AtomicReference agentRef = new AtomicReference<>(); + + // Create image generation tool with model, quality, and size + ImageGenTool imageGenTool = new ImageGenTool() + .setModel(ImageGenToolModel.fromString(imageModel)) + .setQuality(ImageGenToolQuality.LOW) + .setSize(ImageGenToolSize.fromString("1024x1024")); + // Create agent with image generation tool + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a creative assistant that can generate images based on descriptions.") + .setTools(Collections.singletonList(imageGenTool)); + + agentsAsyncClient.createAgentVersion("image-gen-agent", agentDefinition) + .flatMap(agent -> { + agentRef.set(agent); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + return responsesAsyncClient.createWithAgent(agentReference, + ResponseCreateParams.builder() + .input("Generate an image of a sunset over a mountain range")); + }) + .doOnNext(response -> { + System.out.println("Response: " + response.output()); + }) + .then(Mono.defer(() -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) + .doOnSuccess(v -> System.out.println("Agent deleted")); + } + return Mono.empty(); + })) + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(300)) + .block(); + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ImageGenerationSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ImageGenerationSync.java similarity index 99% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ImageGenerationSample.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ImageGenerationSync.java index ceb7f342ddcd..3c21be19a30e 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ImageGenerationSample.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ImageGenerationSync.java @@ -31,7 +31,7 @@ *
  • IMAGE_GENERATION_MODEL_DEPLOYMENT_NAME - The image generation model deployment name.
  • * */ -public class ImageGenerationSample { +public class ImageGenerationSync { public static void main(String[] args) { String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAgentAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java similarity index 69% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAgentAsync.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java index e52c4febd3e0..57da352a175c 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAgentAsync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java @@ -5,7 +5,6 @@ import com.azure.ai.agents.AgentsAsyncClient; import com.azure.ai.agents.AgentsClientBuilder; -import com.azure.ai.agents.AgentsServiceVersion; import com.azure.ai.agents.ResponsesAsyncClient; import com.azure.ai.agents.models.AgentReference; import com.azure.ai.agents.models.AgentVersionDetails; @@ -23,52 +22,53 @@ import java.util.concurrent.atomic.AtomicReference; /** - * This sample demonstrates how to create an Azure AI Agent with the MCP (Model Context Protocol) tool - * and use it to get responses that involve MCP server calls using the async client. + * This sample demonstrates how to create an agent with a Model Context Protocol (MCP) tool + * to connect to external MCP servers, using the async client. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    */ -public class McpAgentAsync { - public static void main(String[] args) throws InterruptedException { - String endpoint = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_ENDPOINT"); - String model = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_MODEL"); +public class McpAsync { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); AgentsClientBuilder builder = new AgentsClientBuilder() .credential(new DefaultAzureCredentialBuilder().build()) - .serviceVersion(AgentsServiceVersion.getLatest()) .endpoint(endpoint); AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); - // For cleanup AtomicReference agentRef = new AtomicReference<>(); - // Create an MCPTool that connects to an MCP server via project connection + // Create an MCP tool that connects to a remote MCP server McpTool tool = new McpTool("my-mcp-server") - .setServerUrl("https://example.mcp.server/mcp") // Add your MCP server URL here + .setServerUrl("https://example.mcp.server/mcp") .setServerDescription("An MCP server that provides additional tools"); - // Create the agent definition with MCP tool enabled PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) .setInstructions("You are a helpful assistant that can use MCP tools to access external services. " + "When asked to perform tasks, use the available MCP tools to help the user.") .setTools(Collections.singletonList(tool)); - agentsAsyncClient.createAgentVersion("MyAgent", agentDefinition) + agentsAsyncClient.createAgentVersion("mcp-agent", agentDefinition) .flatMap(agent -> { agentRef.set(agent); - System.out.printf("Agent created (id: %s, version: %s)\n", agent.getId(), agent.getVersion()); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); - AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); return responsesAsyncClient.createWithAgent(agentReference, - ResponseCreateParams.builder() - .input("What tools are available from the MCP server?")); + ResponseCreateParams.builder() + .input("What tools are available from the MCP server?")); }) .doOnNext(response -> { - // Process and display the response - System.out.println("\n=== Agent Response ==="); for (ResponseOutputItem outputItem : response.output()) { - // Handle message output if (outputItem.message().isPresent()) { ResponseOutputMessage message = outputItem.message().get(); message.content().forEach(content -> { @@ -78,7 +78,6 @@ public static void main(String[] args) throws InterruptedException { }); } - // Handle MCP tool call output if (outputItem.mcpCall().isPresent()) { ResponseOutputItem.McpCall mcpCall = outputItem.mcpCall().get(); System.out.println("\n--- MCP Tool Call ---"); @@ -91,23 +90,17 @@ public static void main(String[] args) throws InterruptedException { mcpCall.error().ifPresent(error -> System.out.println("Error: " + error)); } } - - System.out.println("\nResponse ID: " + response.id()); - System.out.println("Model Used: " + response.model()); }) - // Cleanup agent .then(Mono.defer(() -> { AgentVersionDetails agent = agentRef.get(); if (agent != null) { return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) - .doOnSuccess(v -> System.out.println("Agent deleted successfully.")); + .doOnSuccess(v -> System.out.println("Agent deleted")); } return Mono.empty(); })) - .doOnError(error -> { - System.err.println("Error: " + error.getMessage()); - error.printStackTrace(); - }).timeout(Duration.ofSeconds(300)) - .block(); + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(300)) + .block(); } } diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAgent.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpSync.java similarity index 72% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAgent.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpSync.java index 00da3cbca9bc..f94d02aeb0f7 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAgent.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpSync.java @@ -5,7 +5,6 @@ import com.azure.ai.agents.AgentsClient; import com.azure.ai.agents.AgentsClientBuilder; -import com.azure.ai.agents.AgentsServiceVersion; import com.azure.ai.agents.ResponsesClient; import com.azure.ai.agents.models.AgentReference; import com.azure.ai.agents.models.AgentVersionDetails; @@ -21,17 +20,22 @@ import java.util.Collections; /** - * This sample demonstrates how to create an Azure AI Agent with the MCP (Model Context Protocol) tool - * and use it to get responses that involve MCP server calls. + * This sample demonstrates how to create an agent with a Model Context Protocol (MCP) tool + * to connect to external MCP servers. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    */ -public class McpAgent { +public class McpSync { public static void main(String[] args) { - String endpoint = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_ENDPOINT"); - String model = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_MODEL"); + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); AgentsClientBuilder builder = new AgentsClientBuilder() .credential(new DefaultAzureCredentialBuilder().build()) - .serviceVersion(AgentsServiceVersion.getLatest()) .endpoint(endpoint); AgentsClient agentsClient = builder.buildAgentsClient(); @@ -40,9 +44,9 @@ public static void main(String[] args) { AgentVersionDetails agent = null; try { - // Create an MCPTool that connects to a remote MCP server + // Create an MCP tool that connects to a remote MCP server McpTool tool = new McpTool("my-mcp-server") - .setServerUrl("https://example.mcp.server/mcp") // Add your MCP server URL here + .setServerUrl("https://example.mcp.server/mcp") .setServerDescription("An MCP server that provides additional tools"); // Create the agent definition with MCP tool enabled @@ -51,18 +55,18 @@ public static void main(String[] args) { + "When asked to perform tasks, use the available MCP tools to help the user.") .setTools(Collections.singletonList(tool)); - agent = agentsClient.createAgentVersion("MyAgent", agentDefinition); - System.out.printf("Agent created (id: %s, version: %s)\n", agent.getId(), agent.getVersion()); + agent = agentsClient.createAgentVersion("mcp-agent", agentDefinition); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); - AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); Response response = responsesClient.createWithAgent(agentReference, - ResponseCreateParams.builder().input("What tools are available from the MCP server?")); + ResponseCreateParams.builder() + .input("What tools are available from the MCP server?")); // Process and display the response - System.out.println("\n=== Agent Response ==="); for (ResponseOutputItem outputItem : response.output()) { - // Handle message output if (outputItem.message().isPresent()) { ResponseOutputMessage message = outputItem.message().get(); message.content().forEach(content -> { @@ -72,7 +76,6 @@ public static void main(String[] args) { }); } - // Handle MCP tool call output if (outputItem.mcpCall().isPresent()) { ResponseOutputItem.McpCall mcpCall = outputItem.mcpCall().get(); System.out.println("\n--- MCP Tool Call ---"); @@ -85,17 +88,10 @@ public static void main(String[] args) { mcpCall.error().ifPresent(error -> System.out.println("Error: " + error)); } } - - System.out.println("\nResponse ID: " + response.id()); - System.out.println("Model Used: " + response.model()); - } catch (Exception e) { - System.err.println("Error: " + e.getMessage()); - e.printStackTrace(); } finally { - // Cleanup agent if (agent != null) { agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); - System.out.println("Agent deleted successfully."); + System.out.println("Agent deleted"); } } } diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpToolSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpToolSample.java deleted file mode 100644 index 7b673380eb9a..000000000000 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpToolSample.java +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.ai.agents.tools; - -import com.azure.ai.agents.AgentsClient; -import com.azure.ai.agents.AgentsClientBuilder; -import com.azure.ai.agents.ResponsesClient; -import com.azure.ai.agents.models.AgentReference; -import com.azure.ai.agents.models.AgentVersionDetails; -import com.azure.ai.agents.models.McpTool; -import com.azure.ai.agents.models.PromptAgentDefinition; -import com.azure.core.util.BinaryData; -import com.azure.core.util.Configuration; -import com.azure.identity.DefaultAzureCredentialBuilder; -import com.openai.models.responses.Response; -import com.openai.models.responses.ResponseCreateParams; - -import java.util.Collections; - -/** - * This sample demonstrates how to create an agent with a Model Context Protocol (MCP) tool - * to connect to external MCP servers. - * - *

    Before running the sample, set these environment variables:

    - *
      - *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • - *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • - *
    • MCP_PROJECT_CONNECTION_ID - The MCP project connection ID.
    • - *
    - */ -public class McpToolSample { - public static void main(String[] args) { - String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); - String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); - String mcpConnectionId = Configuration.getGlobalConfiguration().get("MCP_PROJECT_CONNECTION_ID"); - - AgentsClientBuilder builder = new AgentsClientBuilder() - .credential(new DefaultAzureCredentialBuilder().build()) - .endpoint(endpoint); - - AgentsClient agentsClient = builder.buildAgentsClient(); - ResponsesClient responsesClient = builder.buildResponsesClient(); - - // Create MCP tool with server label, URL, connection, and approval mode - McpTool mcpTool = new McpTool("api-specs") - .setServerUrl("https://gitmcp.io/Azure/azure-rest-api-specs") - .setProjectConnectionId(mcpConnectionId) - .setRequireApproval(BinaryData.fromObject("always")); - - // Create agent with MCP tool - PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) - .setInstructions("You are a helpful assistant that can use MCP tools.") - .setTools(Collections.singletonList(mcpTool)); - - AgentVersionDetails agent = agentsClient.createAgentVersion("mcp-agent", agentDefinition); - System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); - - try { - // Create a response - AgentReference agentReference = new AgentReference(agent.getName()) - .setVersion(agent.getVersion()); - - Response response = responsesClient.createWithAgent( - agentReference, - ResponseCreateParams.builder() - .input("Summarize the Azure REST API specifications")); - - System.out.println("Response: " + response.output()); - } finally { - // Clean up - agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); - } - } -} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionAsync.java new file mode 100644 index 000000000000..c54eb6ca6e03 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionAsync.java @@ -0,0 +1,121 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsAsyncClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ResponsesAsyncClient; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.McpTool; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.BinaryData; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.Response; +import com.openai.models.responses.ResponseCreateParams; +import com.openai.models.responses.ResponseInputItem; +import com.openai.models.responses.ResponseOutputItem; +import reactor.core.publisher.Mono; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +/** + * This sample demonstrates (using the async client) how to create an agent with an MCP tool + * using a project connection for authentication, and how to handle MCP approval requests. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    • MCP_PROJECT_CONNECTION_ID - The MCP project connection ID.
    • + *
    + */ +public class McpWithConnectionAsync { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String mcpConnectionId = Configuration.getGlobalConfiguration().get("MCP_PROJECT_CONNECTION_ID"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); + ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); + + AtomicReference agentRef = new AtomicReference<>(); + + McpTool mcpTool = new McpTool("api-specs") + .setServerUrl("https://api.githubcopilot.com/mcp") + .setProjectConnectionId(mcpConnectionId) + .setRequireApproval(BinaryData.fromObject("always")); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("Use MCP tools as needed") + .setTools(Collections.singletonList(mcpTool)); + + agentsAsyncClient.createAgentVersion("mcp-connection-agent", agentDefinition) + .flatMap(agent -> { + agentRef.set(agent); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + return responsesAsyncClient.createWithAgent(agentReference, + ResponseCreateParams.builder() + .input("What is my username in Github profile?")); + }) + .flatMap(response -> { + AgentVersionDetails agent = agentRef.get(); + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + // Process MCP approval requests + List approvals = new ArrayList<>(); + for (ResponseOutputItem item : response.output()) { + if (item.isMcpApprovalRequest()) { + ResponseOutputItem.McpApprovalRequest request = item.asMcpApprovalRequest(); + System.out.printf("MCP approval requested: server=%s, id=%s%n", + request.serverLabel(), request.id()); + + approvals.add(ResponseInputItem.ofMcpApprovalResponse( + ResponseInputItem.McpApprovalResponse.builder() + .approvalRequestId(request.id()) + .approve(true) + .build())); + } + } + + if (!approvals.isEmpty()) { + System.out.println("Sending " + approvals.size() + " approval(s)..."); + return responsesAsyncClient.createWithAgent(agentReference, + ResponseCreateParams.builder() + .inputOfResponse(approvals) + .previousResponseId(response.id())); + } + + return Mono.just(response); + }) + .doOnNext(response -> { + System.out.println("Response: " + response.output()); + }) + .then(Mono.defer(() -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) + .doOnSuccess(v -> System.out.println("Agent deleted")); + } + return Mono.empty(); + })) + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(300)) + .block(); + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSync.java similarity index 99% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSample.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSync.java index 4b22e5547ac7..6e9d75f098f0 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSample.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSync.java @@ -39,7 +39,7 @@ * with key "Authorization" and value "Bearer <your GitHub PAT token>"). * */ -public class McpWithConnectionSample { +public class McpWithConnectionSync { public static void main(String[] args) { String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchAsync.java new file mode 100644 index 000000000000..39c575fabc28 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchAsync.java @@ -0,0 +1,151 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsAsyncClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ConversationsAsyncClient; +import com.azure.ai.agents.MemoryStoresClient; +import com.azure.ai.agents.ResponsesAsyncClient; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.MemorySearchPreviewTool; +import com.azure.ai.agents.models.MemoryStoreDefaultDefinition; +import com.azure.ai.agents.models.MemoryStoreDefaultOptions; +import com.azure.ai.agents.models.MemoryStoreDetails; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.exception.ResourceNotFoundException; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.Response; +import com.openai.models.responses.ResponseCreateParams; +import reactor.core.publisher.Mono; + +import java.time.Duration; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicReference; + +/** + * This sample demonstrates (using the async client) how to integrate memory into a prompt agent + * using the Memory Search tool to retrieve relevant past user messages. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    • AZURE_AI_CHAT_MODEL_DEPLOYMENT_NAME - The chat model deployment name for memory.
    • + *
    • AZURE_AI_EMBEDDING_MODEL_DEPLOYMENT_NAME - The embedding model deployment name for memory.
    • + *
    + */ +public class MemorySearchAsync { + private static final long MEMORY_WRITE_DELAY_SECONDS = 60; + + public static void main(String[] args) throws Exception { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String chatModel = Configuration.getGlobalConfiguration().get("AZURE_AI_CHAT_MODEL_DEPLOYMENT_NAME"); + String embeddingModel = Configuration.getGlobalConfiguration().get("AZURE_AI_EMBEDDING_MODEL_DEPLOYMENT_NAME"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); + ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); + ConversationsAsyncClient conversationsAsyncClient = builder.buildConversationsAsyncClient(); + // Memory store operations use sync client for setup/teardown + MemoryStoresClient memoryStoresClient = builder.buildMemoryStoresClient(); + + String memoryStoreName = "my_memory_store"; + String scope = "user_123"; + + AtomicReference agentRef = new AtomicReference<>(); + AtomicReference firstConvRef = new AtomicReference<>(); + AtomicReference secondConvRef = new AtomicReference<>(); + + // Setup: delete memory store if it exists, then create it (sync) + try { + memoryStoresClient.deleteMemoryStore(memoryStoreName); + } catch (ResourceNotFoundException ignored) { + // no-op + } + + MemoryStoreDefaultDefinition definition = new MemoryStoreDefaultDefinition(chatModel, embeddingModel) + .setOptions(new MemoryStoreDefaultOptions(true, true)); + MemoryStoreDetails memoryStore = memoryStoresClient.createMemoryStore( + memoryStoreName, definition, "Example memory store for conversations", null); + System.out.printf("Created memory store: %s (%s)%n", memoryStore.getName(), memoryStore.getId()); + + MemorySearchPreviewTool tool = new MemorySearchPreviewTool(memoryStore.getName(), scope) + .setUpdateDelaySeconds(1); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a helpful assistant that answers general questions.") + .setTools(Collections.singletonList(tool)); + + agentsAsyncClient.createAgentVersion("memory-search-agent", agentDefinition) + .flatMap(agent -> { + agentRef.set(agent); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + // First conversation: teach a preference + return Mono.fromFuture(conversationsAsyncClient.getConversationServiceAsync().create()) + .flatMap(conv -> { + firstConvRef.set(conv.id()); + return responsesAsyncClient.createWithAgentConversation( + agentReference, conv.id(), + ResponseCreateParams.builder().input("I prefer dark roast coffee")); + }); + }) + .doOnNext(response -> System.out.println("First response received")) + .delayElement(Duration.ofSeconds(MEMORY_WRITE_DELAY_SECONDS)) + .flatMap(ignored -> { + AgentVersionDetails agent = agentRef.get(); + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + // Second conversation: test memory recall + return Mono.fromFuture(conversationsAsyncClient.getConversationServiceAsync().create()) + .flatMap(conv -> { + secondConvRef.set(conv.id()); + return responsesAsyncClient.createWithAgentConversation( + agentReference, conv.id(), + ResponseCreateParams.builder().input("Please order my usual coffee")); + }); + }) + .doOnNext(response -> System.out.println("Response: " + response.output())) + .doFinally(signal -> { + // Cleanup (sync) + try { + String c1 = firstConvRef.get(); + if (c1 != null) { + conversationsAsyncClient.getConversationServiceAsync().delete(c1); + } + String c2 = secondConvRef.get(); + if (c2 != null) { + conversationsAsyncClient.getConversationServiceAsync().delete(c2); + } + } catch (Exception ignored) { + // best-effort + } + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()).block(); + System.out.println("Agent deleted"); + } + try { + memoryStoresClient.deleteMemoryStore(memoryStoreName); + System.out.println("Memory store deleted"); + } catch (ResourceNotFoundException ignored) { + // no-op + } + }) + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(600)) + .block(); + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSync.java similarity index 99% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSample.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSync.java index c55fcb6d6d88..5650439a9dee 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSample.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSync.java @@ -37,7 +37,7 @@ *
  • AZURE_AI_EMBEDDING_MODEL_DEPLOYMENT_NAME - The embedding model deployment name for memory.
  • * */ -public class MemorySearchSample { +public class MemorySearchSync { private static final long MEMORY_WRITE_DELAY_SECONDS = 60; public static void main(String[] args) { diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiAsync.java new file mode 100644 index 000000000000..e0dbe24c73ba --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiAsync.java @@ -0,0 +1,90 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsAsyncClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ResponsesAsyncClient; +import com.azure.ai.agents.SampleUtils; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.OpenApiAnonymousAuthDetails; +import com.azure.ai.agents.models.OpenApiFunctionDefinition; +import com.azure.ai.agents.models.OpenApiTool; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.BinaryData; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.ResponseCreateParams; +import reactor.core.publisher.Mono; + +import java.time.Duration; +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +/** + * This sample demonstrates (using the async client) how to create an agent with an OpenAPI tool + * for calling external REST APIs defined by an OpenAPI specification. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    + */ +public class OpenApiAsync { + public static void main(String[] args) throws Exception { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); + ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); + + AtomicReference agentRef = new AtomicReference<>(); + + Map spec = OpenApiFunctionDefinition.readSpecFromFile( + SampleUtils.getResourcePath("assets/httpbin_openapi.json")); + + OpenApiTool openApiTool = new OpenApiTool( + new OpenApiFunctionDefinition("httpbin_get", spec, + new OpenApiAnonymousAuthDetails()) + .setDescription("Retrieve weather information for a location.")); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a helpful assistant. Use the OpenAPI tool when asked to call an API.") + .setTools(Collections.singletonList(openApiTool)); + + agentsAsyncClient.createAgentVersion("openapi-agent", agentDefinition) + .flatMap(agent -> { + agentRef.set(agent); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + return responsesAsyncClient.createWithAgent(agentReference, + ResponseCreateParams.builder() + .input("Call the API and tell me what it returns.")); + }) + .doOnNext(response -> { + System.out.println("Response: " + response.output()); + }) + .then(Mono.defer(() -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) + .doOnSuccess(v -> System.out.println("Agent deleted")); + } + return Mono.empty(); + })) + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(300)) + .block(); + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSync.java similarity index 99% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSync.java index 1823d374c882..55ee12172ecc 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSample.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSync.java @@ -38,7 +38,7 @@ * *

    Also place an OpenAPI spec JSON file at {@code src/samples/resources/assets/httpbin_openapi.json}.

    */ -public class OpenApiSample { +public class OpenApiSync { public static void main(String[] args) throws Exception { String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionAsync.java new file mode 100644 index 000000000000..39c9456bf9e8 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionAsync.java @@ -0,0 +1,96 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsAsyncClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ResponsesAsyncClient; +import com.azure.ai.agents.SampleUtils; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.OpenApiFunctionDefinition; +import com.azure.ai.agents.models.OpenApiProjectConnectionAuthDetails; +import com.azure.ai.agents.models.OpenApiProjectConnectionSecurityScheme; +import com.azure.ai.agents.models.OpenApiTool; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.BinaryData; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.ResponseCreateParams; +import reactor.core.publisher.Mono; + +import java.time.Duration; +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +/** + * This sample demonstrates (using the async client) how to create an agent with an OpenAPI tool + * using project connection authentication. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    • OPENAPI_PROJECT_CONNECTION_ID - The OpenAPI project connection ID.
    • + *
    + */ +public class OpenApiWithConnectionAsync { + public static void main(String[] args) throws Exception { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String connectionId = Configuration.getGlobalConfiguration().get("OPENAPI_PROJECT_CONNECTION_ID"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); + ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); + + AtomicReference agentRef = new AtomicReference<>(); + + Map spec = OpenApiFunctionDefinition.readSpecFromFile( + SampleUtils.getResourcePath("assets/httpbin_openapi.json")); + + OpenApiTool openApiTool = new OpenApiTool( + new OpenApiFunctionDefinition( + "httpbin_get", + spec, + new OpenApiProjectConnectionAuthDetails( + new OpenApiProjectConnectionSecurityScheme(connectionId))) + .setDescription("Get request metadata from an OpenAPI endpoint.")); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a helpful assistant.") + .setTools(Collections.singletonList(openApiTool)); + + agentsAsyncClient.createAgentVersion("openapi-connection-agent", agentDefinition) + .flatMap(agent -> { + agentRef.set(agent); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + return responsesAsyncClient.createWithAgent(agentReference, + ResponseCreateParams.builder() + .input("Call the API and summarize the returned URL and origin.")); + }) + .doOnNext(response -> { + System.out.println("Response: " + response.output()); + }) + .then(Mono.defer(() -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) + .doOnSuccess(v -> System.out.println("Agent deleted")); + } + return Mono.empty(); + })) + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(300)) + .block(); + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSync.java similarity index 98% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSample.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSync.java index 454ee2118391..049af351f829 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSample.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSync.java @@ -40,7 +40,7 @@ * {@code src/samples/resources/assets/httpbin_openapi.json}. Replace it with your * own spec to call a different API.

    */ -public class OpenApiWithConnectionSample { +public class OpenApiWithConnectionSync { public static void main(String[] args) throws Exception { String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingAsync.java new file mode 100644 index 000000000000..660e57cdfb45 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingAsync.java @@ -0,0 +1,89 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents.tools; + +import com.azure.ai.agents.AgentsAsyncClient; +import com.azure.ai.agents.AgentsClientBuilder; +import com.azure.ai.agents.ResponsesAsyncClient; +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.ai.agents.models.SharepointGroundingToolParameters; +import com.azure.ai.agents.models.SharepointPreviewTool; +import com.azure.ai.agents.models.ToolProjectConnection; +import com.azure.core.util.Configuration; +import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.ResponseCreateParams; +import java.time.Duration; +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicReference; +import reactor.core.publisher.Mono; + +/** + * This sample demonstrates (using the async client) how to create an agent with the SharePoint Grounding tool + * to search through SharePoint documents. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    • SHAREPOINT_PROJECT_CONNECTION_ID - The SharePoint connection ID.
    • + *
    + */ +public class SharePointGroundingAsync { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); + String sharepointConnectionId = Configuration.getGlobalConfiguration().get("SHAREPOINT_PROJECT_CONNECTION_ID"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); + ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); + + AtomicReference agentRef = new AtomicReference<>(); + + // Create SharePoint grounding tool with connection configuration + SharepointPreviewTool sharepointTool = new SharepointPreviewTool( + new SharepointGroundingToolParameters() + .setProjectConnections(Arrays.asList( + new ToolProjectConnection(sharepointConnectionId) + )) + ); + // Create agent with SharePoint tool + PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) + .setInstructions("You are a helpful assistant that can search through SharePoint documents.") + .setTools(Collections.singletonList(sharepointTool)); + + agentsAsyncClient.createAgentVersion("sharepoint-agent", agentDefinition) + .flatMap(agent -> { + agentRef.set(agent); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + return responsesAsyncClient.createWithAgent(agentReference, + ResponseCreateParams.builder() + .input("Find the latest project documentation in SharePoint")); + }) + .doOnNext(response -> { + System.out.println("Response: " + response.output()); + }) + .then(Mono.defer(() -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) + .doOnSuccess(v -> System.out.println("Agent deleted")); + } + return Mono.empty(); + })) + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(300)) + .block(); + } +} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingSync.java similarity index 98% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingSample.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingSync.java index 909124ec6bed..570472c2da90 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingSample.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingSync.java @@ -31,7 +31,7 @@ *
  • SHAREPOINT_PROJECT_CONNECTION_ID - The SharePoint connection ID.
  • * */ -public class SharePointGroundingSample { +public class SharePointGroundingSync { public static void main(String[] args) { String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchAgentAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchAsync.java similarity index 65% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchAgentAsync.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchAsync.java index cb9d6680914b..5923bfdd4e0f 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchAgentAsync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchAsync.java @@ -5,12 +5,11 @@ import com.azure.ai.agents.AgentsAsyncClient; import com.azure.ai.agents.AgentsClientBuilder; -import com.azure.ai.agents.AgentsServiceVersion; import com.azure.ai.agents.ResponsesAsyncClient; import com.azure.ai.agents.models.AgentReference; import com.azure.ai.agents.models.AgentVersionDetails; -import com.azure.ai.agents.models.WebSearchTool; import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.ai.agents.models.WebSearchPreviewTool; import com.azure.core.util.Configuration; import com.azure.identity.DefaultAzureCredentialBuilder; import com.openai.models.responses.ResponseCreateParams; @@ -23,48 +22,51 @@ import java.util.concurrent.atomic.AtomicReference; /** - * This sample demonstrates how to create an Azure AI Agent with the Code Interpreter tool - * and use it to get responses that involve code execution using the async client. + * This sample demonstrates how to create an agent with the Web Search tool + * to search the web for current information, using the async client. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    */ -public class WebSearchAgentAsync { - public static void main(String[] args) throws InterruptedException { - String endpoint = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_ENDPOINT"); - String model = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_MODEL"); +public class WebSearchAsync { + public static void main(String[] args) { + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); AgentsClientBuilder builder = new AgentsClientBuilder() .credential(new DefaultAzureCredentialBuilder().build()) - .serviceVersion(AgentsServiceVersion.getLatest()) .endpoint(endpoint); AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient(); ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient(); - // For cleanup AtomicReference agentRef = new AtomicReference<>(); - // Create a WebSearchTool - WebSearchTool tool = new WebSearchTool(); + // Create a WebSearchPreviewTool + WebSearchPreviewTool tool = new WebSearchPreviewTool(); - // Create the agent definition with Web Search tool enabled PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) .setInstructions("You are a helpful assistant that can perform web searches to find information. " + "When asked to find information, use the web search tool to gather relevant data.") .setTools(Collections.singletonList(tool)); - agentsAsyncClient.createAgentVersion("MyAgent", agentDefinition) + agentsAsyncClient.createAgentVersion("web-search-agent", agentDefinition) .flatMap(agent -> { agentRef.set(agent); - AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); return responsesAsyncClient.createWithAgent(agentReference, - ResponseCreateParams.builder() - .input("What are the latest developments in AI technology?")); + ResponseCreateParams.builder() + .input("What are the latest trends in renewable energy?")); }) .doOnNext(response -> { - // Process and display the response - System.out.println("\n=== Agent Response ==="); for (ResponseOutputItem outputItem : response.output()) { - // Handle message output if (outputItem.message().isPresent()) { ResponseOutputMessage message = outputItem.message().get(); message.content().forEach(content -> { @@ -74,23 +76,17 @@ public static void main(String[] args) throws InterruptedException { }); } } - - System.out.println("\nResponse ID: " + response.id()); - System.out.println("Model Used: " + response.model()); }) - // Cleanup agent .then(Mono.defer(() -> { AgentVersionDetails agent = agentRef.get(); if (agent != null) { return agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()) - .doOnSuccess(v -> System.out.println("Agent deleted successfully.")); + .doOnSuccess(v -> System.out.println("Agent deleted")); } return Mono.empty(); })) - .doOnError(error -> { - System.err.println("Error: " + error.getMessage()); - error.printStackTrace(); - }).timeout(Duration.ofSeconds(30)) - .block(); + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .timeout(Duration.ofSeconds(30)) + .block(); } } diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchSample.java deleted file mode 100644 index e471d9fba608..000000000000 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchSample.java +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.ai.agents.tools; - -import com.azure.ai.agents.AgentsClient; -import com.azure.ai.agents.AgentsClientBuilder; -import com.azure.ai.agents.ResponsesClient; -import com.azure.ai.agents.models.AgentReference; -import com.azure.ai.agents.models.AgentVersionDetails; -import com.azure.ai.agents.models.PromptAgentDefinition; -import com.azure.ai.agents.models.WebSearchPreviewTool; -import com.azure.core.util.Configuration; -import com.azure.identity.DefaultAzureCredentialBuilder; -import com.openai.models.responses.Response; -import com.openai.models.responses.ResponseCreateParams; - -import java.util.Collections; - -/** - * This sample demonstrates how to create an agent with the Web Search tool - * to search the web for current information. - * - *

    Before running the sample, set these environment variables:

    - *
      - *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • - *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • - *
    - */ -public class WebSearchSample { - public static void main(String[] args) { - String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); - String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); - - AgentsClientBuilder builder = new AgentsClientBuilder() - .credential(new DefaultAzureCredentialBuilder().build()) - .endpoint(endpoint); - - AgentsClient agentsClient = builder.buildAgentsClient(); - ResponsesClient responsesClient = builder.buildResponsesClient(); - - // Create web search tool - WebSearchPreviewTool webSearchTool = new WebSearchPreviewTool(); - - // Create agent with web search tool - PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) - .setInstructions("You are a helpful assistant that can search the web for current information.") - .setTools(Collections.singletonList(webSearchTool)); - - AgentVersionDetails agent = agentsClient.createAgentVersion("web-search-agent", agentDefinition); - System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); - - try { - // Create a response - AgentReference agentReference = new AgentReference(agent.getName()) - .setVersion(agent.getVersion()); - - Response response = responsesClient.createWithAgent( - agentReference, - ResponseCreateParams.builder() - .input("What are the latest trends in renewable energy?")); - - System.out.println("Response: " + response.output()); - } finally { - // Clean up - agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); - } - } -} diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchAgent.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchSync.java similarity index 67% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchAgent.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchSync.java index bc56369beaee..c6bb1dc4eaa3 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchAgent.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchSync.java @@ -5,12 +5,11 @@ import com.azure.ai.agents.AgentsClient; import com.azure.ai.agents.AgentsClientBuilder; -import com.azure.ai.agents.AgentsServiceVersion; import com.azure.ai.agents.ResponsesClient; import com.azure.ai.agents.models.AgentReference; import com.azure.ai.agents.models.AgentVersionDetails; -import com.azure.ai.agents.models.WebSearchTool; import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.ai.agents.models.WebSearchPreviewTool; import com.azure.core.util.Configuration; import com.azure.identity.DefaultAzureCredentialBuilder; import com.openai.models.responses.Response; @@ -21,17 +20,22 @@ import java.util.Collections; /** - * This sample demonstrates how to create an Azure AI Agent with the Web Search tool - * and use it to get responses that involve web search. + * This sample demonstrates how to create an agent with the Web Search tool + * to search the web for current information. + * + *

    Before running the sample, set these environment variables:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    */ -public class WebSearchAgent { +public class WebSearchSync { public static void main(String[] args) { - String endpoint = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_ENDPOINT"); - String model = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_MODEL"); + String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"); + String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_DEPLOYMENT_NAME"); AgentsClientBuilder builder = new AgentsClientBuilder() .credential(new DefaultAzureCredentialBuilder().build()) - .serviceVersion(AgentsServiceVersion.getLatest()) .endpoint(endpoint); AgentsClient agentsClient = builder.buildAgentsClient(); @@ -40,8 +44,8 @@ public static void main(String[] args) { AgentVersionDetails agent = null; try { - // Create a WebSearchTool - WebSearchTool tool = new WebSearchTool(); + // Create a WebSearchPreviewTool + WebSearchPreviewTool tool = new WebSearchPreviewTool(); // Create the agent definition with Web Search tool enabled PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) @@ -49,18 +53,18 @@ public static void main(String[] args) { + "When asked to find information, use the web search tool to gather relevant data.") .setTools(Collections.singletonList(tool)); - agent = agentsClient.createAgentVersion("MyAgent", agentDefinition); - System.out.printf("Agent created (id: %s, version: %s)\n", agent.getId(), agent.getVersion()); + agent = agentsClient.createAgentVersion("web-search-agent", agentDefinition); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); - AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); Response response = responsesClient.createWithAgent(agentReference, - ResponseCreateParams.builder().input("What are the latest developments in AI technology?")); + ResponseCreateParams.builder() + .input("What are the latest trends in renewable energy?")); // Process and display the response - System.out.println("\n=== Agent Response ==="); for (ResponseOutputItem outputItem : response.output()) { - // Handle message output if (outputItem.message().isPresent()) { ResponseOutputMessage message = outputItem.message().get(); message.content().forEach(content -> { @@ -70,17 +74,10 @@ public static void main(String[] args) { }); } } - - System.out.println("\nResponse ID: " + response.id()); - System.out.println("Model Used: " + response.model()); - } catch (Exception e) { - System.err.println("Error: " + e.getMessage()); - e.printStackTrace(); } finally { - // Cleanup agent if (agent != null) { agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); - System.out.println("Agent deleted successfully."); + System.out.println("Agent deleted"); } } } From 6ec135a3dc05a3a0d77c2cbb698f72c0daf9d171 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Fri, 6 Mar 2026 15:01:12 +0100 Subject: [PATCH 08/22] Samples pass --- .../ai/agents/tools/AzureFunctionAsync.java | 15 ++++++++--- .../ai/agents/tools/AzureFunctionSync.java | 16 +++++++++--- .../ai/agents/tools/FunctionCallAsync.java | 25 ++++++++++++++----- .../ai/agents/tools/FunctionCallSync.java | 25 ++++++++++++++----- 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionAsync.java index b4022eeafe88..05d4f830cbc1 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionAsync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionAsync.java @@ -24,6 +24,7 @@ import java.time.Duration; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; @@ -57,10 +58,16 @@ public static void main(String[] args) { AtomicReference agentRef = new AtomicReference<>(); - Map parameters = new HashMap<>(); - parameters.put("type", BinaryData.fromString("\"object\"")); - parameters.put("properties", BinaryData.fromString( - "{\"location\":{\"type\":\"string\",\"description\":\"location to determine weather for\"}}")); + Map locationProp = new LinkedHashMap(); + locationProp.put("type", "string"); + locationProp.put("description", "location to determine weather for"); + + Map props = new LinkedHashMap(); + props.put("location", locationProp); + + Map parameters = new HashMap(); + parameters.put("type", BinaryData.fromObject("object")); + parameters.put("properties", BinaryData.fromObject(props)); AzureFunctionTool azureFunctionTool = new AzureFunctionTool( new AzureFunctionDefinition( diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSync.java index 268ba1914618..9a488d83d0c0 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSync.java @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; /** @@ -54,10 +55,17 @@ public static void main(String[] args) { ResponsesClient responsesClient = builder.buildResponsesClient(); // Define function parameters - Map parameters = new HashMap<>(); - parameters.put("type", BinaryData.fromString("\"object\"")); - parameters.put("properties", BinaryData.fromString( - "{\"location\":{\"type\":\"string\",\"description\":\"location to determine weather for\"}}")); + // Use BinaryData.fromObject() to produce correct JSON types + Map locationProp = new LinkedHashMap(); + locationProp.put("type", "string"); + locationProp.put("description", "location to determine weather for"); + + Map props = new LinkedHashMap(); + props.put("location", locationProp); + + Map parameters = new HashMap(); + parameters.put("type", BinaryData.fromObject("object")); + parameters.put("properties", BinaryData.fromObject(props)); // Create Azure Function tool with Storage Queue bindings AzureFunctionTool azureFunctionTool = new AzureFunctionTool( diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java index e7641f789d4f..dc001fac3ad0 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java @@ -20,8 +20,10 @@ import reactor.core.publisher.Mono; import java.time.Duration; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; @@ -50,13 +52,24 @@ public static void main(String[] args) { AtomicReference agentRef = new AtomicReference<>(); // Create a FunctionTool with parameters schema + // Use BinaryData.fromObject() to produce correct JSON types (not double-encoded strings) + Map locationProp = new LinkedHashMap(); + locationProp.put("type", "string"); + locationProp.put("description", "The city and state, e.g. Seattle, WA"); + + Map unitProp = new LinkedHashMap(); + unitProp.put("type", "string"); + unitProp.put("enum", Arrays.asList("celsius", "fahrenheit")); + + Map properties = new LinkedHashMap(); + properties.put("location", locationProp); + properties.put("unit", unitProp); + Map parameters = new HashMap(); - parameters.put("type", BinaryData.fromString("\"object\"")); - parameters.put("properties", BinaryData.fromString( - "{\"location\":{\"type\":\"string\",\"description\":\"The city and state, e.g. Seattle, WA\"}," - + "\"unit\":{\"type\":\"string\",\"enum\":[\"celsius\",\"fahrenheit\"]}}")); - parameters.put("required", BinaryData.fromString("[\"location\", \"unit\"]")); - parameters.put("additionalProperties", BinaryData.fromString("false")); + parameters.put("type", BinaryData.fromObject("object")); + parameters.put("properties", BinaryData.fromObject(properties)); + parameters.put("required", BinaryData.fromObject(Arrays.asList("location", "unit"))); + parameters.put("additionalProperties", BinaryData.fromObject(false)); FunctionTool tool = new FunctionTool("get_weather", parameters, true) .setDescription("Get the current weather in a given location"); diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallSync.java index 155aaf36abe2..362d0da51fe9 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallSync.java @@ -19,8 +19,10 @@ import com.openai.models.responses.ResponseOutputItem; import com.openai.models.responses.ResponseOutputMessage; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; /** @@ -49,13 +51,24 @@ public static void main(String[] args) { try { // Create a FunctionTool with parameters schema + // Use BinaryData.fromObject() to produce correct JSON types (not double-encoded strings) + Map locationProp = new LinkedHashMap(); + locationProp.put("type", "string"); + locationProp.put("description", "The city and state, e.g. Seattle, WA"); + + Map unitProp = new LinkedHashMap(); + unitProp.put("type", "string"); + unitProp.put("enum", Arrays.asList("celsius", "fahrenheit")); + + Map properties = new LinkedHashMap(); + properties.put("location", locationProp); + properties.put("unit", unitProp); + Map parameters = new HashMap(); - parameters.put("type", BinaryData.fromString("\"object\"")); - parameters.put("properties", BinaryData.fromString( - "{\"location\":{\"type\":\"string\",\"description\":\"The city and state, e.g. Seattle, WA\"}," - + "\"unit\":{\"type\":\"string\",\"enum\":[\"celsius\",\"fahrenheit\"]}}")); - parameters.put("required", BinaryData.fromString("[\"location\", \"unit\"]")); - parameters.put("additionalProperties", BinaryData.fromString("false")); + parameters.put("type", BinaryData.fromObject("object")); + parameters.put("properties", BinaryData.fromObject(properties)); + parameters.put("required", BinaryData.fromObject(Arrays.asList("location", "unit"))); + parameters.put("additionalProperties", BinaryData.fromObject(false)); FunctionTool tool = new FunctionTool("get_weather", parameters, true) .setDescription("Get the current weather in a given location"); From fe952fb642ee73b406b95ee071465a9cd985c467 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Fri, 6 Mar 2026 15:08:35 +0100 Subject: [PATCH 09/22] MCP sample correction and alignment with python --- .../com/azure/ai/agents/tools/McpAsync.java | 56 ++++++++++++++++--- .../com/azure/ai/agents/tools/McpSync.java | 49 +++++++++++++--- 2 files changed, 89 insertions(+), 16 deletions(-) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java index 57da352a175c..bd36515e9769 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java @@ -10,20 +10,28 @@ import com.azure.ai.agents.models.AgentVersionDetails; import com.azure.ai.agents.models.McpTool; import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.BinaryData; import com.azure.core.util.Configuration; import com.azure.identity.DefaultAzureCredentialBuilder; +import com.openai.models.responses.Response; import com.openai.models.responses.ResponseCreateParams; +import com.openai.models.responses.ResponseInputItem; import com.openai.models.responses.ResponseOutputItem; import com.openai.models.responses.ResponseOutputMessage; import reactor.core.publisher.Mono; import java.time.Duration; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.concurrent.atomic.AtomicReference; /** - * This sample demonstrates how to create an agent with a Model Context Protocol (MCP) tool - * to connect to external MCP servers, using the async client. + * This sample demonstrates (using the async client) how to create an agent with a Model Context Protocol (MCP) tool + * to connect to an external MCP server and handle approval requests. + * + *

    Uses gitmcp.io to expose a GitHub repository as an + * MCP-compatible server (no authentication required).

    * *

    Before running the sample, set these environment variables:

    *
      @@ -46,13 +54,14 @@ public static void main(String[] args) { AtomicReference agentRef = new AtomicReference<>(); // Create an MCP tool that connects to a remote MCP server - McpTool tool = new McpTool("my-mcp-server") - .setServerUrl("https://example.mcp.server/mcp") - .setServerDescription("An MCP server that provides additional tools"); + // Uses gitmcp.io to expose a GitHub repository as an MCP-compatible server + McpTool tool = new McpTool("api-specs") + .setServerUrl("https://gitmcp.io/Azure/azure-rest-api-specs") + .setRequireApproval(BinaryData.fromObject("always")); PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) - .setInstructions("You are a helpful assistant that can use MCP tools to access external services. " - + "When asked to perform tasks, use the available MCP tools to help the user.") + .setInstructions("You are a helpful agent that can use MCP tools to assist users. " + + "Use the available MCP tools to answer questions and perform tasks.") .setTools(Collections.singletonList(tool)); agentsAsyncClient.createAgentVersion("mcp-agent", agentDefinition) @@ -65,7 +74,38 @@ public static void main(String[] args) { return responsesAsyncClient.createWithAgent(agentReference, ResponseCreateParams.builder() - .input("What tools are available from the MCP server?")); + .input("Please summarize the Azure REST API specifications Readme")); + }) + .flatMap(response -> { + AgentVersionDetails agent = agentRef.get(); + AgentReference agentReference = new AgentReference(agent.getName()) + .setVersion(agent.getVersion()); + + // Process MCP approval requests + List approvals = new ArrayList(); + for (ResponseOutputItem item : response.output()) { + if (item.isMcpApprovalRequest()) { + ResponseOutputItem.McpApprovalRequest request = item.asMcpApprovalRequest(); + System.out.printf("MCP approval requested: server=%s, id=%s%n", + request.serverLabel(), request.id()); + + approvals.add(ResponseInputItem.ofMcpApprovalResponse( + ResponseInputItem.McpApprovalResponse.builder() + .approvalRequestId(request.id()) + .approve(true) + .build())); + } + } + + if (!approvals.isEmpty()) { + System.out.println("Sending " + approvals.size() + " approval(s)..."); + return responsesAsyncClient.createWithAgent(agentReference, + ResponseCreateParams.builder() + .inputOfResponse(approvals) + .previousResponseId(response.id())); + } + + return Mono.just(response); }) .doOnNext(response -> { for (ResponseOutputItem outputItem : response.output()) { diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpSync.java index f94d02aeb0f7..15dfe84ccaf8 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpSync.java @@ -10,18 +10,25 @@ import com.azure.ai.agents.models.AgentVersionDetails; import com.azure.ai.agents.models.McpTool; import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.core.util.BinaryData; import com.azure.core.util.Configuration; import com.azure.identity.DefaultAzureCredentialBuilder; import com.openai.models.responses.Response; import com.openai.models.responses.ResponseCreateParams; +import com.openai.models.responses.ResponseInputItem; import com.openai.models.responses.ResponseOutputItem; import com.openai.models.responses.ResponseOutputMessage; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; /** * This sample demonstrates how to create an agent with a Model Context Protocol (MCP) tool - * to connect to external MCP servers. + * to connect to an external MCP server and handle approval requests. + * + *

      Uses gitmcp.io to expose a GitHub repository as an + * MCP-compatible server (no authentication required).

      * *

      Before running the sample, set these environment variables:

      *
        @@ -45,14 +52,15 @@ public static void main(String[] args) { try { // Create an MCP tool that connects to a remote MCP server - McpTool tool = new McpTool("my-mcp-server") - .setServerUrl("https://example.mcp.server/mcp") - .setServerDescription("An MCP server that provides additional tools"); + // Uses gitmcp.io to expose a GitHub repository as an MCP-compatible server + McpTool tool = new McpTool("api-specs") + .setServerUrl("https://gitmcp.io/Azure/azure-rest-api-specs") + .setRequireApproval(BinaryData.fromObject("always")); // Create the agent definition with MCP tool enabled PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) - .setInstructions("You are a helpful assistant that can use MCP tools to access external services. " - + "When asked to perform tasks, use the available MCP tools to help the user.") + .setInstructions("You are a helpful agent that can use MCP tools to assist users. " + + "Use the available MCP tools to answer questions and perform tasks.") .setTools(Collections.singletonList(tool)); agent = agentsClient.createAgentVersion("mcp-agent", agentDefinition); @@ -63,9 +71,34 @@ public static void main(String[] args) { Response response = responsesClient.createWithAgent(agentReference, ResponseCreateParams.builder() - .input("What tools are available from the MCP server?")); + .input("Please summarize the Azure REST API specifications Readme")); + + // Process MCP approval requests — the server requires approval before executing tools + List approvals = new ArrayList(); + for (ResponseOutputItem item : response.output()) { + if (item.isMcpApprovalRequest()) { + ResponseOutputItem.McpApprovalRequest request = item.asMcpApprovalRequest(); + System.out.printf("MCP approval requested: server=%s, id=%s%n", + request.serverLabel(), request.id()); + + approvals.add(ResponseInputItem.ofMcpApprovalResponse( + ResponseInputItem.McpApprovalResponse.builder() + .approvalRequestId(request.id()) + .approve(true) + .build())); + } + } + + // If approvals were needed, send them back and get the final response + if (!approvals.isEmpty()) { + System.out.println("Sending " + approvals.size() + " approval(s)..."); + response = responsesClient.createWithAgent(agentReference, + ResponseCreateParams.builder() + .inputOfResponse(approvals) + .previousResponseId(response.id())); + } - // Process and display the response + // Process and display the final response for (ResponseOutputItem outputItem : response.output()) { if (outputItem.message().isPresent()) { ResponseOutputMessage message = outputItem.message().get(); From 0a397493c2738d8d00ca2db28b694fcf8abffa4d Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Fri, 6 Mar 2026 18:00:06 +0100 Subject: [PATCH 10/22] Unit tests for tools --- sdk/ai/azure-ai-agents/assets.json | 2 +- .../com/azure/ai/agents/OpenAPIToolTests.java | 93 ---- .../com/azure/ai/agents/ToolsAsyncTests.java | 410 ++++++++++++++++++ .../java/com/azure/ai/agents/ToolsTests.java | 380 ++++++++++++++++ 4 files changed, 791 insertions(+), 94 deletions(-) delete mode 100644 sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/OpenAPIToolTests.java create mode 100644 sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsAsyncTests.java create mode 100644 sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsTests.java diff --git a/sdk/ai/azure-ai-agents/assets.json b/sdk/ai/azure-ai-agents/assets.json index 42ea9478529a..718016065f0e 100644 --- a/sdk/ai/azure-ai-agents/assets.json +++ b/sdk/ai/azure-ai-agents/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "java", "TagPrefix": "java/ai/azure-ai-agents", - "Tag": "java/ai/azure-ai-agents_69bc682982" + "Tag": "java/ai/azure-ai-agents_ca44de768d" } \ No newline at end of file diff --git a/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/OpenAPIToolTests.java b/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/OpenAPIToolTests.java deleted file mode 100644 index c1d814a798b8..000000000000 --- a/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/OpenAPIToolTests.java +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.ai.agents; - -import com.azure.ai.agents.models.AgentReference; -import com.azure.ai.agents.models.AgentVersionDetails; -import com.azure.ai.agents.models.OpenApiAnonymousAuthDetails; -import com.azure.ai.agents.models.OpenApiFunctionDefinition; -import com.azure.ai.agents.models.OpenApiTool; -import com.azure.ai.agents.models.PromptAgentDefinition; -import com.azure.core.http.HttpClient; -import com.azure.core.util.BinaryData; -import com.openai.models.conversations.Conversation; -import com.openai.models.conversations.items.ItemCreateParams; -import com.openai.models.responses.EasyInputMessage; -import com.openai.models.responses.Response; -import com.openai.models.responses.ResponseCreateParams; -import com.openai.models.responses.ResponseStatus; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Map; - -import static com.azure.ai.agents.TestUtils.DISPLAY_NAME_WITH_ARGUMENTS; -import static org.junit.jupiter.api.Assertions.*; - -public class OpenAPIToolTests extends ClientTestBase { - - private static final String AGENT_NAME = "openapi-tool-test-agent-java"; - - @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) - @MethodSource("com.azure.ai.agents.TestUtils#getTestParameters") - public void openApiToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serviceVersion) throws IOException { - AgentsClient agentsClient = getAgentsSyncClient(httpClient, serviceVersion); - ResponsesClient responsesClient = getResponsesSyncClient(httpClient, serviceVersion); - ConversationsClient conversationsClient = getConversationsSyncClient(httpClient, serviceVersion); - - // Load the OpenAPI spec from test resources - Map spec - = OpenApiFunctionDefinition.readSpecFromFile(TestUtils.getTestResourcePath("assets/httpbin_openapi.json")); - - OpenApiFunctionDefinition toolDefinition - = new OpenApiFunctionDefinition("httpbin_get", spec, new OpenApiAnonymousAuthDetails()) - .setDescription("Get request metadata from an OpenAPI endpoint."); - - PromptAgentDefinition agentDefinition - = new PromptAgentDefinition("gpt-4o").setInstructions("Use the OpenAPI tool for HTTP request metadata.") - .setTools(Arrays.asList(new OpenApiTool(toolDefinition))); - - AgentVersionDetails agentVersion = agentsClient.createAgentVersion(AGENT_NAME, agentDefinition); - assertNotNull(agentVersion); - assertNotNull(agentVersion.getId()); - assertEquals(AGENT_NAME, agentVersion.getName()); - - try { - // Create a conversation and add a user message - Conversation conversation = conversationsClient.getConversationService().create(); - assertNotNull(conversation); - assertNotNull(conversation.id()); - - conversationsClient.getConversationService() - .items() - .create(ItemCreateParams.builder() - .conversationId(conversation.id()) - .addItem(EasyInputMessage.builder() - .role(EasyInputMessage.Role.USER) - .content("Use the OpenAPI tool and summarize the returned URL and origin in one sentence.") - .build()) - .build()); - - // Create a response using the agent with the conversation - AgentReference agentReference - = new AgentReference(agentVersion.getName()).setVersion(agentVersion.getVersion()); - - ResponseCreateParams.Builder options = ResponseCreateParams.builder().maxOutputTokens(300L); - - Response response = responsesClient.createWithAgentConversation(agentReference, conversation.id(), options); - - assertNotNull(response); - assertTrue(response.id().startsWith("resp")); - assertTrue(response.status().isPresent()); - assertEquals(ResponseStatus.COMPLETED, response.status().get()); - assertFalse(response.output().isEmpty()); - assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); - } finally { - // Clean up - agentsClient.deleteAgentVersion(agentVersion.getName(), agentVersion.getVersion()); - } - } -} diff --git a/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsAsyncTests.java b/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsAsyncTests.java new file mode 100644 index 000000000000..89033e963f11 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsAsyncTests.java @@ -0,0 +1,410 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents; + +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.CodeInterpreterTool; +import com.azure.ai.agents.models.FileSearchTool; +import com.azure.ai.agents.models.FunctionTool; +import com.azure.ai.agents.models.McpTool; +import com.azure.ai.agents.models.OpenApiAnonymousAuthDetails; +import com.azure.ai.agents.models.OpenApiFunctionDefinition; +import com.azure.ai.agents.models.OpenApiTool; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.ai.agents.models.WebSearchPreviewTool; +import com.azure.core.http.HttpClient; +import com.azure.core.util.BinaryData; +import com.openai.models.conversations.Conversation; +import com.openai.models.files.FileCreateParams; +import com.openai.models.files.FileObject; +import com.openai.models.files.FilePurpose; +import com.openai.models.responses.Response; +import com.openai.models.responses.ResponseCreateParams; +import com.openai.models.responses.ResponseInputItem; +import com.openai.models.responses.ResponseOutputItem; +import com.openai.models.responses.ResponseStatus; +import com.openai.models.vectorstores.VectorStore; +import com.openai.models.vectorstores.VectorStoreCreateParams; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +import static com.azure.ai.agents.TestUtils.DISPLAY_NAME_WITH_ARGUMENTS; +import static org.junit.jupiter.api.Assertions.*; + +public class ToolsAsyncTests extends ClientTestBase { + + // ----------------------------------------------------------------------- + // OpenAPI Tool + // ----------------------------------------------------------------------- + + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.agents.TestUtils#getTestParameters") + public void openApiToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serviceVersion) throws IOException { + AgentsAsyncClient agentsClient = getAgentsAsyncClient(httpClient, serviceVersion); + ResponsesAsyncClient responsesClient = getResponsesAsyncClient(httpClient, serviceVersion); + ConversationsAsyncClient conversationsClient = getConversationsAsyncClient(httpClient, serviceVersion); + + Map spec + = OpenApiFunctionDefinition.readSpecFromFile(TestUtils.getTestResourcePath("assets/httpbin_openapi.json")); + + OpenApiFunctionDefinition toolDefinition + = new OpenApiFunctionDefinition("httpbin_get", spec, new OpenApiAnonymousAuthDetails()) + .setDescription("Get request metadata from an OpenAPI endpoint."); + + PromptAgentDefinition agentDefinition + = new PromptAgentDefinition("gpt-4o").setInstructions("Use the OpenAPI tool for HTTP request metadata.") + .setTools(Arrays.asList(new OpenApiTool(toolDefinition))); + + AtomicReference agentRef = new AtomicReference<>(); + + StepVerifier.create( + agentsClient.createAgentVersion("openapi-tool-test-agent-java-async", agentDefinition).flatMap(agent -> { + agentRef.set(agent); + assertNotNull(agent); + assertNotNull(agent.getId()); + + AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + + return Mono.fromFuture(conversationsClient.getConversationServiceAsync().create()) + .flatMap(conversation -> { + assertNotNull(conversation); + return responsesClient.createWithAgentConversation(agentReference, conversation.id(), + ResponseCreateParams.builder() + .input( + "Use the OpenAPI tool and summarize the returned URL and origin in one sentence.") + .maxOutputTokens(300L)); + }); + }).doFinally(signal -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()).block(); + } + })).assertNext(response -> { + assertNotNull(response); + assertTrue(response.id().startsWith("resp")); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); + }).verifyComplete(); + } + + // ----------------------------------------------------------------------- + // Code Interpreter Tool + // ----------------------------------------------------------------------- + + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.agents.TestUtils#getTestParameters") + public void codeInterpreterToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serviceVersion) { + AgentsAsyncClient agentsClient = getAgentsAsyncClient(httpClient, serviceVersion); + ResponsesAsyncClient responsesClient = getResponsesAsyncClient(httpClient, serviceVersion); + + CodeInterpreterTool tool = new CodeInterpreterTool(); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition("gpt-4o") + .setInstructions("You are a helpful assistant that can execute Python code to solve problems.") + .setTools(Collections.singletonList(tool)); + + AtomicReference agentRef = new AtomicReference<>(); + + StepVerifier.create(agentsClient.createAgentVersion("code-interpreter-test-agent-java-async", agentDefinition) + .flatMap(agent -> { + agentRef.set(agent); + assertNotNull(agent); + + AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + + return responsesClient.createWithAgent(agentReference, ResponseCreateParams.builder() + .input("Calculate the first 10 prime numbers and show the Python code.")); + }) + .doFinally(signal -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()).block(); + } + })).assertNext(response -> { + assertNotNull(response); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + assertTrue(response.output().stream().anyMatch(item -> item.isCodeInterpreterCall())); + }).verifyComplete(); + } + + // ----------------------------------------------------------------------- + // Function Calling Tool + // ----------------------------------------------------------------------- + + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.agents.TestUtils#getTestParameters") + public void functionCallToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serviceVersion) { + AgentsAsyncClient agentsClient = getAgentsAsyncClient(httpClient, serviceVersion); + ResponsesAsyncClient responsesClient = getResponsesAsyncClient(httpClient, serviceVersion); + + Map locationProp = new LinkedHashMap(); + locationProp.put("type", "string"); + locationProp.put("description", "The city and state, e.g. Seattle, WA"); + + Map unitProp = new LinkedHashMap(); + unitProp.put("type", "string"); + unitProp.put("enum", Arrays.asList("celsius", "fahrenheit")); + + Map properties = new LinkedHashMap(); + properties.put("location", locationProp); + properties.put("unit", unitProp); + + Map parameters = new HashMap(); + parameters.put("type", BinaryData.fromObject("object")); + parameters.put("properties", BinaryData.fromObject(properties)); + parameters.put("required", BinaryData.fromObject(Arrays.asList("location", "unit"))); + parameters.put("additionalProperties", BinaryData.fromObject(false)); + + FunctionTool tool = new FunctionTool("get_weather", parameters, true) + .setDescription("Get the current weather in a given location"); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition("gpt-4o") + .setInstructions("You are a helpful assistant. When asked about weather, use the get_weather function.") + .setTools(Collections.singletonList(tool)); + + AtomicReference agentRef = new AtomicReference<>(); + + StepVerifier.create( + agentsClient.createAgentVersion("function-call-test-agent-java-async", agentDefinition).flatMap(agent -> { + agentRef.set(agent); + assertNotNull(agent); + + AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + + return responsesClient.createWithAgent(agentReference, + ResponseCreateParams.builder().input("What's the weather like in Seattle?")); + }).doFinally(signal -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()).block(); + } + })).assertNext(response -> { + assertNotNull(response); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + assertTrue(response.output().stream().anyMatch(item -> item.isFunctionCall())); + + ResponseOutputItem functionCallItem + = response.output().stream().filter(item -> item.isFunctionCall()).findFirst().get(); + assertEquals("get_weather", functionCallItem.asFunctionCall().name()); + assertNotNull(functionCallItem.asFunctionCall().arguments()); + }).verifyComplete(); + } + + // ----------------------------------------------------------------------- + // Web Search Tool + // ----------------------------------------------------------------------- + + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.agents.TestUtils#getTestParameters") + public void webSearchToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serviceVersion) { + AgentsAsyncClient agentsClient = getAgentsAsyncClient(httpClient, serviceVersion); + ResponsesAsyncClient responsesClient = getResponsesAsyncClient(httpClient, serviceVersion); + + WebSearchPreviewTool tool = new WebSearchPreviewTool(); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition("gpt-4o") + .setInstructions("You are a helpful assistant that can search the web.") + .setTools(Collections.singletonList(tool)); + + AtomicReference agentRef = new AtomicReference<>(); + + StepVerifier.create( + agentsClient.createAgentVersion("web-search-test-agent-java-async", agentDefinition).flatMap(agent -> { + agentRef.set(agent); + assertNotNull(agent); + + AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + + return responsesClient.createWithAgent(agentReference, + ResponseCreateParams.builder().input("What are the latest trends in renewable energy?")); + }).doFinally(signal -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()).block(); + } + })).assertNext(response -> { + assertNotNull(response); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); + }).verifyComplete(); + } + + // ----------------------------------------------------------------------- + // MCP Tool + // ----------------------------------------------------------------------- + + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.agents.TestUtils#getTestParameters") + public void mcpToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serviceVersion) { + AgentsAsyncClient agentsClient = getAgentsAsyncClient(httpClient, serviceVersion); + ResponsesAsyncClient responsesClient = getResponsesAsyncClient(httpClient, serviceVersion); + + McpTool tool = new McpTool("api-specs").setServerUrl("https://gitmcp.io/Azure/azure-rest-api-specs") + .setRequireApproval(BinaryData.fromObject("always")); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition("gpt-4o") + .setInstructions("You are a helpful agent that can use MCP tools to assist users.") + .setTools(Collections.singletonList(tool)); + + AtomicReference agentRef = new AtomicReference<>(); + + StepVerifier + .create(agentsClient.createAgentVersion("mcp-test-agent-java-async", agentDefinition).flatMap(agent -> { + agentRef.set(agent); + assertNotNull(agent); + + AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + + return responsesClient.createWithAgent(agentReference, + ResponseCreateParams.builder().input("Please summarize the Azure REST API specifications Readme")); + }).flatMap(response -> { + assertNotNull(response); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + + AgentVersionDetails agent = agentRef.get(); + AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + + List approvals = new ArrayList(); + for (ResponseOutputItem item : response.output()) { + if (item.isMcpApprovalRequest()) { + approvals + .add(ResponseInputItem.ofMcpApprovalResponse(ResponseInputItem.McpApprovalResponse.builder() + .approvalRequestId(item.asMcpApprovalRequest().id()) + .approve(true) + .build())); + } + } + + assertFalse(approvals.isEmpty(), "Expected at least one MCP approval request"); + + return responsesClient.createWithAgent(agentReference, + ResponseCreateParams.builder().inputOfResponse(approvals).previousResponseId(response.id())); + }).doFinally(signal -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()).block(); + } + })) + .assertNext(response -> { + assertNotNull(response); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); + }) + .verifyComplete(); + } + + // ----------------------------------------------------------------------- + // File Search Tool + // ----------------------------------------------------------------------- + + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.agents.TestUtils#getTestParameters") + public void fileSearchToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serviceVersion) throws Exception { + AgentsAsyncClient agentsClient = getAgentsAsyncClient(httpClient, serviceVersion); + ResponsesAsyncClient responsesClient = getResponsesAsyncClient(httpClient, serviceVersion); + ConversationsAsyncClient conversationsClient = getConversationsAsyncClient(httpClient, serviceVersion); + + AgentsClientBuilder openAIBuilder = getClientBuilder(httpClient, serviceVersion); + com.openai.client.OpenAIClient openAIClient = openAIBuilder.buildOpenAIClient(); + + String sampleContent = "The Solar System consists of the Sun and the celestial objects bound to it by gravity. " + + "The eight planets in order from the Sun are: Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, and Neptune. " + + "Jupiter is the largest planet, while Mercury is the smallest."; + + Path tempFile = Files.createTempFile("test_document", ".txt"); + Files.write(tempFile, sampleContent.getBytes(StandardCharsets.UTF_8)); + + FileObject uploadedFile = null; + VectorStore vectorStore = null; + AtomicReference agentRef = new AtomicReference<>(); + + try { + uploadedFile = openAIClient.files() + .create(FileCreateParams.builder().file(tempFile).purpose(FilePurpose.ASSISTANTS).build()); + assertNotNull(uploadedFile); + + vectorStore = openAIClient.vectorStores() + .create(VectorStoreCreateParams.builder() + .name("TestVectorStoreAsync") + .fileIds(Collections.singletonList(uploadedFile.id())) + .build()); + assertNotNull(vectorStore); + + sleep(5000); + + FileSearchTool tool = new FileSearchTool(Collections.singletonList(vectorStore.id())); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition("gpt-4o") + .setInstructions("You are a helpful assistant that searches uploaded files to answer questions.") + .setTools(Collections.singletonList(tool)); + + final FileObject uploadedFileFinal = uploadedFile; + final VectorStore vectorStoreFinal = vectorStore; + + StepVerifier.create( + agentsClient.createAgentVersion("file-search-test-agent-java-async", agentDefinition).flatMap(agent -> { + agentRef.set(agent); + assertNotNull(agent); + + AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + + return Mono.fromFuture(conversationsClient.getConversationServiceAsync().create()) + .flatMap(conversation -> { + assertNotNull(conversation); + return responsesClient.createWithAgentConversation(agentReference, conversation.id(), + ResponseCreateParams.builder() + .input("What is the largest planet in the Solar System?")); + }); + }).doFinally(signal -> { + AgentVersionDetails agent = agentRef.get(); + if (agent != null) { + agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()).block(); + } + })).assertNext(response -> { + assertNotNull(response); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + assertTrue(response.output().stream().anyMatch(item -> item.isFileSearchCall())); + assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); + }).verifyComplete(); + } finally { + Files.deleteIfExists(tempFile); + if (vectorStore != null) { + openAIClient.vectorStores().delete(vectorStore.id()); + } + if (uploadedFile != null) { + openAIClient.files().delete(uploadedFile.id()); + } + } + } +} diff --git a/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsTests.java b/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsTests.java new file mode 100644 index 000000000000..0b5305fd3014 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsTests.java @@ -0,0 +1,380 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.ai.agents; + +import com.azure.ai.agents.models.AgentReference; +import com.azure.ai.agents.models.AgentVersionDetails; +import com.azure.ai.agents.models.CodeInterpreterTool; +import com.azure.ai.agents.models.FileSearchTool; +import com.azure.ai.agents.models.FunctionTool; +import com.azure.ai.agents.models.McpTool; +import com.azure.ai.agents.models.OpenApiAnonymousAuthDetails; +import com.azure.ai.agents.models.OpenApiFunctionDefinition; +import com.azure.ai.agents.models.OpenApiTool; +import com.azure.ai.agents.models.PromptAgentDefinition; +import com.azure.ai.agents.models.WebSearchPreviewTool; +import com.azure.core.http.HttpClient; +import com.azure.core.util.BinaryData; +import com.openai.models.conversations.Conversation; +import com.openai.models.conversations.items.ItemCreateParams; +import com.openai.models.files.FileCreateParams; +import com.openai.models.files.FileObject; +import com.openai.models.files.FilePurpose; +import com.openai.models.responses.EasyInputMessage; +import com.openai.models.responses.Response; +import com.openai.models.responses.ResponseCreateParams; +import com.openai.models.responses.ResponseInputItem; +import com.openai.models.responses.ResponseOutputItem; +import com.openai.models.responses.ResponseStatus; +import com.openai.models.vectorstores.VectorStore; +import com.openai.models.vectorstores.VectorStoreCreateParams; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static com.azure.ai.agents.TestUtils.DISPLAY_NAME_WITH_ARGUMENTS; +import static org.junit.jupiter.api.Assertions.*; + +public class ToolsTests extends ClientTestBase { + + // ----------------------------------------------------------------------- + // OpenAPI Tool + // ----------------------------------------------------------------------- + + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.agents.TestUtils#getTestParameters") + public void openApiToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serviceVersion) throws IOException { + AgentsClient agentsClient = getAgentsSyncClient(httpClient, serviceVersion); + ResponsesClient responsesClient = getResponsesSyncClient(httpClient, serviceVersion); + ConversationsClient conversationsClient = getConversationsSyncClient(httpClient, serviceVersion); + + Map spec + = OpenApiFunctionDefinition.readSpecFromFile(TestUtils.getTestResourcePath("assets/httpbin_openapi.json")); + + OpenApiFunctionDefinition toolDefinition + = new OpenApiFunctionDefinition("httpbin_get", spec, new OpenApiAnonymousAuthDetails()) + .setDescription("Get request metadata from an OpenAPI endpoint."); + + PromptAgentDefinition agentDefinition + = new PromptAgentDefinition("gpt-4o").setInstructions("Use the OpenAPI tool for HTTP request metadata.") + .setTools(Arrays.asList(new OpenApiTool(toolDefinition))); + + AgentVersionDetails agent = agentsClient.createAgentVersion("openapi-tool-test-agent-java", agentDefinition); + assertNotNull(agent); + assertNotNull(agent.getId()); + + try { + Conversation conversation = conversationsClient.getConversationService().create(); + assertNotNull(conversation); + + conversationsClient.getConversationService() + .items() + .create(ItemCreateParams.builder() + .conversationId(conversation.id()) + .addItem(EasyInputMessage.builder() + .role(EasyInputMessage.Role.USER) + .content("Use the OpenAPI tool and summarize the returned URL and origin in one sentence.") + .build()) + .build()); + + AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + + Response response = responsesClient.createWithAgentConversation(agentReference, conversation.id(), + ResponseCreateParams.builder().maxOutputTokens(300L)); + + assertNotNull(response); + assertTrue(response.id().startsWith("resp")); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); + } finally { + agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); + } + } + + // ----------------------------------------------------------------------- + // Code Interpreter Tool + // ----------------------------------------------------------------------- + + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.agents.TestUtils#getTestParameters") + public void codeInterpreterToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serviceVersion) { + AgentsClient agentsClient = getAgentsSyncClient(httpClient, serviceVersion); + ResponsesClient responsesClient = getResponsesSyncClient(httpClient, serviceVersion); + + CodeInterpreterTool tool = new CodeInterpreterTool(); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition("gpt-4o") + .setInstructions("You are a helpful assistant that can execute Python code to solve problems.") + .setTools(Collections.singletonList(tool)); + + AgentVersionDetails agent + = agentsClient.createAgentVersion("code-interpreter-test-agent-java", agentDefinition); + assertNotNull(agent); + assertNotNull(agent.getId()); + + try { + AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + + Response response = responsesClient.createWithAgent(agentReference, + ResponseCreateParams.builder().input("Calculate the first 10 prime numbers and show the Python code.")); + + assertNotNull(response); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + // Should contain at least one code interpreter call + assertTrue(response.output().stream().anyMatch(item -> item.isCodeInterpreterCall())); + } finally { + agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); + } + } + + // ----------------------------------------------------------------------- + // Function Calling Tool + // ----------------------------------------------------------------------- + + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.agents.TestUtils#getTestParameters") + public void functionCallToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serviceVersion) { + AgentsClient agentsClient = getAgentsSyncClient(httpClient, serviceVersion); + ResponsesClient responsesClient = getResponsesSyncClient(httpClient, serviceVersion); + + Map locationProp = new LinkedHashMap(); + locationProp.put("type", "string"); + locationProp.put("description", "The city and state, e.g. Seattle, WA"); + + Map unitProp = new LinkedHashMap(); + unitProp.put("type", "string"); + unitProp.put("enum", Arrays.asList("celsius", "fahrenheit")); + + Map properties = new LinkedHashMap(); + properties.put("location", locationProp); + properties.put("unit", unitProp); + + Map parameters = new HashMap(); + parameters.put("type", BinaryData.fromObject("object")); + parameters.put("properties", BinaryData.fromObject(properties)); + parameters.put("required", BinaryData.fromObject(Arrays.asList("location", "unit"))); + parameters.put("additionalProperties", BinaryData.fromObject(false)); + + FunctionTool tool = new FunctionTool("get_weather", parameters, true) + .setDescription("Get the current weather in a given location"); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition("gpt-4o") + .setInstructions("You are a helpful assistant. When asked about weather, use the get_weather function.") + .setTools(Collections.singletonList(tool)); + + AgentVersionDetails agent = agentsClient.createAgentVersion("function-call-test-agent-java", agentDefinition); + assertNotNull(agent); + + try { + AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + + Response response = responsesClient.createWithAgent(agentReference, + ResponseCreateParams.builder().input("What's the weather like in Seattle?")); + + assertNotNull(response); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + // Should contain a function call + assertTrue(response.output().stream().anyMatch(item -> item.isFunctionCall())); + + // Validate function call details + ResponseOutputItem functionCallItem + = response.output().stream().filter(item -> item.isFunctionCall()).findFirst().get(); + + assertEquals("get_weather", functionCallItem.asFunctionCall().name()); + assertNotNull(functionCallItem.asFunctionCall().arguments()); + } finally { + agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); + } + } + + // ----------------------------------------------------------------------- + // Web Search Tool + // ----------------------------------------------------------------------- + + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.agents.TestUtils#getTestParameters") + public void webSearchToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serviceVersion) { + AgentsClient agentsClient = getAgentsSyncClient(httpClient, serviceVersion); + ResponsesClient responsesClient = getResponsesSyncClient(httpClient, serviceVersion); + + WebSearchPreviewTool tool = new WebSearchPreviewTool(); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition("gpt-4o") + .setInstructions("You are a helpful assistant that can search the web.") + .setTools(Collections.singletonList(tool)); + + AgentVersionDetails agent = agentsClient.createAgentVersion("web-search-test-agent-java", agentDefinition); + assertNotNull(agent); + + try { + AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + + Response response = responsesClient.createWithAgent(agentReference, + ResponseCreateParams.builder().input("What are the latest trends in renewable energy?")); + + assertNotNull(response); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); + } finally { + agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); + } + } + + // ----------------------------------------------------------------------- + // MCP Tool + // ----------------------------------------------------------------------- + + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.agents.TestUtils#getTestParameters") + public void mcpToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serviceVersion) { + AgentsClient agentsClient = getAgentsSyncClient(httpClient, serviceVersion); + ResponsesClient responsesClient = getResponsesSyncClient(httpClient, serviceVersion); + + McpTool tool = new McpTool("api-specs").setServerUrl("https://gitmcp.io/Azure/azure-rest-api-specs") + .setRequireApproval(BinaryData.fromObject("always")); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition("gpt-4o") + .setInstructions("You are a helpful agent that can use MCP tools to assist users.") + .setTools(Collections.singletonList(tool)); + + AgentVersionDetails agent = agentsClient.createAgentVersion("mcp-test-agent-java", agentDefinition); + assertNotNull(agent); + + try { + AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + + Response response = responsesClient.createWithAgent(agentReference, + ResponseCreateParams.builder().input("Please summarize the Azure REST API specifications Readme")); + + assertNotNull(response); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + + // Process MCP approval requests + List approvals = new ArrayList(); + for (ResponseOutputItem item : response.output()) { + if (item.isMcpApprovalRequest()) { + approvals + .add(ResponseInputItem.ofMcpApprovalResponse(ResponseInputItem.McpApprovalResponse.builder() + .approvalRequestId(item.asMcpApprovalRequest().id()) + .approve(true) + .build())); + } + } + + assertFalse(approvals.isEmpty(), "Expected at least one MCP approval request"); + + // Send approvals and get the final response + Response finalResponse = responsesClient.createWithAgent(agentReference, + ResponseCreateParams.builder().inputOfResponse(approvals).previousResponseId(response.id())); + + assertNotNull(finalResponse); + assertTrue(finalResponse.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, finalResponse.status().get()); + assertFalse(finalResponse.output().isEmpty()); + assertTrue(finalResponse.output().stream().anyMatch(item -> item.isMessage())); + } finally { + agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); + } + } + + // ----------------------------------------------------------------------- + // File Search Tool + // ----------------------------------------------------------------------- + + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("com.azure.ai.agents.TestUtils#getTestParameters") + public void fileSearchToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serviceVersion) throws Exception { + AgentsClient agentsClient = getAgentsSyncClient(httpClient, serviceVersion); + ResponsesClient responsesClient = getResponsesSyncClient(httpClient, serviceVersion); + ConversationsClient conversationsClient = getConversationsSyncClient(httpClient, serviceVersion); + + AgentsClientBuilder openAIBuilder = getClientBuilder(httpClient, serviceVersion); + com.openai.client.OpenAIClient openAIClient = openAIBuilder.buildOpenAIClient(); + + // Create a sample document and upload it + String sampleContent = "The Solar System consists of the Sun and the celestial objects bound to it by gravity. " + + "The eight planets in order from the Sun are: Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, and Neptune. " + + "Jupiter is the largest planet, while Mercury is the smallest."; + + Path tempFile = Files.createTempFile("test_document", ".txt"); + Files.write(tempFile, sampleContent.getBytes(StandardCharsets.UTF_8)); + + FileObject uploadedFile = null; + VectorStore vectorStore = null; + AgentVersionDetails agent = null; + + try { + uploadedFile = openAIClient.files() + .create(FileCreateParams.builder().file(tempFile).purpose(FilePurpose.ASSISTANTS).build()); + assertNotNull(uploadedFile); + assertNotNull(uploadedFile.id()); + + vectorStore = openAIClient.vectorStores() + .create(VectorStoreCreateParams.builder() + .name("TestVectorStore") + .fileIds(Collections.singletonList(uploadedFile.id())) + .build()); + assertNotNull(vectorStore); + + // Wait for vector store to process + sleep(5000); + + FileSearchTool tool = new FileSearchTool(Collections.singletonList(vectorStore.id())); + + PromptAgentDefinition agentDefinition = new PromptAgentDefinition("gpt-4o") + .setInstructions("You are a helpful assistant that searches uploaded files to answer questions.") + .setTools(Collections.singletonList(tool)); + + agent = agentsClient.createAgentVersion("file-search-test-agent-java", agentDefinition); + assertNotNull(agent); + + AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); + + Conversation conversation = conversationsClient.getConversationService().create(); + assertNotNull(conversation); + + Response response = responsesClient.createWithAgentConversation(agentReference, conversation.id(), + ResponseCreateParams.builder().input("What is the largest planet in the Solar System?")); + + assertNotNull(response); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + // Should contain file search call and a message + assertTrue(response.output().stream().anyMatch(item -> item.isFileSearchCall())); + assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); + } finally { + Files.deleteIfExists(tempFile); + if (agent != null) { + agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()); + } + if (vectorStore != null) { + openAIClient.vectorStores().delete(vectorStore.id()); + } + if (uploadedFile != null) { + openAIClient.files().delete(uploadedFile.id()); + } + } + } +} From 2f62819ef133a5f5609209416cbd39370cd5c4fb Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Mon, 9 Mar 2026 11:47:02 +0100 Subject: [PATCH 11/22] Removed unused imports --- .../src/samples/java/com/azure/ai/agents/tools/McpAsync.java | 1 - .../java/com/azure/ai/agents/tools/McpWithConnectionAsync.java | 1 - .../src/test/java/com/azure/ai/agents/ToolsAsyncTests.java | 3 --- 3 files changed, 5 deletions(-) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java index bd36515e9769..26ba9880d50c 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java @@ -13,7 +13,6 @@ import com.azure.core.util.BinaryData; import com.azure.core.util.Configuration; import com.azure.identity.DefaultAzureCredentialBuilder; -import com.openai.models.responses.Response; import com.openai.models.responses.ResponseCreateParams; import com.openai.models.responses.ResponseInputItem; import com.openai.models.responses.ResponseOutputItem; diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionAsync.java index c54eb6ca6e03..d566b4d138f8 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionAsync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionAsync.java @@ -13,7 +13,6 @@ import com.azure.core.util.BinaryData; import com.azure.core.util.Configuration; import com.azure.identity.DefaultAzureCredentialBuilder; -import com.openai.models.responses.Response; import com.openai.models.responses.ResponseCreateParams; import com.openai.models.responses.ResponseInputItem; import com.openai.models.responses.ResponseOutputItem; diff --git a/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsAsyncTests.java b/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsAsyncTests.java index 89033e963f11..d484cffd49cd 100644 --- a/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsAsyncTests.java +++ b/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsAsyncTests.java @@ -16,11 +16,9 @@ import com.azure.ai.agents.models.WebSearchPreviewTool; import com.azure.core.http.HttpClient; import com.azure.core.util.BinaryData; -import com.openai.models.conversations.Conversation; import com.openai.models.files.FileCreateParams; import com.openai.models.files.FileObject; import com.openai.models.files.FilePurpose; -import com.openai.models.responses.Response; import com.openai.models.responses.ResponseCreateParams; import com.openai.models.responses.ResponseInputItem; import com.openai.models.responses.ResponseOutputItem; @@ -36,7 +34,6 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; From c75e0540f6e16f5cdb606fa97750e02756aaa2dc Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Mon, 9 Mar 2026 11:53:43 +0100 Subject: [PATCH 12/22] Merge test recordings and removed duplicate test file --- sdk/ai/azure-ai-agents/assets.json | 2 +- .../com/azure/ai/agents/OpenAPIToolTests.java | 93 ------------------- ...omptAgentDefinitionSerializationTests.java | 3 +- 3 files changed, 2 insertions(+), 96 deletions(-) delete mode 100644 sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/OpenAPIToolTests.java rename sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/{ => models}/PromptAgentDefinitionSerializationTests.java (99%) diff --git a/sdk/ai/azure-ai-agents/assets.json b/sdk/ai/azure-ai-agents/assets.json index 6d51c7bbb671..21c3f65f039c 100644 --- a/sdk/ai/azure-ai-agents/assets.json +++ b/sdk/ai/azure-ai-agents/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "java", "TagPrefix": "java/ai/azure-ai-agents", - "Tag": "java/ai/azure-ai-agents_ca44de768d" + "Tag": "java/ai/azure-ai-agents_30fb38a114" } diff --git a/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/OpenAPIToolTests.java b/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/OpenAPIToolTests.java deleted file mode 100644 index c1d814a798b8..000000000000 --- a/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/OpenAPIToolTests.java +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.ai.agents; - -import com.azure.ai.agents.models.AgentReference; -import com.azure.ai.agents.models.AgentVersionDetails; -import com.azure.ai.agents.models.OpenApiAnonymousAuthDetails; -import com.azure.ai.agents.models.OpenApiFunctionDefinition; -import com.azure.ai.agents.models.OpenApiTool; -import com.azure.ai.agents.models.PromptAgentDefinition; -import com.azure.core.http.HttpClient; -import com.azure.core.util.BinaryData; -import com.openai.models.conversations.Conversation; -import com.openai.models.conversations.items.ItemCreateParams; -import com.openai.models.responses.EasyInputMessage; -import com.openai.models.responses.Response; -import com.openai.models.responses.ResponseCreateParams; -import com.openai.models.responses.ResponseStatus; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Map; - -import static com.azure.ai.agents.TestUtils.DISPLAY_NAME_WITH_ARGUMENTS; -import static org.junit.jupiter.api.Assertions.*; - -public class OpenAPIToolTests extends ClientTestBase { - - private static final String AGENT_NAME = "openapi-tool-test-agent-java"; - - @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) - @MethodSource("com.azure.ai.agents.TestUtils#getTestParameters") - public void openApiToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serviceVersion) throws IOException { - AgentsClient agentsClient = getAgentsSyncClient(httpClient, serviceVersion); - ResponsesClient responsesClient = getResponsesSyncClient(httpClient, serviceVersion); - ConversationsClient conversationsClient = getConversationsSyncClient(httpClient, serviceVersion); - - // Load the OpenAPI spec from test resources - Map spec - = OpenApiFunctionDefinition.readSpecFromFile(TestUtils.getTestResourcePath("assets/httpbin_openapi.json")); - - OpenApiFunctionDefinition toolDefinition - = new OpenApiFunctionDefinition("httpbin_get", spec, new OpenApiAnonymousAuthDetails()) - .setDescription("Get request metadata from an OpenAPI endpoint."); - - PromptAgentDefinition agentDefinition - = new PromptAgentDefinition("gpt-4o").setInstructions("Use the OpenAPI tool for HTTP request metadata.") - .setTools(Arrays.asList(new OpenApiTool(toolDefinition))); - - AgentVersionDetails agentVersion = agentsClient.createAgentVersion(AGENT_NAME, agentDefinition); - assertNotNull(agentVersion); - assertNotNull(agentVersion.getId()); - assertEquals(AGENT_NAME, agentVersion.getName()); - - try { - // Create a conversation and add a user message - Conversation conversation = conversationsClient.getConversationService().create(); - assertNotNull(conversation); - assertNotNull(conversation.id()); - - conversationsClient.getConversationService() - .items() - .create(ItemCreateParams.builder() - .conversationId(conversation.id()) - .addItem(EasyInputMessage.builder() - .role(EasyInputMessage.Role.USER) - .content("Use the OpenAPI tool and summarize the returned URL and origin in one sentence.") - .build()) - .build()); - - // Create a response using the agent with the conversation - AgentReference agentReference - = new AgentReference(agentVersion.getName()).setVersion(agentVersion.getVersion()); - - ResponseCreateParams.Builder options = ResponseCreateParams.builder().maxOutputTokens(300L); - - Response response = responsesClient.createWithAgentConversation(agentReference, conversation.id(), options); - - assertNotNull(response); - assertTrue(response.id().startsWith("resp")); - assertTrue(response.status().isPresent()); - assertEquals(ResponseStatus.COMPLETED, response.status().get()); - assertFalse(response.output().isEmpty()); - assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); - } finally { - // Clean up - agentsClient.deleteAgentVersion(agentVersion.getName(), agentVersion.getVersion()); - } - } -} diff --git a/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/PromptAgentDefinitionSerializationTests.java b/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/models/PromptAgentDefinitionSerializationTests.java similarity index 99% rename from sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/PromptAgentDefinitionSerializationTests.java rename to sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/models/PromptAgentDefinitionSerializationTests.java index 7f335dd27877..7cfc9d323689 100644 --- a/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/PromptAgentDefinitionSerializationTests.java +++ b/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/models/PromptAgentDefinitionSerializationTests.java @@ -1,9 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -package com.azure.ai.agents; +package com.azure.ai.agents.models; -import com.azure.ai.agents.models.PromptAgentDefinition; import com.azure.json.JsonProviders; import com.azure.json.JsonReader; import com.azure.json.JsonWriter; From be4b6a8fc88de14be668939a4df941050e83aead Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Mon, 9 Mar 2026 13:23:17 +0100 Subject: [PATCH 13/22] Trying out cspell exception file --- sdk/ai/cspell.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 sdk/ai/cspell.yaml diff --git a/sdk/ai/cspell.yaml b/sdk/ai/cspell.yaml new file mode 100644 index 000000000000..9e437ff0ce52 --- /dev/null +++ b/sdk/ai/cspell.yaml @@ -0,0 +1,6 @@ +import: + - ../../.vscode/cspell.json +overrides: + - filename: "**/sdk/ai/azure-ai-agents/*" + words: + - gitmcp \ No newline at end of file From fc54db5cd7e0aaebc0df9a9924cb61d47fdafa63 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Mon, 9 Mar 2026 13:34:59 +0100 Subject: [PATCH 14/22] path fix --- sdk/ai/azure-ai-agents/README.md | 2 +- .../java/com/azure/ai/agents/tools/FunctionCallAsync.java | 2 ++ sdk/ai/cspell.yaml | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sdk/ai/azure-ai-agents/README.md b/sdk/ai/azure-ai-agents/README.md index 65df613160f7..9da1d40a6e95 100644 --- a/sdk/ai/azure-ai-agents/README.md +++ b/sdk/ai/azure-ai-agents/README.md @@ -322,7 +322,7 @@ OpenApiTool tool = new OpenApiTool( Define custom functions that allow agents to interact with external APIs, databases, or application logic: -```java +```java com.azure.ai.agents.define_function_call Map parameters = new HashMap<>(); parameters.put("type", BinaryData.fromString("\"object\"")); parameters.put("properties", BinaryData.fromString( diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java index dc001fac3ad0..279eba89fc2b 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java @@ -53,6 +53,7 @@ public static void main(String[] args) { // Create a FunctionTool with parameters schema // Use BinaryData.fromObject() to produce correct JSON types (not double-encoded strings) + // BEGIN: com.azure.ai.agents.define_function_call Map locationProp = new LinkedHashMap(); locationProp.put("type", "string"); locationProp.put("description", "The city and state, e.g. Seattle, WA"); @@ -78,6 +79,7 @@ public static void main(String[] args) { .setInstructions("You are a helpful assistant that can get weather information. " + "When asked about the weather, use the get_weather function to retrieve weather data.") .setTools(Collections.singletonList(tool)); + // END: com.azure.ai.agents.define_function_call agentsAsyncClient.createAgentVersion("function-call-agent", agentDefinition) .flatMap(agent -> { diff --git a/sdk/ai/cspell.yaml b/sdk/ai/cspell.yaml index 9e437ff0ce52..d8163c7781be 100644 --- a/sdk/ai/cspell.yaml +++ b/sdk/ai/cspell.yaml @@ -1,5 +1,5 @@ import: - - ../../.vscode/cspell.json + - ../../../.vscode/cspell.json overrides: - filename: "**/sdk/ai/azure-ai-agents/*" words: From 74fe4c7a33058e03d891e9479875a867b9ec9a81 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Mon, 9 Mar 2026 13:42:31 +0100 Subject: [PATCH 15/22] Feedback and cspell --- sdk/ai/azure-ai-agents/README.md | 30 +++++++++++++------ .../ai/agents/tools/FunctionCallAsync.java | 2 +- .../com/azure/ai/agents/tools/McpAsync.java | 2 ++ .../agents/tools/McpWithConnectionAsync.java | 2 +- .../agents/tools/McpWithConnectionSync.java | 2 +- .../com/azure/ai/agents/ToolsAsyncTests.java | 3 -- sdk/ai/cspell.yaml | 2 +- 7 files changed, 27 insertions(+), 16 deletions(-) diff --git a/sdk/ai/azure-ai-agents/README.md b/sdk/ai/azure-ai-agents/README.md index 9da1d40a6e95..91b034abdaac 100644 --- a/sdk/ai/azure-ai-agents/README.md +++ b/sdk/ai/azure-ai-agents/README.md @@ -290,10 +290,9 @@ See the full sample in [ComputerUseSync.java](https://github.com/Azure/azure-sdk Connect agents to external MCP servers: -```java +```java com.azure.ai.agents.built_in_mcp McpTool tool = new McpTool("api-specs") .setServerUrl("https://gitmcp.io/Azure/azure-rest-api-specs") - .setProjectConnectionId(mcpConnectionId) .setRequireApproval(BinaryData.fromObject("always")); ``` @@ -323,13 +322,26 @@ OpenApiTool tool = new OpenApiTool( Define custom functions that allow agents to interact with external APIs, databases, or application logic: ```java com.azure.ai.agents.define_function_call -Map parameters = new HashMap<>(); -parameters.put("type", BinaryData.fromString("\"object\"")); -parameters.put("properties", BinaryData.fromString( - "{\"location\":{\"type\":\"string\",\"description\":\"The city and state\"}}")); -parameters.put("required", BinaryData.fromString("[\"location\"]")); - -FunctionTool tool = new FunctionTool("get_weather", parameters, true); +Map locationProp = new LinkedHashMap(); +locationProp.put("type", "string"); +locationProp.put("description", "The city and state, e.g. Seattle, WA"); + +Map unitProp = new LinkedHashMap(); +unitProp.put("type", "string"); +unitProp.put("enum", Arrays.asList("celsius", "fahrenheit")); + +Map properties = new LinkedHashMap(); +properties.put("location", locationProp); +properties.put("unit", unitProp); + +Map parameters = new HashMap(); +parameters.put("type", BinaryData.fromObject("object")); +parameters.put("properties", BinaryData.fromObject(properties)); +parameters.put("required", BinaryData.fromObject(Arrays.asList("location", "unit"))); +parameters.put("additionalProperties", BinaryData.fromObject(false)); + +FunctionTool tool = new FunctionTool("get_weather", parameters, true) + .setDescription("Get the current weather in a given location"); ``` See the full sample in [FunctionCallingSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallingSample.java). diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java index 279eba89fc2b..ea9fbc56ab2e 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java @@ -74,12 +74,12 @@ public static void main(String[] args) { FunctionTool tool = new FunctionTool("get_weather", parameters, true) .setDescription("Get the current weather in a given location"); + // END: com.azure.ai.agents.define_function_call PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) .setInstructions("You are a helpful assistant that can get weather information. " + "When asked about the weather, use the get_weather function to retrieve weather data.") .setTools(Collections.singletonList(tool)); - // END: com.azure.ai.agents.define_function_call agentsAsyncClient.createAgentVersion("function-call-agent", agentDefinition) .flatMap(agent -> { diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java index 26ba9880d50c..456909d657e0 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java @@ -54,9 +54,11 @@ public static void main(String[] args) { // Create an MCP tool that connects to a remote MCP server // Uses gitmcp.io to expose a GitHub repository as an MCP-compatible server + // BEGIN: com.azure.ai.agents.built_in_mcp McpTool tool = new McpTool("api-specs") .setServerUrl("https://gitmcp.io/Azure/azure-rest-api-specs") .setRequireApproval(BinaryData.fromObject("always")); + // END: com.azure.ai.agents.built_in_mcp PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) .setInstructions("You are a helpful agent that can use MCP tools to assist users. " diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionAsync.java index d566b4d138f8..04fd7d2bf5d0 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionAsync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionAsync.java @@ -69,7 +69,7 @@ public static void main(String[] args) { return responsesAsyncClient.createWithAgent(agentReference, ResponseCreateParams.builder() - .input("What is my username in Github profile?")); + .input("What is my username in GitHub profile?")); }) .flatMap(response -> { AgentVersionDetails agent = agentRef.get(); diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSync.java index 6e9d75f098f0..d846d4b5385e 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSync.java @@ -78,7 +78,7 @@ public static void main(String[] args) { Response response = responsesClient.createWithAgentConversation( agentReference, conversation.id(), ResponseCreateParams.builder() - .input("What is my username in Github profile?")); + .input("What is my username in GitHub profile?")); // Process MCP approval requests: approve each one so the agent can proceed List approvals = new ArrayList<>(); diff --git a/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsAsyncTests.java b/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsAsyncTests.java index d484cffd49cd..95ec3857283c 100644 --- a/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsAsyncTests.java +++ b/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsAsyncTests.java @@ -364,9 +364,6 @@ public void fileSearchToolEndToEnd(HttpClient httpClient, AgentsServiceVersion s .setInstructions("You are a helpful assistant that searches uploaded files to answer questions.") .setTools(Collections.singletonList(tool)); - final FileObject uploadedFileFinal = uploadedFile; - final VectorStore vectorStoreFinal = vectorStore; - StepVerifier.create( agentsClient.createAgentVersion("file-search-test-agent-java-async", agentDefinition).flatMap(agent -> { agentRef.set(agent); diff --git a/sdk/ai/cspell.yaml b/sdk/ai/cspell.yaml index d8163c7781be..9e437ff0ce52 100644 --- a/sdk/ai/cspell.yaml +++ b/sdk/ai/cspell.yaml @@ -1,5 +1,5 @@ import: - - ../../../.vscode/cspell.json + - ../../.vscode/cspell.json overrides: - filename: "**/sdk/ai/azure-ai-agents/*" words: From 13e99208045c57d652c4da3f3c0db0212f3b9db9 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Mar 2026 13:50:41 +0100 Subject: [PATCH 16/22] =?UTF-8?q?Fix=20broken=20README=20sample=20links=20?= =?UTF-8?q?after=20*Sample.java=20=E2=86=92=20*Sync.java=20rename=20(#4833?= =?UTF-8?q?7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial plan * Fix README links: update *Sample.java to *Sync.java Co-authored-by: jpalvarezl <11056031+jpalvarezl@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jpalvarezl <11056031+jpalvarezl@users.noreply.github.com> --- sdk/ai/azure-ai-agents/README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sdk/ai/azure-ai-agents/README.md b/sdk/ai/azure-ai-agents/README.md index 91b034abdaac..b5e56f13dd90 100644 --- a/sdk/ai/azure-ai-agents/README.md +++ b/sdk/ai/azure-ai-agents/README.md @@ -230,7 +230,7 @@ Write and run Python code in a sandboxed environment, process files and work wit CodeInterpreterTool tool = new CodeInterpreterTool(); ``` -See the full sample in [CodeInterpreterSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterSample.java). +See the full sample in [CodeInterpreterSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterSync.java). --- @@ -242,7 +242,7 @@ Search through files in a vector store for knowledge retrieval: FileSearchTool tool = new FileSearchTool(Arrays.asList(vectorStoreId)); ``` -See the full sample in [FileSearchSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchSample.java). +See the full sample in [FileSearchSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchSync.java). --- @@ -257,7 +257,7 @@ ImageGenTool tool = new ImageGenTool() .setSize(ImageGenToolSize.fromString("1024x1024")); ``` -See the full sample in [ImageGenerationSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ImageGenerationSample.java). +See the full sample in [ImageGenerationSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ImageGenerationSync.java). --- @@ -269,7 +269,7 @@ Search the web for current information: WebSearchPreviewTool tool = new WebSearchPreviewTool(); ``` -See the full sample in [WebSearchSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchSample.java). +See the full sample in [WebSearchSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchSync.java). --- @@ -296,7 +296,7 @@ McpTool tool = new McpTool("api-specs") .setRequireApproval(BinaryData.fromObject("always")); ``` -See the full sample in [McpToolSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpToolSample.java). +See the full sample in [McpSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpSync.java). --- @@ -313,7 +313,7 @@ OpenApiTool tool = new OpenApiTool( .setDescription("Retrieve weather information for a location.")); ``` - +See the full sample in [OpenApiSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSync.java). --- @@ -344,7 +344,7 @@ FunctionTool tool = new FunctionTool("get_weather", parameters, true) .setDescription("Get the current weather in a given location"); ``` -See the full sample in [FunctionCallingSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallingSample.java). +See the full sample in [FunctionCallSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallSync.java). --- @@ -367,7 +367,7 @@ AzureAISearchTool tool = new AzureAISearchTool( .setQueryType(AzureAISearchQueryType.SIMPLE)))); ``` -See the full sample in [AzureAISearchSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchSample.java). +See the full sample in [AzureAISearchSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchSync.java). --- @@ -381,7 +381,7 @@ BingGroundingTool tool = new BingGroundingTool( new BingGroundingSearchConfiguration(bingConnectionId)))); ``` -See the full sample in [BingGroundingSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingSample.java). +See the full sample in [BingGroundingSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingSync.java). --- @@ -396,7 +396,7 @@ MicrosoftFabricPreviewTool tool = new MicrosoftFabricPreviewTool( new ToolProjectConnection(fabricConnectionId)))); ``` -See the full sample in [FabricSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricSample.java). +See the full sample in [FabricSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricSync.java). --- @@ -411,7 +411,7 @@ SharepointPreviewTool tool = new SharepointPreviewTool( new ToolProjectConnection(sharepointConnectionId)))); ``` -See the full sample in [SharePointGroundingSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingSample.java). +See the full sample in [SharePointGroundingSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingSync.java). --- @@ -425,7 +425,7 @@ BrowserAutomationPreviewTool tool = new BrowserAutomationPreviewTool( new BrowserAutomationToolConnectionParameters(connectionId))); ``` -See the full sample in [BrowserAutomationSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationSample.java). +See the full sample in [BrowserAutomationSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationSync.java). --- @@ -438,7 +438,7 @@ A2APreviewTool tool = new A2APreviewTool() .setProjectConnectionId(a2aConnectionId); ``` -See the full sample in [AgentToAgentSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AgentToAgentSample.java). +See the full sample in [AgentToAgentSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AgentToAgentSync.java). --- From 4191fc513678cf5a022a33da2053950cc59ea5c2 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Mon, 9 Mar 2026 13:52:42 +0100 Subject: [PATCH 17/22] Moved cspell file --- sdk/ai/{ => azure-ai-agents}/cspell.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename sdk/ai/{ => azure-ai-agents}/cspell.yaml (72%) diff --git a/sdk/ai/cspell.yaml b/sdk/ai/azure-ai-agents/cspell.yaml similarity index 72% rename from sdk/ai/cspell.yaml rename to sdk/ai/azure-ai-agents/cspell.yaml index 9e437ff0ce52..d8163c7781be 100644 --- a/sdk/ai/cspell.yaml +++ b/sdk/ai/azure-ai-agents/cspell.yaml @@ -1,5 +1,5 @@ import: - - ../../.vscode/cspell.json + - ../../../.vscode/cspell.json overrides: - filename: "**/sdk/ai/azure-ai-agents/*" words: From bca4013400d55760c1228beb6c316bb1b2eab783 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Mon, 9 Mar 2026 14:10:53 +0100 Subject: [PATCH 18/22] More PR feedack --- .../java/com/azure/ai/agents/tools/MemorySearchAsync.java | 6 +++--- .../java/com/azure/ai/agents/tools/OpenApiAsync.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchAsync.java index 39c575fabc28..d9546dd7f20c 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchAsync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchAsync.java @@ -119,15 +119,15 @@ public static void main(String[] args) throws Exception { }) .doOnNext(response -> System.out.println("Response: " + response.output())) .doFinally(signal -> { - // Cleanup (sync) + // Cleanup — await conversation deletes before proceeding try { String c1 = firstConvRef.get(); if (c1 != null) { - conversationsAsyncClient.getConversationServiceAsync().delete(c1); + conversationsAsyncClient.getConversationServiceAsync().delete(c1).join(); } String c2 = secondConvRef.get(); if (c2 != null) { - conversationsAsyncClient.getConversationServiceAsync().delete(c2); + conversationsAsyncClient.getConversationServiceAsync().delete(c2).join(); } } catch (Exception ignored) { // best-effort diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiAsync.java index e0dbe24c73ba..0348a287c1ad 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiAsync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiAsync.java @@ -54,7 +54,7 @@ public static void main(String[] args) throws Exception { OpenApiTool openApiTool = new OpenApiTool( new OpenApiFunctionDefinition("httpbin_get", spec, new OpenApiAnonymousAuthDetails()) - .setDescription("Retrieve weather information for a location.")); + .setDescription("Get request metadata from an OpenAPI endpoint.")); PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) .setInstructions("You are a helpful assistant. Use the OpenAPI tool when asked to call an API.") From ef7032cafc9cc06030a21f216868780ac5e920a4 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Mon, 9 Mar 2026 14:47:35 +0100 Subject: [PATCH 19/22] CHANGELOG updates --- sdk/ai/azure-ai-agents/CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/ai/azure-ai-agents/CHANGELOG.md b/sdk/ai/azure-ai-agents/CHANGELOG.md index 69e6ac4c93d0..d2cadc69781b 100644 --- a/sdk/ai/azure-ai-agents/CHANGELOG.md +++ b/sdk/ai/azure-ai-agents/CHANGELOG.md @@ -5,8 +5,8 @@ ### Features Added - Added `readSpecFromFile(Path)` static convenience method to `OpenApiFunctionDefinition` for loading OpenAPI specification JSON files as the `Map` required by the constructor, eliminating the need for manual `JsonReader`/`BinaryData` wiring. -- Added new `OpenApiSample` demonstrating end-to-end OpenAPI tool integration: loading a spec file, creating an agent with an `OpenApiTool`, and invoking an external API via conversation. -- Added new tool samples for parity with the Python SDK: `AzureFunctionSample`, `BingCustomSearchSample`, `MemorySearchSample`, `McpWithConnectionSample`, and `OpenApiWithConnectionSample`. +- Added new `OpenApiSync`/`OpenApiAsync` samples demonstrating end-to-end OpenAPI tool integration: loading a spec file, creating an agent with an `OpenApiTool`, and invoking an external API via conversation. +- Added new tool samples for parity with the Python SDK: `AzureFunctionSync`/`AzureFunctionAsync`, `BingCustomSearchSync`/`BingCustomSearchAsync`, `MemorySearchSync`/`MemorySearchAsync`, `McpWithConnectionSync`/`McpWithConnectionAsync`, and `OpenApiWithConnectionSync`/`OpenApiWithConnectionAsync`. ### Breaking Changes @@ -14,7 +14,7 @@ ### Other Changes -- Added `OpenAPIToolTests` with recorded end-to-end test coverage for the OpenAPI tool flow. +- Added `ToolsTests` and `ToolsAsyncTests` with recorded end-to-end test coverage for OpenAPI, Code Interpreter, Function Call, Web Search, MCP, and File Search tools. ## 2.0.0-beta.2 (2026-03-04) From 4365d9899f3a1c98cf0933569e660ae6e9d521f1 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Mon, 9 Mar 2026 15:12:42 +0100 Subject: [PATCH 20/22] More readme updates --- sdk/ai/azure-ai-agents/README.md | 164 +++++++++++++++--- sdk/ai/azure-ai-agents/UPDATE_README_LINKS.md | 87 ---------- .../ai/agents/tools/AgentToAgentSync.java | 2 + .../ai/agents/tools/AzureAISearchSync.java | 2 + .../ai/agents/tools/AzureFunctionSync.java | 2 + .../ai/agents/tools/BingCustomSearchSync.java | 2 + .../ai/agents/tools/BingGroundingSync.java | 2 + .../agents/tools/BrowserAutomationSync.java | 2 + .../ai/agents/tools/CodeInterpreterSync.java | 2 + .../ai/agents/tools/ComputerUseSync.java | 2 + .../com/azure/ai/agents/tools/FabricSync.java | 2 + .../azure/ai/agents/tools/FileSearchSync.java | 2 + .../ai/agents/tools/FunctionCallAsync.java | 1 - .../ai/agents/tools/ImageGenerationSync.java | 2 + .../com/azure/ai/agents/tools/McpAsync.java | 2 - .../com/azure/ai/agents/tools/McpSync.java | 2 + .../agents/tools/McpWithConnectionSync.java | 2 + .../ai/agents/tools/MemorySearchSync.java | 2 + .../azure/ai/agents/tools/OpenApiSync.java | 15 +- .../tools/OpenApiWithConnectionSync.java | 2 + .../agents/tools/SharePointGroundingSync.java | 2 + .../azure/ai/agents/tools/WebSearchSync.java | 2 + 22 files changed, 183 insertions(+), 120 deletions(-) delete mode 100644 sdk/ai/azure-ai-agents/UPDATE_README_LINKS.md diff --git a/sdk/ai/azure-ai-agents/README.md b/sdk/ai/azure-ai-agents/README.md index b5e56f13dd90..c7b4fd893f81 100644 --- a/sdk/ai/azure-ai-agents/README.md +++ b/sdk/ai/azure-ai-agents/README.md @@ -226,7 +226,8 @@ These tools work immediately without requiring external connections. Write and run Python code in a sandboxed environment, process files and work with diverse data formats. -```java +```java com.azure.ai.agents.define_code_interpreter +// Create a CodeInterpreterTool with default auto container configuration CodeInterpreterTool tool = new CodeInterpreterTool(); ``` @@ -238,8 +239,9 @@ See the full sample in [CodeInterpreterSync.java](https://github.com/Azure/azure Search through files in a vector store for knowledge retrieval: -```java -FileSearchTool tool = new FileSearchTool(Arrays.asList(vectorStoreId)); +```java com.azure.ai.agents.define_file_search +// Create a FileSearchTool with the vector store ID +FileSearchTool tool = new FileSearchTool(Collections.singletonList(vectorStore.id())); ``` See the full sample in [FileSearchSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchSync.java). @@ -250,8 +252,9 @@ See the full sample in [FileSearchSync.java](https://github.com/Azure/azure-sdk- Generate images from text descriptions: -```java -ImageGenTool tool = new ImageGenTool() +```java com.azure.ai.agents.define_image_generation +// Create image generation tool with model, quality, and size +ImageGenTool imageGenTool = new ImageGenTool() .setModel(ImageGenToolModel.fromString(imageModel)) .setQuality(ImageGenToolQuality.LOW) .setSize(ImageGenToolSize.fromString("1024x1024")); @@ -265,7 +268,8 @@ See the full sample in [ImageGenerationSync.java](https://github.com/Azure/azure Search the web for current information: -```java +```java com.azure.ai.agents.define_web_search +// Create a WebSearchPreviewTool WebSearchPreviewTool tool = new WebSearchPreviewTool(); ``` @@ -277,9 +281,12 @@ See the full sample in [WebSearchSync.java](https://github.com/Azure/azure-sdk-f Interact with computer interfaces through simulated actions and screenshots: -```java +```java com.azure.ai.agents.define_computer_use ComputerUsePreviewTool tool = new ComputerUsePreviewTool( - ComputerEnvironment.WINDOWS, 1026, 769); + ComputerEnvironment.WINDOWS, + 1026, + 769 +); ``` See the full sample in [ComputerUseSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ComputerUseSync.java). @@ -291,6 +298,7 @@ See the full sample in [ComputerUseSync.java](https://github.com/Azure/azure-sdk Connect agents to external MCP servers: ```java com.azure.ai.agents.built_in_mcp +// Uses gitmcp.io to expose a GitHub repository as an MCP-compatible server McpTool tool = new McpTool("api-specs") .setServerUrl("https://gitmcp.io/Azure/azure-rest-api-specs") .setRequireApproval(BinaryData.fromObject("always")); @@ -304,13 +312,17 @@ See the full sample in [McpSync.java](https://github.com/Azure/azure-sdk-for-jav Call external APIs defined by OpenAPI specifications without additional client-side code: -```java +```java com.azure.ai.agents.define_openapi +// Load the OpenAPI spec from a JSON file Map spec = OpenApiFunctionDefinition.readSpecFromFile( - Paths.get("path/to/openapi_spec.json")); + SampleUtils.getResourcePath("assets/httpbin_openapi.json")); OpenApiTool tool = new OpenApiTool( - new OpenApiFunctionDefinition("get_weather", spec, new OpenApiAnonymousAuthDetails()) - .setDescription("Retrieve weather information for a location.")); + new OpenApiFunctionDefinition( + "httpbin_get", + spec, + new OpenApiAnonymousAuthDetails()) + .setDescription("Get request metadata from an OpenAPI endpoint.")); ``` See the full sample in [OpenApiSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSync.java). @@ -348,6 +360,44 @@ See the full sample in [FunctionCallSync.java](https://github.com/Azure/azure-sd --- +##### **Azure Functions** + +Integrate Azure Functions with agents to extend capabilities via serverless compute. Functions are invoked through Azure Storage Queue triggers, allowing asynchronous execution of custom logic: + +```java com.azure.ai.agents.define_azure_function +// Create Azure Function tool with Storage Queue bindings +AzureFunctionTool azureFunctionTool = new AzureFunctionTool( + new AzureFunctionDefinition( + new AzureFunctionDefinitionDetails("queue_trigger", parameters) + .setDescription("Get weather for a given location"), + new AzureFunctionBinding( + new AzureFunctionStorageQueue(queueServiceEndpoint, inputQueueName)), + new AzureFunctionBinding( + new AzureFunctionStorageQueue(queueServiceEndpoint, outputQueueName)) + ) +); +``` + +*After calling `responsesClient.createWithAgent()`, the agent enqueues function arguments to the input queue. Your Azure Function processes the request and returns results via the output queue.* + +See the full sample in [AzureFunctionSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSync.java). + +--- + +##### **Memory Search (Preview)** ([documentation](https://learn.microsoft.com/azure/foundry/agents/concepts/what-is-memory)) + +The Memory Search tool adds memory to an agent, allowing the agent's AI model to search for past information related to the current user prompt: + +```java com.azure.ai.agents.define_memory_search +// Create memory search tool +MemorySearchPreviewTool tool = new MemorySearchPreviewTool(memoryStore.getName(), scope) + .setUpdateDelaySeconds(1); +``` + +See the full sample in [MemorySearchSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSync.java) showing how to create an agent with a memory store and use it across multiple conversations. + +--- + #### Connection-Based Tools These tools require configuring connections in your Microsoft Foundry project and use a `projectConnectionId`. @@ -358,13 +408,16 @@ These tools require configuring connections in your Microsoft Foundry project an Integrate with Azure AI Search indexes for powerful knowledge retrieval and semantic search capabilities: -```java -AzureAISearchTool tool = new AzureAISearchTool( +```java com.azure.ai.agents.define_azure_ai_search +// Create Azure AI Search tool with index configuration +AzureAISearchTool aiSearchTool = new AzureAISearchTool( new AzureAISearchToolResource(Arrays.asList( new AISearchIndexResource() .setProjectConnectionId(connectionId) .setIndexName(indexName) - .setQueryType(AzureAISearchQueryType.SIMPLE)))); + .setQueryType(AzureAISearchQueryType.SIMPLE) + )) +); ``` See the full sample in [AzureAISearchSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchSync.java). @@ -375,25 +428,50 @@ See the full sample in [AzureAISearchSync.java](https://github.com/Azure/azure-s Ground agent responses with real-time web search results from Bing to provide up-to-date information: -```java -BingGroundingTool tool = new BingGroundingTool( +```java com.azure.ai.agents.define_bing_grounding +// Create Bing grounding tool with connection configuration +BingGroundingTool bingTool = new BingGroundingTool( new BingGroundingSearchToolParameters(Arrays.asList( - new BingGroundingSearchConfiguration(bingConnectionId)))); + new BingGroundingSearchConfiguration(bingConnectionId) + )) +); ``` See the full sample in [BingGroundingSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingSync.java). --- +##### **Bing Custom Search (Preview)** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/bing-tools?pivots=java)) + +**Warning**: Grounding with Bing Custom Search uses Grounding with Bing, which has additional costs and terms: [terms of use](https://www.microsoft.com/bing/apis/grounding-legal-enterprise) and [privacy statement](https://go.microsoft.com/fwlink/?LinkId=521839&clcid=0x409). Customer data will flow outside the Azure compliance boundary. + +Use custom-configured Bing search instances for domain-specific or filtered web search results: + +```java com.azure.ai.agents.define_bing_custom_search +// Create Bing Custom Search tool with connection and instance configuration +BingCustomSearchPreviewTool bingCustomSearchTool = new BingCustomSearchPreviewTool( + new BingCustomSearchToolParameters(Arrays.asList( + new BingCustomSearchConfiguration(connectionId, instanceName) + )) +); +``` + +See the full sample in [BingCustomSearchSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSync.java). + +--- + ##### **Microsoft Fabric (Preview)** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/fabric?pivots=java)) Query data from Microsoft Fabric data sources: -```java -MicrosoftFabricPreviewTool tool = new MicrosoftFabricPreviewTool( +```java com.azure.ai.agents.define_fabric +// Create Microsoft Fabric tool with connection configuration +MicrosoftFabricPreviewTool fabricTool = new MicrosoftFabricPreviewTool( new FabricDataAgentToolParameters() .setProjectConnections(Arrays.asList( - new ToolProjectConnection(fabricConnectionId)))); + new ToolProjectConnection(fabricConnectionId) + )) +); ``` See the full sample in [FabricSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricSync.java). @@ -404,11 +482,14 @@ See the full sample in [FabricSync.java](https://github.com/Azure/azure-sdk-for- Search through SharePoint documents for grounding: -```java -SharepointPreviewTool tool = new SharepointPreviewTool( +```java com.azure.ai.agents.define_sharepoint +// Create SharePoint grounding tool with connection configuration +SharepointPreviewTool sharepointTool = new SharepointPreviewTool( new SharepointGroundingToolParameters() .setProjectConnections(Arrays.asList( - new ToolProjectConnection(sharepointConnectionId)))); + new ToolProjectConnection(sharepointConnectionId) + )) +); ``` See the full sample in [SharePointGroundingSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingSync.java). @@ -442,6 +523,41 @@ See the full sample in [AgentToAgentSync.java](https://github.com/Azure/azure-sd --- +##### **MCP with Project Connection** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/model-context-protocol?pivots=java)) + +MCP integration using project-specific connections for accessing connected MCP servers: + +```java com.azure.ai.agents.define_mcp_with_connection +// Create MCP tool with project connection authentication +McpTool mcpTool = new McpTool("api-specs") + .setServerUrl("https://api.githubcopilot.com/mcp") + .setProjectConnectionId(mcpConnectionId) + .setRequireApproval(BinaryData.fromObject("always")); +``` + +See the full sample in [McpWithConnectionSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSync.java). + +--- + +##### **OpenAPI with Project Connection** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/openapi?pivots=java)) + +Call external APIs defined by OpenAPI specifications using project connection authentication: + +```java com.azure.ai.agents.define_openapi_with_connection +// Create OpenAPI tool with project connection authentication +OpenApiTool openApiTool = new OpenApiTool( + new OpenApiFunctionDefinition( + "httpbin_get", + spec, + new OpenApiProjectConnectionAuthDetails( + new OpenApiProjectConnectionSecurityScheme(connectionId))) + .setDescription("Get request metadata from an OpenAPI endpoint.")); +``` + +See the full sample in [OpenApiWithConnectionSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSync.java). + +--- + ### Service API versions The client library targets the latest service API version by default. diff --git a/sdk/ai/azure-ai-agents/UPDATE_README_LINKS.md b/sdk/ai/azure-ai-agents/UPDATE_README_LINKS.md deleted file mode 100644 index 09f3ed36e0e5..000000000000 --- a/sdk/ai/azure-ai-agents/UPDATE_README_LINKS.md +++ /dev/null @@ -1,87 +0,0 @@ -# README Link Updates — Pending Sample Merge - -These README tool sections need sample links added **after** the corresponding `.java` files are checked into `main`. - -CI rejects `https://github.com/Azure/azure-sdk-for-java/tree/main/...` URLs that point to files not yet on `main`, so these links must be added in a follow-up commit. - -## Samples not yet on `main` - -All tool samples were renamed from `*Sample.java` / `*Agent.java` to `*Sync.java` / `*Async.java`. -This means **every** README sample link will need updating once the new files land on `main`. - -### Renamed samples (exist on `main` under old names) - -| Old Name (on `main`) | New Name | README Section | -|---|---|---| -| `CodeInterpreterSample.java` | `CodeInterpreterSync.java` | **Code Interpreter** | -| `FileSearchSample.java` | `FileSearchSync.java` | **File Search** | -| `ImageGenerationSample.java` | `ImageGenerationSync.java` | **Image Generation** | -| `WebSearchSample.java` | `WebSearchSync.java` | **Web Search (Preview)** | -| `ComputerUseSync.java` | `ComputerUseSync.java` | **Computer Use** (unchanged) | -| `McpToolSample.java` | `McpSync.java` | **MCP** | -| `FunctionCallingSample.java` | `FunctionCallSync.java` | **Function Tool** | -| `AzureAISearchSample.java` | `AzureAISearchSync.java` | **Azure AI Search** | -| `BingGroundingSample.java` | `BingGroundingSync.java` | **Bing Grounding** | -| `FabricSample.java` | `FabricSync.java` | **Microsoft Fabric** | -| `SharePointGroundingSample.java` | `SharePointGroundingSync.java` | **Microsoft SharePoint** | -| `BrowserAutomationSample.java` | `BrowserAutomationSync.java` | **Browser Automation** | -| `AgentToAgentSample.java` | `AgentToAgentSync.java` | **Agent-to-Agent (A2A)** | - -### Brand-new samples (not on `main` at all) - -| Sample File | README Section | -|---|---| -| `OpenApiSync.java` | **OpenAPI** (restore link — currently HTML comment) | -| `AzureFunctionSync.java` | **Azure Functions** (new Built-in section) | -| `MemorySearchSync.java` | **Memory Search (Preview)** (new Built-in section) | -| `BingCustomSearchSync.java` | **Bing Custom Search (Preview)** (new Connection-Based section) | -| `McpWithConnectionSync.java` | **MCP with Project Connection** (new Connection-Based section) | -| `OpenApiWithConnectionSync.java` | **OpenAPI with Project Connection** (new Connection-Based section) | - -### Deleted files (remove old links from `main`) - -| Old Name (on `main`) | Replaced By | -|---|---| -| `CodeInterpreterAgent.java` | `CodeInterpreterSync.java` | -| `CodeInterpreterAgentAsync.java` | `CodeInterpreterAsync.java` | -| `FunctionCallAgent.java` | `FunctionCallSync.java` | -| `FunctionCallAgentAsync.java` | `FunctionCallAsync.java` | -| `McpAgent.java` | `McpSync.java` | -| `McpAgentAsync.java` | `McpAsync.java` | -| `WebSearchAgent.java` | `WebSearchSync.java` | -| `WebSearchAgentAsync.java` | `WebSearchAsync.java` | -| `FileSearchAgent.java` | `FileSearchSync.java` | -| `FunctionCallingSample.java` | `FunctionCallSync.java` | -| `McpToolSample.java` | `McpSync.java` | - -## What to update in README - -### 1. Update all existing sample links (renamed files) - -Replace each `*Sample.java` / `*Agent.java` link with the corresponding `*Sync.java`: - -``` -CodeInterpreterSample.java → CodeInterpreterSync.java -FileSearchSample.java → FileSearchSync.java -ImageGenerationSample.java → ImageGenerationSync.java -WebSearchSample.java → WebSearchSync.java -McpToolSample.java → McpSync.java -FunctionCallingSample.java → FunctionCallSync.java -AzureAISearchSample.java → AzureAISearchSync.java -BingGroundingSample.java → BingGroundingSync.java -FabricSample.java → FabricSync.java -SharePointGroundingSample.java → SharePointGroundingSync.java -BrowserAutomationSample.java → BrowserAutomationSync.java -AgentToAgentSample.java → AgentToAgentSync.java -``` - -### 2. Restore OpenAPI link - -Replace the `` comment with: -```markdown -See the full sample in [OpenApiSync.java](...tools/OpenApiSync.java). -``` - -### 3. Add 5 new tool sections - -See previous version of this file for the exact markdown snippets. Update file names from `*Sample.java` to `*Sync.java`. diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AgentToAgentSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AgentToAgentSync.java index 64e4e41f59fe..8ac3c6ed9e1c 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AgentToAgentSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AgentToAgentSync.java @@ -41,9 +41,11 @@ public static void main(String[] args) { AgentsClient agentsClient = builder.buildAgentsClient(); ResponsesClient responsesClient = builder.buildResponsesClient(); + // BEGIN: com.azure.ai.agents.define_agent_to_agent // Create agent-to-agent tool with connection ID A2APreviewTool a2aTool = new A2APreviewTool() .setProjectConnectionId(a2aConnectionId); + // END: com.azure.ai.agents.define_agent_to_agent // Create agent with agent-to-agent tool PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchSync.java index 489cd79cba18..6fac9eb704e4 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureAISearchSync.java @@ -47,6 +47,7 @@ public static void main(String[] args) { AgentsClient agentsClient = builder.buildAgentsClient(); ResponsesClient responsesClient = builder.buildResponsesClient(); + // BEGIN: com.azure.ai.agents.define_azure_ai_search // Create Azure AI Search tool with index configuration AzureAISearchTool aiSearchTool = new AzureAISearchTool( new AzureAISearchToolResource(Arrays.asList( @@ -56,6 +57,7 @@ public static void main(String[] args) { .setQueryType(AzureAISearchQueryType.SIMPLE) )) ); + // END: com.azure.ai.agents.define_azure_ai_search // Create agent with AI Search tool PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSync.java index 9a488d83d0c0..b8025b3de805 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSync.java @@ -67,6 +67,7 @@ public static void main(String[] args) { parameters.put("type", BinaryData.fromObject("object")); parameters.put("properties", BinaryData.fromObject(props)); + // BEGIN: com.azure.ai.agents.define_azure_function // Create Azure Function tool with Storage Queue bindings AzureFunctionTool azureFunctionTool = new AzureFunctionTool( new AzureFunctionDefinition( @@ -78,6 +79,7 @@ public static void main(String[] args) { new AzureFunctionStorageQueue(queueServiceEndpoint, outputQueueName)) ) ); + // END: com.azure.ai.agents.define_azure_function // Create agent with Azure Function tool PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSync.java index 7f23f41b4941..994b271bf04f 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSync.java @@ -51,12 +51,14 @@ public static void main(String[] args) { AgentsClient agentsClient = builder.buildAgentsClient(); ResponsesClient responsesClient = builder.buildResponsesClient(); + // BEGIN: com.azure.ai.agents.define_bing_custom_search // Create Bing Custom Search tool with connection and instance configuration BingCustomSearchPreviewTool bingCustomSearchTool = new BingCustomSearchPreviewTool( new BingCustomSearchToolParameters(Arrays.asList( new BingCustomSearchConfiguration(connectionId, instanceName) )) ); + // END: com.azure.ai.agents.define_bing_custom_search // Create agent with Bing Custom Search tool PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingSync.java index 851bad795aae..fedf8f04a490 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingGroundingSync.java @@ -44,12 +44,14 @@ public static void main(String[] args) { AgentsClient agentsClient = builder.buildAgentsClient(); ResponsesClient responsesClient = builder.buildResponsesClient(); + // BEGIN: com.azure.ai.agents.define_bing_grounding // Create Bing grounding tool with connection configuration BingGroundingTool bingTool = new BingGroundingTool( new BingGroundingSearchToolParameters(Arrays.asList( new BingGroundingSearchConfiguration(bingConnectionId) )) ); + // END: com.azure.ai.agents.define_bing_grounding // Create agent with Bing grounding tool PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationSync.java index 29d224f3818c..1199545f954c 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationSync.java @@ -43,12 +43,14 @@ public static void main(String[] args) { AgentsClient agentsClient = builder.buildAgentsClient(); ResponsesClient responsesClient = builder.buildResponsesClient(); + // BEGIN: com.azure.ai.agents.define_browser_automation // Create browser automation tool with connection configuration BrowserAutomationPreviewTool browserTool = new BrowserAutomationPreviewTool( new BrowserAutomationToolParameters( new BrowserAutomationToolConnectionParameters(connectionId) ) ); + // END: com.azure.ai.agents.define_browser_automation // Create agent with browser automation tool PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterSync.java index 897253e761e1..c5934156a4a4 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterSync.java @@ -45,8 +45,10 @@ public static void main(String[] args) { AgentVersionDetails agent = null; try { + // BEGIN: com.azure.ai.agents.define_code_interpreter // Create a CodeInterpreterTool with default auto container configuration CodeInterpreterTool tool = new CodeInterpreterTool(); + // END: com.azure.ai.agents.define_code_interpreter // Create the agent definition with Code Interpreter tool enabled PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ComputerUseSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ComputerUseSync.java index 6737655860ab..013d5e47cf96 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ComputerUseSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ComputerUseSync.java @@ -86,11 +86,13 @@ public static void main(String[] args) { AgentVersionDetails agent = null; try { + // BEGIN: com.azure.ai.agents.define_computer_use ComputerUsePreviewTool tool = new ComputerUsePreviewTool( ComputerEnvironment.WINDOWS, 1026, 769 ); + // END: com.azure.ai.agents.define_computer_use PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) .setInstructions("You are a computer automation assistant." diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricSync.java index 3e6460a9730a..63e3b9c990a5 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FabricSync.java @@ -44,6 +44,7 @@ public static void main(String[] args) { AgentsClient agentsClient = builder.buildAgentsClient(); ResponsesClient responsesClient = builder.buildResponsesClient(); + // BEGIN: com.azure.ai.agents.define_fabric // Create Microsoft Fabric tool with connection configuration MicrosoftFabricPreviewTool fabricTool = new MicrosoftFabricPreviewTool( new FabricDataAgentToolParameters() @@ -51,6 +52,7 @@ public static void main(String[] args) { new ToolProjectConnection(fabricConnectionId) )) ); + // END: com.azure.ai.agents.define_fabric // Create agent with Fabric tool PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchSync.java index b84bf3802360..814d5cd1ad2d 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FileSearchSync.java @@ -91,8 +91,10 @@ public static void main(String[] args) { System.out.println("Waiting for vector store to process files..."); Thread.sleep(5000); + // BEGIN: com.azure.ai.agents.define_file_search // Create a FileSearchTool with the vector store ID FileSearchTool tool = new FileSearchTool(Collections.singletonList(vectorStore.id())); + // END: com.azure.ai.agents.define_file_search PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) .setInstructions("You are a helpful assistant that can search through uploaded files to answer questions. " diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java index ea9fbc56ab2e..59d8eef799bb 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/FunctionCallAsync.java @@ -75,7 +75,6 @@ public static void main(String[] args) { FunctionTool tool = new FunctionTool("get_weather", parameters, true) .setDescription("Get the current weather in a given location"); // END: com.azure.ai.agents.define_function_call - PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) .setInstructions("You are a helpful assistant that can get weather information. " + "When asked about the weather, use the get_weather function to retrieve weather data.") diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ImageGenerationSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ImageGenerationSync.java index 3c21be19a30e..96dccd43388d 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ImageGenerationSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/ImageGenerationSync.java @@ -44,11 +44,13 @@ public static void main(String[] args) { AgentsClient agentsClient = builder.buildAgentsClient(); ResponsesClient responsesClient = builder.buildResponsesClient(); + // BEGIN: com.azure.ai.agents.define_image_generation // Create image generation tool with model, quality, and size ImageGenTool imageGenTool = new ImageGenTool() .setModel(ImageGenToolModel.fromString(imageModel)) .setQuality(ImageGenToolQuality.LOW) .setSize(ImageGenToolSize.fromString("1024x1024")); + // END: com.azure.ai.agents.define_image_generation // Create agent with image generation tool PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java index 456909d657e0..26ba9880d50c 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAsync.java @@ -54,11 +54,9 @@ public static void main(String[] args) { // Create an MCP tool that connects to a remote MCP server // Uses gitmcp.io to expose a GitHub repository as an MCP-compatible server - // BEGIN: com.azure.ai.agents.built_in_mcp McpTool tool = new McpTool("api-specs") .setServerUrl("https://gitmcp.io/Azure/azure-rest-api-specs") .setRequireApproval(BinaryData.fromObject("always")); - // END: com.azure.ai.agents.built_in_mcp PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) .setInstructions("You are a helpful agent that can use MCP tools to assist users. " diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpSync.java index 15dfe84ccaf8..75cf8157bf22 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpSync.java @@ -52,10 +52,12 @@ public static void main(String[] args) { try { // Create an MCP tool that connects to a remote MCP server + // BEGIN: com.azure.ai.agents.built_in_mcp // Uses gitmcp.io to expose a GitHub repository as an MCP-compatible server McpTool tool = new McpTool("api-specs") .setServerUrl("https://gitmcp.io/Azure/azure-rest-api-specs") .setRequireApproval(BinaryData.fromObject("always")); + // END: com.azure.ai.agents.built_in_mcp // Create the agent definition with MCP tool enabled PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSync.java index d846d4b5385e..c28d421a8a14 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSync.java @@ -53,11 +53,13 @@ public static void main(String[] args) { ResponsesClient responsesClient = builder.buildResponsesClient(); ConversationsClient conversationsClient = builder.buildConversationsClient(); + // BEGIN: com.azure.ai.agents.define_mcp_with_connection // Create MCP tool with project connection authentication McpTool mcpTool = new McpTool("api-specs") .setServerUrl("https://api.githubcopilot.com/mcp") .setProjectConnectionId(mcpConnectionId) .setRequireApproval(BinaryData.fromObject("always")); + // END: com.azure.ai.agents.define_mcp_with_connection // Create agent with MCP tool PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSync.java index 5650439a9dee..7e86048091ed 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSync.java @@ -73,9 +73,11 @@ public static void main(String[] args) { memoryStoreName, definition, "Example memory store for conversations", null); System.out.printf("Created memory store: %s (%s)%n", memoryStore.getName(), memoryStore.getId()); + // BEGIN: com.azure.ai.agents.define_memory_search // Create memory search tool MemorySearchPreviewTool tool = new MemorySearchPreviewTool(memoryStore.getName(), scope) .setUpdateDelaySeconds(1); + // END: com.azure.ai.agents.define_memory_search // Create agent with memory search tool PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSync.java index 55ee12172ecc..4910852e68cc 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSync.java @@ -52,19 +52,22 @@ public static void main(String[] args) throws Exception { ConversationsClient conversationsClient = builder.buildConversationsClient(); + // BEGIN: com.azure.ai.agents.define_openapi // Load the OpenAPI spec from a JSON file Map spec = OpenApiFunctionDefinition.readSpecFromFile( SampleUtils.getResourcePath("assets/httpbin_openapi.json")); - OpenApiFunctionDefinition toolDefinition = new OpenApiFunctionDefinition( - "httpbin_get", - spec, - new OpenApiAnonymousAuthDetails()) - .setDescription("Get request metadata from an OpenAPI endpoint."); + OpenApiTool tool = new OpenApiTool( + new OpenApiFunctionDefinition( + "httpbin_get", + spec, + new OpenApiAnonymousAuthDetails()) + .setDescription("Get request metadata from an OpenAPI endpoint.")); + // END: com.azure.ai.agents.define_openapi PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) .setInstructions("Use the OpenAPI tool for HTTP request metadata.") - .setTools(Arrays.asList(new OpenApiTool(toolDefinition))); + .setTools(Arrays.asList(tool)); AgentVersionDetails agentVersion = agentsClient.createAgentVersion("openapi-agent", agentDefinition); System.out.println("Agent: " + agentVersion.getName() + ", version: " + agentVersion.getVersion()); diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSync.java index 049af351f829..46cfb576cc3d 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSync.java @@ -57,6 +57,7 @@ public static void main(String[] args) throws Exception { Map spec = OpenApiFunctionDefinition.readSpecFromFile( SampleUtils.getResourcePath("assets/httpbin_openapi.json")); + // BEGIN: com.azure.ai.agents.define_openapi_with_connection // Create OpenAPI tool with project connection authentication OpenApiTool openApiTool = new OpenApiTool( new OpenApiFunctionDefinition( @@ -65,6 +66,7 @@ public static void main(String[] args) throws Exception { new OpenApiProjectConnectionAuthDetails( new OpenApiProjectConnectionSecurityScheme(connectionId))) .setDescription("Get request metadata from an OpenAPI endpoint.")); + // END: com.azure.ai.agents.define_openapi_with_connection // Create agent with OpenAPI tool PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingSync.java index 570472c2da90..3a072307c865 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/SharePointGroundingSync.java @@ -44,6 +44,7 @@ public static void main(String[] args) { AgentsClient agentsClient = builder.buildAgentsClient(); ResponsesClient responsesClient = builder.buildResponsesClient(); + // BEGIN: com.azure.ai.agents.define_sharepoint // Create SharePoint grounding tool with connection configuration SharepointPreviewTool sharepointTool = new SharepointPreviewTool( new SharepointGroundingToolParameters() @@ -51,6 +52,7 @@ public static void main(String[] args) { new ToolProjectConnection(sharepointConnectionId) )) ); + // END: com.azure.ai.agents.define_sharepoint // Create agent with SharePoint tool PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) diff --git a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchSync.java index c6bb1dc4eaa3..40d588536669 100644 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchSync.java +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/WebSearchSync.java @@ -44,8 +44,10 @@ public static void main(String[] args) { AgentVersionDetails agent = null; try { + // BEGIN: com.azure.ai.agents.define_web_search // Create a WebSearchPreviewTool WebSearchPreviewTool tool = new WebSearchPreviewTool(); + // END: com.azure.ai.agents.define_web_search // Create the agent definition with Web Search tool enabled PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model) From 75e35fd40459357c9d03608527b262d07383ba92 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Mon, 9 Mar 2026 15:15:51 +0100 Subject: [PATCH 21/22] Last fixes --- sdk/ai/azure-ai-agents/README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sdk/ai/azure-ai-agents/README.md b/sdk/ai/azure-ai-agents/README.md index c7b4fd893f81..79421f811241 100644 --- a/sdk/ai/azure-ai-agents/README.md +++ b/sdk/ai/azure-ai-agents/README.md @@ -500,10 +500,13 @@ See the full sample in [SharePointGroundingSync.java](https://github.com/Azure/a Interact with web pages through browser automation: -```java -BrowserAutomationPreviewTool tool = new BrowserAutomationPreviewTool( +```java com.azure.ai.agents.define_browser_automation +// Create browser automation tool with connection configuration +BrowserAutomationPreviewTool browserTool = new BrowserAutomationPreviewTool( new BrowserAutomationToolParameters( - new BrowserAutomationToolConnectionParameters(connectionId))); + new BrowserAutomationToolConnectionParameters(connectionId) + ) +); ``` See the full sample in [BrowserAutomationSync.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BrowserAutomationSync.java). @@ -514,8 +517,9 @@ See the full sample in [BrowserAutomationSync.java](https://github.com/Azure/azu Enable agent-to-agent communication with remote A2A endpoints: -```java -A2APreviewTool tool = new A2APreviewTool() +```java com.azure.ai.agents.define_agent_to_agent +// Create agent-to-agent tool with connection ID +A2APreviewTool a2aTool = new A2APreviewTool() .setProjectConnectionId(a2aConnectionId); ``` From 4982d707d6cfc9210fca6cdaa8dc689cfebd0e51 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Mon, 9 Mar 2026 15:59:21 +0100 Subject: [PATCH 22/22] Async test fixes --- sdk/ai/azure-ai-agents/assets.json | 2 +- .../com/azure/ai/agents/ToolsAsyncTests.java | 238 +++++++++--------- 2 files changed, 113 insertions(+), 127 deletions(-) diff --git a/sdk/ai/azure-ai-agents/assets.json b/sdk/ai/azure-ai-agents/assets.json index 21c3f65f039c..321243e18338 100644 --- a/sdk/ai/azure-ai-agents/assets.json +++ b/sdk/ai/azure-ai-agents/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "java", "TagPrefix": "java/ai/azure-ai-agents", - "Tag": "java/ai/azure-ai-agents_30fb38a114" + "Tag": "java/ai/azure-ai-agents_25e4920008" } diff --git a/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsAsyncTests.java b/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsAsyncTests.java index 95ec3857283c..ef667ef08902 100644 --- a/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsAsyncTests.java +++ b/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsAsyncTests.java @@ -4,7 +4,6 @@ package com.azure.ai.agents; import com.azure.ai.agents.models.AgentReference; -import com.azure.ai.agents.models.AgentVersionDetails; import com.azure.ai.agents.models.CodeInterpreterTool; import com.azure.ai.agents.models.FileSearchTool; import com.azure.ai.agents.models.FunctionTool; @@ -41,7 +40,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; import static com.azure.ai.agents.TestUtils.DISPLAY_NAME_WITH_ARGUMENTS; import static org.junit.jupiter.api.Assertions.*; @@ -70,11 +68,8 @@ public void openApiToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serv = new PromptAgentDefinition("gpt-4o").setInstructions("Use the OpenAPI tool for HTTP request metadata.") .setTools(Arrays.asList(new OpenApiTool(toolDefinition))); - AtomicReference agentRef = new AtomicReference<>(); - StepVerifier.create( agentsClient.createAgentVersion("openapi-tool-test-agent-java-async", agentDefinition).flatMap(agent -> { - agentRef.set(agent); assertNotNull(agent); assertNotNull(agent.getId()); @@ -88,19 +83,19 @@ public void openApiToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serv .input( "Use the OpenAPI tool and summarize the returned URL and origin in one sentence.") .maxOutputTokens(300L)); - }); - }).doFinally(signal -> { - AgentVersionDetails agent = agentRef.get(); - if (agent != null) { - agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()).block(); - } - })).assertNext(response -> { - assertNotNull(response); - assertTrue(response.id().startsWith("resp")); - assertTrue(response.status().isPresent()); - assertEquals(ResponseStatus.COMPLETED, response.status().get()); - assertFalse(response.output().isEmpty()); - assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); + }) + .doOnNext(response -> { + assertNotNull(response); + assertTrue(response.id().startsWith("resp")); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); + }) + .then(agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion())); + })).assertNext(deletedAgent -> { + assertEquals("openapi-tool-test-agent-java-async", deletedAgent.getName()); + assertTrue(deletedAgent.isDeleted()); }).verifyComplete(); } @@ -120,29 +115,27 @@ public void codeInterpreterToolEndToEnd(HttpClient httpClient, AgentsServiceVers .setInstructions("You are a helpful assistant that can execute Python code to solve problems.") .setTools(Collections.singletonList(tool)); - AtomicReference agentRef = new AtomicReference<>(); - StepVerifier.create(agentsClient.createAgentVersion("code-interpreter-test-agent-java-async", agentDefinition) .flatMap(agent -> { - agentRef.set(agent); assertNotNull(agent); AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); - return responsesClient.createWithAgent(agentReference, ResponseCreateParams.builder() - .input("Calculate the first 10 prime numbers and show the Python code.")); - }) - .doFinally(signal -> { - AgentVersionDetails agent = agentRef.get(); - if (agent != null) { - agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()).block(); - } - })).assertNext(response -> { - assertNotNull(response); - assertTrue(response.status().isPresent()); - assertEquals(ResponseStatus.COMPLETED, response.status().get()); - assertFalse(response.output().isEmpty()); - assertTrue(response.output().stream().anyMatch(item -> item.isCodeInterpreterCall())); + return responsesClient + .createWithAgent(agentReference, + ResponseCreateParams.builder() + .input("Calculate the first 10 prime numbers and show the Python code.")) + .doOnNext(response -> { + assertNotNull(response); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + assertTrue(response.output().stream().anyMatch(item -> item.isCodeInterpreterCall())); + }) + .then(agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion())); + })).assertNext(deletedAgent -> { + assertEquals("code-interpreter-test-agent-java-async", deletedAgent.getName()); + assertTrue(deletedAgent.isDeleted()); }).verifyComplete(); } @@ -181,33 +174,31 @@ public void functionCallToolEndToEnd(HttpClient httpClient, AgentsServiceVersion .setInstructions("You are a helpful assistant. When asked about weather, use the get_weather function.") .setTools(Collections.singletonList(tool)); - AtomicReference agentRef = new AtomicReference<>(); - StepVerifier.create( agentsClient.createAgentVersion("function-call-test-agent-java-async", agentDefinition).flatMap(agent -> { - agentRef.set(agent); assertNotNull(agent); AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); - return responsesClient.createWithAgent(agentReference, - ResponseCreateParams.builder().input("What's the weather like in Seattle?")); - }).doFinally(signal -> { - AgentVersionDetails agent = agentRef.get(); - if (agent != null) { - agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()).block(); - } - })).assertNext(response -> { - assertNotNull(response); - assertTrue(response.status().isPresent()); - assertEquals(ResponseStatus.COMPLETED, response.status().get()); - assertFalse(response.output().isEmpty()); - assertTrue(response.output().stream().anyMatch(item -> item.isFunctionCall())); - - ResponseOutputItem functionCallItem - = response.output().stream().filter(item -> item.isFunctionCall()).findFirst().get(); - assertEquals("get_weather", functionCallItem.asFunctionCall().name()); - assertNotNull(functionCallItem.asFunctionCall().arguments()); + return responsesClient + .createWithAgent(agentReference, + ResponseCreateParams.builder().input("What's the weather like in Seattle?")) + .doOnNext(response -> { + assertNotNull(response); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + assertTrue(response.output().stream().anyMatch(item -> item.isFunctionCall())); + + ResponseOutputItem functionCallItem + = response.output().stream().filter(item -> item.isFunctionCall()).findFirst().get(); + assertEquals("get_weather", functionCallItem.asFunctionCall().name()); + assertNotNull(functionCallItem.asFunctionCall().arguments()); + }) + .then(agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion())); + })).assertNext(deletedAgent -> { + assertEquals("function-call-test-agent-java-async", deletedAgent.getName()); + assertTrue(deletedAgent.isDeleted()); }).verifyComplete(); } @@ -227,28 +218,26 @@ public void webSearchToolEndToEnd(HttpClient httpClient, AgentsServiceVersion se .setInstructions("You are a helpful assistant that can search the web.") .setTools(Collections.singletonList(tool)); - AtomicReference agentRef = new AtomicReference<>(); - StepVerifier.create( agentsClient.createAgentVersion("web-search-test-agent-java-async", agentDefinition).flatMap(agent -> { - agentRef.set(agent); assertNotNull(agent); AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); - return responsesClient.createWithAgent(agentReference, - ResponseCreateParams.builder().input("What are the latest trends in renewable energy?")); - }).doFinally(signal -> { - AgentVersionDetails agent = agentRef.get(); - if (agent != null) { - agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()).block(); - } - })).assertNext(response -> { - assertNotNull(response); - assertTrue(response.status().isPresent()); - assertEquals(ResponseStatus.COMPLETED, response.status().get()); - assertFalse(response.output().isEmpty()); - assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); + return responsesClient + .createWithAgent(agentReference, + ResponseCreateParams.builder().input("What are the latest trends in renewable energy?")) + .doOnNext(response -> { + assertNotNull(response); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); + }) + .then(agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion())); + })).assertNext(deletedAgent -> { + assertEquals("web-search-test-agent-java-async", deletedAgent.getName()); + assertTrue(deletedAgent.isDeleted()); }).verifyComplete(); } @@ -269,52 +258,51 @@ public void mcpToolEndToEnd(HttpClient httpClient, AgentsServiceVersion serviceV .setInstructions("You are a helpful agent that can use MCP tools to assist users.") .setTools(Collections.singletonList(tool)); - AtomicReference agentRef = new AtomicReference<>(); - StepVerifier .create(agentsClient.createAgentVersion("mcp-test-agent-java-async", agentDefinition).flatMap(agent -> { - agentRef.set(agent); assertNotNull(agent); AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); - return responsesClient.createWithAgent(agentReference, - ResponseCreateParams.builder().input("Please summarize the Azure REST API specifications Readme")); - }).flatMap(response -> { - assertNotNull(response); - assertTrue(response.status().isPresent()); - assertEquals(ResponseStatus.COMPLETED, response.status().get()); - - AgentVersionDetails agent = agentRef.get(); - AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); - - List approvals = new ArrayList(); - for (ResponseOutputItem item : response.output()) { - if (item.isMcpApprovalRequest()) { - approvals - .add(ResponseInputItem.ofMcpApprovalResponse(ResponseInputItem.McpApprovalResponse.builder() - .approvalRequestId(item.asMcpApprovalRequest().id()) - .approve(true) - .build())); - } - } - - assertFalse(approvals.isEmpty(), "Expected at least one MCP approval request"); - - return responsesClient.createWithAgent(agentReference, - ResponseCreateParams.builder().inputOfResponse(approvals).previousResponseId(response.id())); - }).doFinally(signal -> { - AgentVersionDetails agent = agentRef.get(); - if (agent != null) { - agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()).block(); - } + return responsesClient + .createWithAgent(agentReference, + ResponseCreateParams.builder() + .input("Please summarize the Azure REST API specifications Readme")) + .flatMap(response -> { + assertNotNull(response); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + + List approvals = new ArrayList(); + for (ResponseOutputItem item : response.output()) { + if (item.isMcpApprovalRequest()) { + approvals.add(ResponseInputItem + .ofMcpApprovalResponse(ResponseInputItem.McpApprovalResponse.builder() + .approvalRequestId(item.asMcpApprovalRequest().id()) + .approve(true) + .build())); + } + } + + assertFalse(approvals.isEmpty(), "Expected at least one MCP approval request"); + + return responsesClient.createWithAgent(agentReference, + ResponseCreateParams.builder() + .inputOfResponse(approvals) + .previousResponseId(response.id())); + }) + .doOnNext(response -> { + assertNotNull(response); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); + }) + .then(agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion())); })) - .assertNext(response -> { - assertNotNull(response); - assertTrue(response.status().isPresent()); - assertEquals(ResponseStatus.COMPLETED, response.status().get()); - assertFalse(response.output().isEmpty()); - assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); + .assertNext(deletedAgent -> { + assertEquals("mcp-test-agent-java-async", deletedAgent.getName()); + assertTrue(deletedAgent.isDeleted()); }) .verifyComplete(); } @@ -342,7 +330,6 @@ public void fileSearchToolEndToEnd(HttpClient httpClient, AgentsServiceVersion s FileObject uploadedFile = null; VectorStore vectorStore = null; - AtomicReference agentRef = new AtomicReference<>(); try { uploadedFile = openAIClient.files() @@ -366,7 +353,6 @@ public void fileSearchToolEndToEnd(HttpClient httpClient, AgentsServiceVersion s StepVerifier.create( agentsClient.createAgentVersion("file-search-test-agent-java-async", agentDefinition).flatMap(agent -> { - agentRef.set(agent); assertNotNull(agent); AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion()); @@ -377,19 +363,19 @@ public void fileSearchToolEndToEnd(HttpClient httpClient, AgentsServiceVersion s return responsesClient.createWithAgentConversation(agentReference, conversation.id(), ResponseCreateParams.builder() .input("What is the largest planet in the Solar System?")); - }); - }).doFinally(signal -> { - AgentVersionDetails agent = agentRef.get(); - if (agent != null) { - agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion()).block(); - } - })).assertNext(response -> { - assertNotNull(response); - assertTrue(response.status().isPresent()); - assertEquals(ResponseStatus.COMPLETED, response.status().get()); - assertFalse(response.output().isEmpty()); - assertTrue(response.output().stream().anyMatch(item -> item.isFileSearchCall())); - assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); + }) + .doOnNext(response -> { + assertNotNull(response); + assertTrue(response.status().isPresent()); + assertEquals(ResponseStatus.COMPLETED, response.status().get()); + assertFalse(response.output().isEmpty()); + assertTrue(response.output().stream().anyMatch(item -> item.isFileSearchCall())); + assertTrue(response.output().stream().anyMatch(item -> item.isMessage())); + }) + .then(agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion())); + })).assertNext(deletedAgent -> { + assertEquals("file-search-test-agent-java-async", deletedAgent.getName()); + assertTrue(deletedAgent.isDeleted()); }).verifyComplete(); } finally { Files.deleteIfExists(tempFile);