@@ -676,3 +676,238 @@ curl --request GET \
676676```
677677
678678::: zone-end
679+
680+ ::: zone pivot="java"
681+
682+ ``` java
683+ package com.example.agents ;
684+
685+ import com.azure.ai.agents.persistent.MessagesClient ;
686+ import com.azure.ai.agents.persistent.PersistentAgentsAdministrationClient ;
687+ import com.azure.ai.agents.persistent.PersistentAgentsClient ;
688+ import com.azure.ai.agents.persistent.PersistentAgentsClientBuilder ;
689+ import com.azure.ai.agents.persistent.RunsClient ;
690+ import com.azure.ai.agents.persistent.ThreadsClient ;
691+ import com.azure.ai.agents.persistent.models.CreateAgentOptions ;
692+ import com.azure.ai.agents.persistent.models.CreateRunOptions ;
693+ import com.azure.ai.agents.persistent.models.FunctionDefinition ;
694+ import com.azure.ai.agents.persistent.models.FunctionToolDefinition ;
695+ import com.azure.ai.agents.persistent.models.MessageImageFileContent ;
696+ import com.azure.ai.agents.persistent.models.MessageRole ;
697+ import com.azure.ai.agents.persistent.models.MessageTextContent ;
698+ import com.azure.ai.agents.persistent.models.PersistentAgent ;
699+ import com.azure.ai.agents.persistent.models.PersistentAgentThread ;
700+ import com.azure.ai.agents.persistent.models.RequiredFunctionToolCall ;
701+ import com.azure.ai.agents.persistent.models.RequiredToolCall ;
702+ import com.azure.ai.agents.persistent.models.RunStatus ;
703+ import com.azure.ai.agents.persistent.models.SubmitToolOutputsAction ;
704+ import com.azure.ai.agents.persistent.models.ThreadMessage ;
705+ import com.azure.ai.agents.persistent.models.ThreadRun ;
706+ import com.azure.ai.agents.persistent.models.ToolOutput ;
707+ import com.azure.ai.agents.persistent.models.MessageContent ;
708+ import com.azure.core.http.rest.PagedIterable ;
709+ import com.azure.core.util.BinaryData ;
710+ import com.azure.identity.DefaultAzureCredentialBuilder ;
711+ import com.fasterxml.jackson.core.JsonProcessingException ;
712+ import com.fasterxml.jackson.databind.JsonNode ;
713+ import com.fasterxml.jackson.databind.json.JsonMapper ;
714+
715+ import java.net.URL ;
716+ import java.io.File ;
717+ import java.io.FileNotFoundException ;
718+ import java.net.URISyntaxException ;
719+ import java.nio.file.Path ;
720+ import java.util.ArrayList ;
721+ import java.util.Arrays ;
722+ import java.util.HashMap ;
723+ import java.util.Map ;
724+ import java.util.function.Function ;
725+
726+ public class AgentExample {
727+
728+ public static void main (String [] args ) throws FileNotFoundException , URISyntaxException {
729+
730+ // variables for authenticating requests to the agent service
731+ String projectEndpoint = " https://aahi-may-resource.services.ai.azure.com/api/projects/aahi-may" ;// System.getenv("PROJECT_ENDPOINT");
732+ String modelName = " gpt-4o" ;// System.getenv("MODEL_DEPLOYMENT_NAME");
733+
734+ PersistentAgentsClientBuilder clientBuilder = new PersistentAgentsClientBuilder (). endpoint(projectEndpoint)
735+ .credential(new DefaultAzureCredentialBuilder (). build());
736+ PersistentAgentsClient agentsClient = clientBuilder. buildClient();
737+ PersistentAgentsAdministrationClient administrationClient = agentsClient. getPersistentAgentsAdministrationClient();
738+ ThreadsClient threadsClient = agentsClient. getThreadsClient();
739+ MessagesClient messagesClient = agentsClient. getMessagesClient();
740+ RunsClient runsClient = agentsClient. getRunsClient();
741+
742+ Supplier<String > getUserFavoriteCity = () - > " Seattle, WA" ;
743+ FunctionToolDefinition getUserFavoriteCityTool = new FunctionToolDefinition (
744+ new FunctionDefinition (
745+ " getUserFavoriteCity" ,
746+ BinaryData . fromObject(
747+ new Object ()
748+ ))
749+ );
750+
751+ Function<String , String > getCityNickname = location - > {
752+ return " The Emerald City" ;
753+ };
754+
755+ FunctionToolDefinition getCityNicknameTool = new FunctionToolDefinition (
756+ new FunctionDefinition (
757+ " getCityNickname" ,
758+ BinaryData . fromObject(
759+ mapOf(
760+ " type" , " object" ,
761+ " properties" , mapOf(
762+ " location" ,
763+ mapOf(
764+ " type" , " string" ,
765+ " description" , " The city and state, e.g. San Francisco, CA" )
766+ ),
767+ " required" , new String []{" location" }))
768+ ). setDescription(" Get the nickname of a city" )
769+ );
770+
771+ Function<RequiredToolCall , ToolOutput > getResolvedToolOutput = toolCall - > {
772+ if (toolCall instanceof RequiredFunctionToolCall ) {
773+ RequiredFunctionToolCall functionToolCall = (RequiredFunctionToolCall ) toolCall;
774+ String functionName = functionToolCall. getFunction(). getName();
775+ if (functionName. equals(" getUserFavoriteCity" )) {
776+ return new ToolOutput (). setToolCallId(functionToolCall. getId())
777+ .setOutput(getUserFavoriteCity. get());
778+ } else if (functionName. equals(" getCityNickname" )) {
779+ String arguments = functionToolCall. getFunction(). getArguments();
780+ try {
781+ JsonNode root = new JsonMapper (). readTree(arguments);
782+ String location = String . valueOf(root. get(" location" ). asText());
783+ return new ToolOutput (). setToolCallId(functionToolCall. getId())
784+ .setOutput(getCityNickname. apply(location));
785+ } catch (JsonProcessingException e) {
786+ throw new RuntimeException (e);
787+ }
788+ }
789+ }
790+ return null ;
791+ };
792+
793+ String agentName = " functions_example" ;
794+ CreateAgentOptions createAgentOptions = new CreateAgentOptions (modelName)
795+ .setName(agentName)
796+ .setInstructions(" You are a weather bot. Use the provided functions to help answer questions. "
797+ + " Customize your responses to the user's preferences as much as possible and use friendly "
798+ + " nicknames for cities whenever possible." )
799+ .setTools(Arrays . asList(getUserFavoriteCityTool, getCityNicknameTool));
800+ PersistentAgent agent = administrationClient. createAgent(createAgentOptions);
801+
802+ PersistentAgentThread thread = threadsClient. createThread();
803+ ThreadMessage createdMessage = messagesClient. createMessage(
804+ thread. getId(),
805+ MessageRole . USER ,
806+ " What's the nickname of my favorite city?" );
807+
808+ try {
809+ // run agent
810+ CreateRunOptions createRunOptions = new CreateRunOptions (thread. getId(), agent. getId())
811+ .setAdditionalInstructions(" " );
812+ ThreadRun threadRun = runsClient. createRun(createRunOptions);
813+
814+ do {
815+ Thread . sleep(500 );
816+ threadRun = runsClient. getRun(thread. getId(), threadRun. getId());
817+ if (threadRun. getStatus() == RunStatus . REQUIRES_ACTION
818+ && threadRun. getRequiredAction() instanceof SubmitToolOutputsAction ) {
819+ SubmitToolOutputsAction submitToolsOutputAction = (SubmitToolOutputsAction ) (threadRun. getRequiredAction());
820+ ArrayList<ToolOutput > toolOutputs = new ArrayList<ToolOutput > ();
821+ for (RequiredToolCall toolCall : submitToolsOutputAction. getSubmitToolOutputs(). getToolCalls()) {
822+ toolOutputs. add(getResolvedToolOutput. apply(toolCall));
823+ }
824+ threadRun = runsClient. submitToolOutputsToRun(thread. getId(), threadRun. getId(), toolOutputs);
825+ }
826+ }
827+ while (
828+ threadRun. getStatus() == RunStatus . QUEUED
829+ || threadRun. getStatus() == RunStatus . IN_PROGRESS
830+ || threadRun. getStatus() == RunStatus . REQUIRES_ACTION );
831+
832+ if (threadRun. getStatus() == RunStatus . FAILED ) {
833+ System . out. println(threadRun. getLastError(). getMessage());
834+ }
835+
836+ printRunMessages(messagesClient, thread. getId());
837+ } catch (InterruptedException e) {
838+ throw new RuntimeException (e);
839+ } finally {
840+ // cleanup
841+ threadsClient. deleteThread(thread. getId());
842+ administrationClient. deleteAgent(agent. getId());
843+ }
844+ }
845+
846+ // Use "Map.of" if available
847+ @SuppressWarnings (" unchecked" )
848+ private static <T > Map<String , T > mapOf (Object ... inputs ) {
849+ Map<String , T > map = new HashMap<> ();
850+ for (int i = 0 ; i < inputs. length; i += 2 ) {
851+ String key = (String ) inputs[i];
852+ T value = (T ) inputs[i + 1 ];
853+ map. put(key, value);
854+ }
855+ return map;
856+ }
857+ // A helper function to print messages from the agent
858+ public static void printRunMessages (MessagesClient messagesClient , String threadId ) {
859+
860+ PagedIterable<ThreadMessage > runMessages = messagesClient. listMessages(threadId);
861+ for (ThreadMessage message : runMessages) {
862+ System . out. print(String . format(" %1$s - %2$s : " , message. getCreatedAt(), message. getRole()));
863+ for (MessageContent contentItem : message. getContent()) {
864+ if (contentItem instanceof MessageTextContent ) {
865+ System . out. print((((MessageTextContent ) contentItem). getText(). getValue()));
866+ } else if (contentItem instanceof MessageImageFileContent ) {
867+ String imageFileId = (((MessageImageFileContent ) contentItem). getImageFile(). getFileId());
868+ System . out. print(" Image from ID: " + imageFileId);
869+ }
870+ System . out. println();
871+ }
872+ }
873+ }
874+
875+ // a helper function to wait until a run has completed running
876+ public static void waitForRunCompletion (String threadId , ThreadRun threadRun , RunsClient runsClient )
877+ throws InterruptedException {
878+
879+ do {
880+ Thread . sleep(500 );
881+ threadRun = runsClient. getRun(threadId, threadRun. getId());
882+ }
883+ while (
884+ threadRun. getStatus() == RunStatus . QUEUED
885+ || threadRun. getStatus() == RunStatus . IN_PROGRESS
886+ || threadRun. getStatus() == RunStatus . REQUIRES_ACTION );
887+
888+ if (threadRun. getStatus() == RunStatus . FAILED ) {
889+ System . out. println(threadRun. getLastError(). getMessage());
890+ }
891+ }
892+ private static Path getFile (String fileName ) throws FileNotFoundException , URISyntaxException {
893+ URL resource = AgentExample . class. getClassLoader(). getResource(fileName);
894+ if (resource == null ) {
895+ throw new FileNotFoundException (" File not found" );
896+ }
897+ File file = new File (resource. toURI());
898+ return file. toPath();
899+ }
900+ @FunctionalInterface
901+ public interface Supplier <T> extends java.util.function.Supplier<T > {
902+ /**
903+ * Retrieves an instance of the appropriate type. The returned object may or may not be a new
904+ * instance, depending on the implementation.
905+ *
906+ * @return an instance of the appropriate type
907+ */
908+ @Override
909+ T get ();
910+ }
911+ }
912+ ```
913+ ::: zone-end
0 commit comments