Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions sdk/ai/azure-ai-agents/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@

### Features Added

- Added `readSpecFromFile(Path)` static convenience method to `OpenApiFunctionDefinition` for loading OpenAPI specification JSON files as the `Map<String, BinaryData>` 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
Expand Down
352 changes: 352 additions & 0 deletions sdk/ai/azure-ai-agents/README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions sdk/ai/azure-ai-agents/assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "java",
"TagPrefix": "java/ai/azure-ai-agents",
"Tag": "java/ai/azure-ai-agents_69bc682982"
}
"Tag": "java/ai/azure-ai-agents_25e4920008"
}
6 changes: 6 additions & 0 deletions sdk/ai/azure-ai-agents/cspell.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import:
- ../../../.vscode/cspell.json
overrides:
- filename: "**/sdk/ai/azure-ai-agents/*"
words:
- gitmcp
Original file line number Diff line number Diff line change
@@ -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.
*
* <p>Before running the sample, set these environment variables:</p>
* <ul>
* <li>FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.</li>
* <li>FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.</li>
* <li>A2A_PROJECT_CONNECTION_ID - The A2A project connection ID.</li>
* </ul>
*/
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<AgentVersionDetails> 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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* <li>A2A_PROJECT_CONNECTION_ID - The A2A project connection ID.</li>
* </ul>
*/
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");
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
*
* <p>Before running the sample, set these environment variables:</p>
* <ul>
* <li>FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.</li>
* <li>FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.</li>
* <li>AZURE_AI_SEARCH_CONNECTION_ID - The Azure AI Search connection ID.</li>
* <li>AI_SEARCH_INDEX_NAME - The name of the search index.</li>
* </ul>
*/
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<AgentVersionDetails> 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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
* <li>AI_SEARCH_INDEX_NAME - The name of the search index.</li>
* </ul>
*/
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");
Expand All @@ -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(
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
*
* <p>Before running the sample, set these environment variables:</p>
* <ul>
* <li>FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.</li>
* <li>FOUNDRY_MODEL_DEPLOYMENT_NAME - The model deployment name.</li>
* <li>STORAGE_INPUT_QUEUE_NAME - The Azure Storage Queue name for input.</li>
* <li>STORAGE_OUTPUT_QUEUE_NAME - The Azure Storage Queue name for output.</li>
* <li>STORAGE_QUEUE_SERVICE_ENDPOINT - The Azure Storage Queue service endpoint.</li>
* </ul>
*/
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<AgentVersionDetails> agentRef = new AtomicReference<>();

Map<String, Object> locationProp = new LinkedHashMap<String, Object>();
locationProp.put("type", "string");
locationProp.put("description", "location to determine weather for");

Map<String, Object> props = new LinkedHashMap<String, Object>();
props.put("location", locationProp);

Map<String, BinaryData> parameters = new HashMap<String, BinaryData>();
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();
}
}
Loading