diff --git a/sdk/ai/azure-ai-agents/CHANGELOG.md b/sdk/ai/azure-ai-agents/CHANGELOG.md index 2232d8e3cd02..d2cadc69781b 100644 --- a/sdk/ai/azure-ai-agents/CHANGELOG.md +++ b/sdk/ai/azure-ai-agents/CHANGELOG.md @@ -4,12 +4,18 @@ ### 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 `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 ### Bugs Fixed ### Other Changes +- 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) ### Features Added diff --git a/sdk/ai/azure-ai-agents/README.md b/sdk/ai/azure-ai-agents/README.md index 8bdaa4b533d7..79421f811241 100644 --- a/sdk/ai/azure-ai-agents/README.md +++ b/sdk/ai/azure-ai-agents/README.md @@ -210,6 +210,358 @@ 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 com.azure.ai.agents.define_code_interpreter +// Create a CodeInterpreterTool with default auto container configuration +CodeInterpreterTool tool = new CodeInterpreterTool(); +``` + +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). + +--- + +##### **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 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). + +--- + +##### **Image Generation** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/image-generation?pivots=java)) + +Generate images from text descriptions: + +```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")); +``` + +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). + +--- + +##### **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 com.azure.ai.agents.define_web_search +// Create a WebSearchPreviewTool +WebSearchPreviewTool tool = new WebSearchPreviewTool(); +``` + +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). + +--- + +##### **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 com.azure.ai.agents.define_computer_use +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 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")); +``` + +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). + +--- + +##### **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 com.azure.ai.agents.define_openapi +// Load the OpenAPI spec from a JSON file +Map spec = OpenApiFunctionDefinition.readSpecFromFile( + SampleUtils.getResourcePath("assets/httpbin_openapi.json")); + +OpenApiTool tool = new OpenApiTool( + 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). + +--- + +##### **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 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"); + +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 [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). + +--- + +##### **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`. + +--- + +##### **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 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) + )) +); +``` + +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). + +--- + +##### **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 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) + )) +); +``` + +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 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) + )) +); +``` + +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). + +--- + +##### **Microsoft SharePoint (Preview)** ([documentation](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/sharepoint?pivots=java)) + +Search through SharePoint documents for grounding: + +```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) + )) +); +``` + +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). + +--- + +##### **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 com.azure.ai.agents.define_browser_automation +// Create browser automation tool with connection configuration +BrowserAutomationPreviewTool browserTool = new BrowserAutomationPreviewTool( + new BrowserAutomationToolParameters( + 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). + +--- + +##### **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 com.azure.ai.agents.define_agent_to_agent +// Create agent-to-agent tool with connection ID +A2APreviewTool a2aTool = new A2APreviewTool() + .setProjectConnectionId(a2aConnectionId); +``` + +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). + +--- + +##### **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/assets.json b/sdk/ai/azure-ai-agents/assets.json index 42ea9478529a..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_69bc682982" -} \ No newline at end of file + "Tag": "java/ai/azure-ai-agents_25e4920008" +} diff --git a/sdk/ai/azure-ai-agents/cspell.yaml b/sdk/ai/azure-ai-agents/cspell.yaml new file mode 100644 index 000000000000..d8163c7781be --- /dev/null +++ b/sdk/ai/azure-ai-agents/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 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 95% 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..8ac3c6ed9e1c 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"); @@ -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/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 96% 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..6fac9eb704e4 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"); @@ -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/AzureFunctionAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionAsync.java new file mode 100644 index 000000000000..05d4f830cbc1 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionAsync.java @@ -0,0 +1,115 @@ +// 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.LinkedHashMap; +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 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( + 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/AzureFunctionSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSync.java new file mode 100644 index 000000000000..b8025b3de805 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/AzureFunctionSync.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.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.LinkedHashMap; +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 AzureFunctionSync { + 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 + // 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)); + + // BEGIN: 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)) + ) + ); + // END: com.azure.ai.agents.define_azure_function + + // 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/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/BingCustomSearchSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSync.java new file mode 100644 index 000000000000..994b271bf04f --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/BingCustomSearchSync.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.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 BingCustomSearchSync { + 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(); + + // 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) + .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/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 95% 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..fedf8f04a490 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"); @@ -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/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 95% 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..1199545f954c 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"); @@ -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/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/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..c5934156a4a4 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()) @@ -39,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) @@ -48,18 +56,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 +77,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 +87,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/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/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 96% 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..63e3b9c990a5 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"); @@ -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/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..814d5cd1ad2d 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,34 @@ 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); + // 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 - // 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 +126,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 +142,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 64% 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..59d8eef799bb 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; @@ -21,62 +20,80 @@ 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; /** - * 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 + // 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"); + + 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. San Francisco, CA\"}, \"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"); - - // Create the agent definition with Function tool enabled + // 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)); - 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 +103,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 +112,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 66% 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..362d0da51fe9 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; @@ -20,22 +19,29 @@ 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; /** - * 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(); @@ -45,11 +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. San Francisco, CA\"}, \"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"); @@ -60,18 +79,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 +100,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 +109,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 96% 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..96dccd43388d 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"); @@ -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/McpAgent.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAgent.java deleted file mode 100644 index 00da3cbca9bc..000000000000 --- a/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpAgent.java +++ /dev/null @@ -1,102 +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.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.McpTool; -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 com.openai.models.responses.ResponseOutputItem; -import com.openai.models.responses.ResponseOutputMessage; - -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. - */ -public class McpAgent { - public static void main(String[] args) { - String endpoint = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_ENDPOINT"); - String model = Configuration.getGlobalConfiguration().get("AZURE_AGENTS_MODEL"); - - AgentsClientBuilder builder = new AgentsClientBuilder() - .credential(new DefaultAzureCredentialBuilder().build()) - .serviceVersion(AgentsServiceVersion.getLatest()) - .endpoint(endpoint); - - AgentsClient agentsClient = builder.buildAgentsClient(); - ResponsesClient responsesClient = builder.buildResponsesClient(); - - AgentVersionDetails agent = null; - - try { - // Create an MCPTool 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 - .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)); - - agent = agentsClient.createAgentVersion("MyAgent", agentDefinition); - System.out.printf("Agent created (id: %s, version: %s)\n", agent.getId(), 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?")); - - // 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 -> { - content.outputText().ifPresent(text -> { - System.out.println("Assistant: " + text.text()); - }); - }); - } - - // Handle MCP tool call output - if (outputItem.mcpCall().isPresent()) { - ResponseOutputItem.McpCall mcpCall = outputItem.mcpCall().get(); - System.out.println("\n--- MCP Tool Call ---"); - System.out.println("Call ID: " + mcpCall.id()); - System.out.println("Server Label: " + mcpCall.serverLabel()); - System.out.println("Tool Name: " + mcpCall.name()); - System.out.println("Arguments: " + mcpCall.arguments()); - mcpCall.status().ifPresent(status -> System.out.println("Status: " + status)); - mcpCall.output().ifPresent(output -> System.out.println("Output: " + output)); - 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."); - } - } - } -} 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 51% 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..26ba9880d50c 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,70 +5,109 @@ 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.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 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 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 (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:

    + *
      + *
    • 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 - McpTool tool = new McpTool("my-mcp-server") - .setServerUrl("https://example.mcp.server/mcp") // Add your MCP server URL here - .setServerDescription("An MCP server that provides additional tools"); + // Create an MCP tool that connects to a remote MCP server + // 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)); - 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("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() - .input("What tools are available from the MCP server?")); + .inputOfResponse(approvals) + .previousResponseId(response.id())); + } + + return Mono.just(response); }) .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 +117,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 +129,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/McpSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpSync.java new file mode 100644 index 000000000000..75cf8157bf22 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpSync.java @@ -0,0 +1,133 @@ +// 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 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 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:

    + *
      + *
    • FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.
    • + *
    • FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.
    • + *
    + */ +public class McpSync { + 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(); + + AgentVersionDetails agent = null; + + 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) + .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); + System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion()); + + 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")); + + // 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 final 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.mcpCall().isPresent()) { + ResponseOutputItem.McpCall mcpCall = outputItem.mcpCall().get(); + System.out.println("\n--- MCP Tool Call ---"); + System.out.println("Call ID: " + mcpCall.id()); + System.out.println("Server Label: " + mcpCall.serverLabel()); + System.out.println("Tool Name: " + mcpCall.name()); + System.out.println("Arguments: " + mcpCall.arguments()); + mcpCall.status().ifPresent(status -> System.out.println("Status: " + status)); + mcpCall.output().ifPresent(output -> System.out.println("Output: " + output)); + mcpCall.error().ifPresent(error -> System.out.println("Error: " + error)); + } + } + } finally { + if (agent != null) { + 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/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..04fd7d2bf5d0 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionAsync.java @@ -0,0 +1,120 @@ +// 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 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/McpWithConnectionSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSync.java new file mode 100644 index 000000000000..c28d421a8a14 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/McpWithConnectionSync.java @@ -0,0 +1,120 @@ +// 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 McpWithConnectionSync { + 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(); + + // 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) + .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/MemorySearchAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchAsync.java new file mode 100644 index 000000000000..d9546dd7f20c --- /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 — await conversation deletes before proceeding + try { + String c1 = firstConvRef.get(); + if (c1 != null) { + conversationsAsyncClient.getConversationServiceAsync().delete(c1).join(); + } + String c2 = secondConvRef.get(); + if (c2 != null) { + conversationsAsyncClient.getConversationServiceAsync().delete(c2).join(); + } + } 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/MemorySearchSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSync.java new file mode 100644 index 000000000000..7e86048091ed --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/MemorySearchSync.java @@ -0,0 +1,160 @@ +// 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 MemorySearchSync { + 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()); + + // 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) + .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/OpenApiAsync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiAsync.java new file mode 100644 index 000000000000..0348a287c1ad --- /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("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.") + .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/OpenApiSync.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSync.java new file mode 100644 index 000000000000..4910852e68cc --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiSync.java @@ -0,0 +1,112 @@ +// 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.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.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.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 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"); + + AgentsClientBuilder builder = new AgentsClientBuilder() + .credential(new DefaultAzureCredentialBuilder().build()) + .endpoint(endpoint); + + AgentsClient agentsClient = builder.buildAgentsClient(); + ResponsesClient responsesClient = builder.buildResponsesClient(); + 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")); + + 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(tool)); + + 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/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/CodeInterpreterSample.java b/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSync.java similarity index 50% rename from sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/CodeInterpreterSample.java rename to sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/tools/OpenApiWithConnectionSync.java index 4a8a934c18d6..46cfb576cc3d 100644 --- 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/OpenApiWithConnectionSync.java @@ -6,31 +6,45 @@ 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.CodeInterpreterTool; +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 the Code Interpreter tool - * for data visualization and code execution. + * 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 CodeInterpreterSample { - public static void main(String[] args) { +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"); + String connectionId = Configuration.getGlobalConfiguration().get("OPENAPI_PROJECT_CONNECTION_ID"); AgentsClientBuilder builder = new AgentsClientBuilder() .credential(new DefaultAzureCredentialBuilder().build()) @@ -39,35 +53,40 @@ public static void main(String[] args) { AgentsClient agentsClient = builder.buildAgentsClient(); ResponsesClient responsesClient = builder.buildResponsesClient(); - // Create code interpreter tool - CodeInterpreterTool codeInterpreter = new CodeInterpreterTool(); + // Load the OpenAPI spec from a JSON file + 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( + "httpbin_get", + spec, + 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 code interpreter for data visualization + // Create agent with OpenAPI tool 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)); + .setInstructions("You are a helpful assistant.") + .setTools(Collections.singletonList(openApiTool)); - AgentVersionDetails agent = agentsClient.createAgentVersion("chart-agent", agentDefinition); + AgentVersionDetails agent = agentsClient.createAgentVersion("openapi-connection-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.")); + .input("Call the API and summarize the returned URL and origin.")); 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/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 95% 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..3a072307c865 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"); @@ -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/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..40d588536669 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,10 @@ public static void main(String[] args) { AgentVersionDetails agent = null; try { - // Create a WebSearchTool - WebSearchTool tool = new WebSearchTool(); + // 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) @@ -49,18 +55,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 +76,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"); } } } 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..ef667ef08902 --- /dev/null +++ b/sdk/ai/azure-ai-agents/src/test/java/com/azure/ai/agents/ToolsAsyncTests.java @@ -0,0 +1,390 @@ +// 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.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.files.FileCreateParams; +import com.openai.models.files.FileObject; +import com.openai.models.files.FilePurpose; +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.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 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))); + + StepVerifier.create( + agentsClient.createAgentVersion("openapi-tool-test-agent-java-async", agentDefinition).flatMap(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)); + }) + .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(); + } + + // ----------------------------------------------------------------------- + // 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)); + + StepVerifier.create(agentsClient.createAgentVersion("code-interpreter-test-agent-java-async", agentDefinition) + .flatMap(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.")) + .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(); + } + + // ----------------------------------------------------------------------- + // 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)); + + StepVerifier.create( + agentsClient.createAgentVersion("function-call-test-agent-java-async", agentDefinition).flatMap(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?")) + .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(); + } + + // ----------------------------------------------------------------------- + // 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)); + + StepVerifier.create( + agentsClient.createAgentVersion("web-search-test-agent-java-async", agentDefinition).flatMap(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?")) + .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(); + } + + // ----------------------------------------------------------------------- + // 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)); + + StepVerifier + .create(agentsClient.createAgentVersion("mcp-test-agent-java-async", agentDefinition).flatMap(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()); + + 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(deletedAgent -> { + assertEquals("mcp-test-agent-java-async", deletedAgent.getName()); + assertTrue(deletedAgent.isDeleted()); + }) + .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; + + 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)); + + StepVerifier.create( + agentsClient.createAgentVersion("file-search-test-agent-java-async", agentDefinition).flatMap(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?")); + }) + .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); + 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()); + } + } + } +} 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;