Skip to content
Closed
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
49 changes: 28 additions & 21 deletions sdk/ai/azure-ai-agents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,11 @@ See the full sample in [ImageGenerationSync.java](https://github.com/Azure/azure
Search the web for current information:

```java com.azure.ai.agents.define_web_search
// Create a WebSearchPreviewTool
WebSearchPreviewTool tool = new WebSearchPreviewTool();
WebSearchPreviewTool tool = new WebSearchPreviewTool()
.setUserLocation(new ApproximateLocation()
.setCountry("GB")
.setRegion("London")
.setCity("London"));
```

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).
Expand Down Expand Up @@ -680,25 +683,14 @@ Toolbox tools are defined in toolbox versions and managed through `ToolboxesClie
Toolbox Search lets an agent search the available toolbox tools at runtime. The GA implementation is `ToolSearchToolboxTool` (`toolbox_search`), and the preview implementation `ToolboxSearchPreviewToolboxTool` (`toolbox_search_preview`) is maintained alongside it for backward compatibility.

```java com.azure.ai.agents.toolboxes.ToolboxSearchToolboxSample.createToolboxSearchToolbox

ToolSearchToolboxTool toolboxSearchTool = new ToolSearchToolboxTool()
.setName("search_tools")
.setDescription("Search over available toolbox tools at runtime.");

ToolboxVersionDetails version = toolboxesClient.createToolboxVersion(
toolboxName,
Collections.singletonList(toolboxSearchTool),
"Toolbox version with a Toolbox Search tool.",
null,
null,
null);

System.out.printf("Created toolbox: %s%n", version.getName());
System.out.printf("Toolbox version: %s%n", version.getVersion());
for (ToolboxTool tool : version.getTools()) {
System.out.printf("Tool type: %s%n", tool.getType());
}

McpToolboxTool innerMcp = new McpToolboxTool("github")
.setServerUrl("https://api.githubcopilot.com/mcp")
.setProjectConnectionId(configuration.get("MCP_PROJECT_CONNECTION_ID"))
.setRequireApproval(BinaryData.fromString("\"never\""))
.setDeferLoading(true);
ToolSearchToolboxTool search = new ToolSearchToolboxTool();
ToolboxVersionDetails version = toolboxesClient.createToolboxVersion(toolboxName,
Arrays.<ToolboxTool>asList(innerMcp, search), "Tool-search toolbox", null, null, null);
```

See the full sample in [ToolboxSearchToolboxSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/toolboxes/ToolboxSearchToolboxSample.java).
Expand Down Expand Up @@ -880,6 +872,21 @@ See the full sample in [CreateResponseWithStructuredInput.java](https://github.c

---

### Additional end-to-end samples

All agent samples use `FOUNDRY_PROJECT_ENDPOINT`. Prompt-agent samples also use `FOUNDRY_MODEL_NAME`, while voice-agent samples use `FOUNDRY_VOICE_MODEL` and optionally `FOUNDRY_VOICE_AGENT_NAME`.

- **Agent lifecycle and structured output:** [AgentBasicAsyncSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/AgentBasicAsyncSample.java), [AgentRetrieveBasicAsyncSample.java](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/AgentRetrieveBasicAsyncSample.java), and the `AgentStructuredOutput*` samples.
- **Workflow agents:** `WorkflowMultiAgentSample`, `WorkflowMultiAgentAsyncSample`, and `WorkflowMultiAgentMcpApprovalSample` demonstrate CSDL workflows and MCP approval handling.
- **Optimization jobs:** the [optimization samples](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/optimization) cover SDK polling, application-managed polling, cancellation, listing, retrieval, and deletion.
- **Telemetry:** the [telemetry samples](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/telemetry) demonstrate console tracing, custom span attributes, and Azure Monitor export.
- **Advanced tools:** additional samples cover structured inputs, generated-file download, File Search streaming, non-preview Web Search, custom search, and end-to-end toolbox search.
- **Voice agents:** the [voice samples](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/ai/azure-ai-agents/src/samples/java/com/azure/ai/agents/voice) cover lifecycle, versions and drafts, guided generation, tool-rich definitions, persisted conversation readback, and audio download.

Live voice text/audio sessions are not included because the current Java client exposes the WebSocket handshake but not the bidirectional realtime event-session abstraction required by those scenarios.

---

### Service API versions

The client library targets the latest service API version by default.
Expand Down
24 changes: 24 additions & 0 deletions sdk/ai/azure-ai-agents/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,30 @@
<version>1.27.0-beta.18</version> <!-- {x-version-update;com.azure:azure-core-test;dependency} -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-core-tracing-opentelemetry</artifactId>
<version>1.0.0-beta.66</version> <!-- {x-version-update;com.azure:azure-core-tracing-opentelemetry;dependency} -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-monitor-opentelemetry-autoconfigure</artifactId>
<version>1.6.0</version> <!-- {x-version-update;com.azure:azure-monitor-opentelemetry-autoconfigure;dependency} -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId>
<version>1.58.0</version> <!-- {x-version-update;io.opentelemetry:opentelemetry-sdk-extension-autoconfigure;external_dependency} -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-logging</artifactId>
<version>1.58.0</version> <!-- {x-version-update;io.opentelemetry:opentelemetry-exporter-logging;external_dependency} -->
<scope>test</scope>
</dependency>

</dependencies>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.ai.agents;

import com.azure.ai.agents.models.AgentDetails;
import com.azure.ai.agents.models.AgentEndpointConfig;
import com.azure.ai.agents.models.AgentVersionDetails;
import com.azure.ai.agents.models.AzureCreateResponseOptions;
import com.azure.ai.agents.models.CreateAgentVersionInput;
import com.azure.ai.agents.models.FixedRatioVersionSelectionRule;
import com.azure.ai.agents.models.PromptAgentDefinition;
import com.azure.ai.agents.models.ProtocolConfiguration;
import com.azure.ai.agents.models.ResponsesProtocolConfiguration;
import com.azure.ai.agents.models.UpdateAgentDetailsOptions;
import com.azure.ai.agents.models.VersionSelector;
import com.azure.core.util.Configuration;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.openai.models.conversations.items.ItemCreateParams;
import com.openai.models.responses.EasyInputMessage;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.services.async.ConversationServiceAsync;
import reactor.core.publisher.Mono;

import java.util.Collections;
import java.util.concurrent.atomic.AtomicReference;

/**
* Demonstrates asynchronous prompt-agent creation, endpoint routing, and a multi-turn conversation.
*
* <p>Before running the sample, set these environment variables:</p>
* <ul>
* <li>{@code FOUNDRY_PROJECT_ENDPOINT} - The Azure AI Project endpoint.</li>
* <li>{@code FOUNDRY_MODEL_NAME} - The model deployment name.</li>
* </ul>
*/
public class AgentBasicAsyncSample {
public static void main(String[] args) {
Configuration configuration = Configuration.getGlobalConfiguration();
String endpoint = configuration.get("FOUNDRY_PROJECT_ENDPOINT");
String model = configuration.get("FOUNDRY_MODEL_NAME");

AgentsClientBuilder builder = new AgentsClientBuilder()
.credential(new DefaultAzureCredentialBuilder().build())
.endpoint(endpoint);
AgentsAsyncClient agentsClient = builder.buildAgentsAsyncClient();
ResponsesAsyncClient responsesClient = builder.buildResponsesAsyncClient();
ConversationServiceAsync conversations = builder.buildOpenAIAsyncClient().conversations();

String agentName = "basic-async-agent";
AtomicReference<AgentVersionDetails> agentRef = new AtomicReference<>();
AtomicReference<AgentEndpointConfig> originalEndpointRef = new AtomicReference<>();
AtomicReference<String> conversationIdRef = new AtomicReference<>();

Mono<Void> sample = agentsClient.createAgentVersion(agentName,
new CreateAgentVersionInput(new PromptAgentDefinition(model)
.setInstructions("You are a helpful assistant that answers general questions.")))
.doOnNext(agent -> {
agentRef.set(agent);
System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion());
})
.flatMap(agent -> agentsClient.getAgent(agentName)
.doOnNext(details -> originalEndpointRef.set(details.getAgentEndpoint()))
.thenReturn(agent))
.flatMap(agent -> {
AgentEndpointConfig endpointConfig = new AgentEndpointConfig()
.setVersionSelector(new VersionSelector().setVersionSelectionRules(Collections.singletonList(
new FixedRatioVersionSelectionRule(100).setAgentVersion(agent.getVersion()))))
.setProtocolConfiguration(new ProtocolConfiguration()
.setResponses(new ResponsesProtocolConfiguration()));
return agentsClient.updateAgentDetails(agentName,
new UpdateAgentDetailsOptions().setAgentEndpoint(endpointConfig));
})
.then(Mono.defer(() -> Mono.fromFuture(conversations.create())))
.doOnNext(conversation -> {
conversationIdRef.set(conversation.id());
System.out.println("Conversation created: " + conversation.id());
})
.flatMap(conversation -> responsesClient.createAzureResponse(
new AzureCreateResponseOptions().setAgentReference(
SampleUtils.toAgentReference(agentRef.get())),
ResponseCreateParams.builder()
.conversation(conversation.id())
.input("What is the size of France in square miles?")))
.doOnNext(SampleUtils::printResponseText)
.flatMap(response -> Mono.fromFuture(conversations.items().create(ItemCreateParams.builder()
.conversationId(conversationIdRef.get())
.addItem(EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content("What is its capital city?")
.build())
.build())))
.then(Mono.defer(() -> responsesClient.createAzureResponse(
new AzureCreateResponseOptions().setAgentReference(
SampleUtils.toAgentReference(agentRef.get())),
ResponseCreateParams.builder().conversation(conversationIdRef.get()))))
.doOnNext(SampleUtils::printResponseText)
.then();

sample.then(Mono.defer(() -> cleanup(agentsClient, conversations, agentName, agentRef, originalEndpointRef,
conversationIdRef)))
.onErrorResume(error -> cleanup(agentsClient, conversations, agentName, agentRef,
originalEndpointRef, conversationIdRef)
.then(Mono.error(error)))
.block();
}

private static Mono<Void> cleanup(AgentsAsyncClient agentsClient, ConversationServiceAsync conversations,
String agentName, AtomicReference<AgentVersionDetails> agentRef,
AtomicReference<AgentEndpointConfig> originalEndpointRef, AtomicReference<String> conversationIdRef) {
Mono<Void> deleteConversation = conversationIdRef.get() == null
? Mono.empty()
: Mono.fromFuture(conversations.delete(conversationIdRef.get())).then();
Mono<AgentDetails> restoreEndpoint = agentRef.get() == null
? Mono.empty()
: agentsClient.updateAgentDetails(agentName,
new UpdateAgentDetailsOptions().setAgentEndpoint(originalEndpointRef.get()));
Mono<Void> deleteVersion = agentRef.get() == null
? Mono.empty()
: agentsClient.deleteAgentVersion(agentName, agentRef.get().getVersion());
return deleteConversation.then(restoreEndpoint).then(deleteVersion);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.ai.agents;

import com.azure.ai.agents.models.AgentDetails;
import com.azure.ai.agents.models.AgentEndpointConfig;
import com.azure.ai.agents.models.AgentVersionDetails;
import com.azure.ai.agents.models.AzureCreateResponseOptions;
import com.azure.ai.agents.models.CreateAgentVersionInput;
import com.azure.ai.agents.models.FixedRatioVersionSelectionRule;
import com.azure.ai.agents.models.PromptAgentDefinition;
import com.azure.ai.agents.models.ProtocolConfiguration;
import com.azure.ai.agents.models.ResponsesProtocolConfiguration;
import com.azure.ai.agents.models.UpdateAgentDetailsOptions;
import com.azure.ai.agents.models.VersionSelector;
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 com.openai.services.blocking.ConversationService;

import java.util.Collections;

/**
* Demonstrates synchronous prompt-agent creation, endpoint routing, and a multi-turn conversation.
*
* <p>Before running the sample, set these environment variables:</p>
* <ul>
* <li>{@code FOUNDRY_PROJECT_ENDPOINT} - The Azure AI Project endpoint.</li>
* <li>{@code FOUNDRY_MODEL_NAME} - The model deployment name.</li>
* </ul>
*/
public class AgentBasicSample {
public static void main(String[] args) {
Configuration configuration = Configuration.getGlobalConfiguration();
String endpoint = configuration.get("FOUNDRY_PROJECT_ENDPOINT");
String model = configuration.get("FOUNDRY_MODEL_NAME");

AgentsClientBuilder builder = new AgentsClientBuilder()
.credential(new DefaultAzureCredentialBuilder().build())
.endpoint(endpoint);
AgentsClient agentsClient = builder.buildAgentsClient();
ResponsesClient responsesClient = builder.buildResponsesClient();
ConversationService conversations = builder.buildOpenAIClient().conversations();

String agentName = "basic-agent";
AgentVersionDetails agent = null;
AgentEndpointConfig originalEndpoint = null;
String conversationId = null;

try {
agent = agentsClient.createAgentVersion(agentName,
new CreateAgentVersionInput(new PromptAgentDefinition(model)
.setInstructions("You are a helpful assistant that answers general questions.")));
System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion());

AgentDetails details = agentsClient.getAgent(agentName);
originalEndpoint = details.getAgentEndpoint();
AgentEndpointConfig endpointConfig = new AgentEndpointConfig()
.setVersionSelector(new VersionSelector().setVersionSelectionRules(Collections.singletonList(
new FixedRatioVersionSelectionRule(100).setAgentVersion(agent.getVersion()))))
.setProtocolConfiguration(new ProtocolConfiguration()
.setResponses(new ResponsesProtocolConfiguration()));
agentsClient.updateAgentDetails(agentName,
new UpdateAgentDetailsOptions().setAgentEndpoint(endpointConfig));
System.out.printf("Agent endpoint configured for version %s%n", agent.getVersion());

Conversation conversation = conversations.create();
conversationId = conversation.id();
System.out.println("Conversation created: " + conversationId);

AzureCreateResponseOptions options = new AzureCreateResponseOptions()
.setAgentReference(SampleUtils.toAgentReference(agent));
Response first = responsesClient.createAzureResponse(options,
ResponseCreateParams.builder()
.conversation(conversationId)
.input("What is the size of France in square miles?"));
SampleUtils.printResponseText(first);

conversations.items().create(ItemCreateParams.builder()
.conversationId(conversationId)
.addItem(EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content("What is its capital city?")
.build())
.build());
Response second = responsesClient.createAzureResponse(options,
ResponseCreateParams.builder().conversation(conversationId));
SampleUtils.printResponseText(second);
} finally {
if (conversationId != null) {
conversations.delete(conversationId);
}
if (agent != null) {
agentsClient.updateAgentDetails(agentName,
new UpdateAgentDetailsOptions().setAgentEndpoint(originalEndpoint));
agentsClient.deleteAgentVersion(agentName, agent.getVersion());
}
}
}
}
Loading
Loading