### Configure AI Provider in tools4ai.properties (Gemini Example) Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/1_introduction.md Example of setting the 'gemini' AI provider in the tools4ai.properties configuration file. ```properties # tools4ai.properties agent.provider=gemini ``` -------------------------------- ### Spring State Machine Integration Example Source: https://github.com/vishalmysore/a2ajava/wiki/Human-In-Loop-Validation-for-Google-A2A-protocol-with-Java-and-Spring-State-Machines Example demonstrating the integration of Spring State Machine with the Human-in-Loop functionality for managing approval workflows. ```APIDOC ## Spring State Machine Integration Example ### Description This example shows how to use Spring State Machine with the HumanInLoop interface to manage approval workflows. It defines states, events, configures the state machine, and integrates it into a service. ### 1. Define States and Events ```java public enum ApprovalStates { PENDING, UNDER_REVIEW, APPROVED, REJECTED } public enum ApprovalEvents { SUBMIT, START_REVIEW, APPROVE, REJECT } ``` ### 2. Configure State Machine ```java @Configuration @EnableStateMachine public class ApprovalStateMachineConfig extends StateMachineConfigurerAdapter { @Override public void configure(StateMachineStateConfigurer states) throws Exception { states .withStates() .initial(ApprovalStates.PENDING) .states(EnumSet.allOf(ApprovalStates.class)); } @Override public void configure(StateMachineTransitionConfigurer transitions) throws Exception { transitions .withExternal() .source(ApprovalStates.PENDING) .target(ApprovalStates.UNDER_REVIEW) .event(ApprovalEvents.START_REVIEW) .and() .withExternal() .source(ApprovalStates.UNDER_REVIEW) .target(ApprovalStates.APPROVED) .event(ApprovalEvents.APPROVE) .and() .withExternal() .source(ApprovalStates.UNDER_REVIEW) .target(ApprovalStates.REJECTED) .event(ApprovalEvents.REJECT); } } ``` ### 3. Integrate with HumanInLoop ```java @Service @WithStateMachine public class ApprovalWorkflowService implements HumanInLoop { @Autowired private StateMachine stateMachine; private ActionCallback callback; @Override public FeedbackLoop allow(String promptText, String methodName, Map params) { // Start the approval process stateMachine.sendEvent(ApprovalEvents.START_REVIEW); // Create feedback loop with state machine integration return new FeedbackLoop() { @Override public void onApprove() { stateMachine.sendEvent(ApprovalEvents.APPROVE); if (callback != null) { callback.onComplete(ActionState.APPROVED); } } @Override public void onReject() { stateMachine.sendEvent(ApprovalEvents.REJECT); if (callback != null) { callback.onComplete(ActionState.REJECTED); } } }; } @Override public void setCallback(ActionCallback callback) { this.callback = callback; } } ``` ``` -------------------------------- ### RestaurantBookingService Example Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/6_SpringAndSelenium.md A service for booking restaurant reservations, annotated with @Log and @Service. It logs the reservation details. ```java @Log @Service public class RestaurantBookingService { public RestaurantBookingService() { log.info("created RestaurantBookingService"); } public String bookReservation(RestaurantPojo restaurantPojo) { log.info(restaurantPojo.toString()); return "This has been booked " + restaurantPojo.toString(); } } ``` -------------------------------- ### Prompt to POJO Conversion Example Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/2_AnnotationsDeepDive.md Demonstrates converting natural language text containing employee information into an Organization POJO using OpenAIPromptTransformer. ```java OpenAIPromptTransformer transformer = new OpenAIPromptTransformer(); // Example prompt with employee information String promptText = "Shahrukh Khan works for MovieHits inc and his salary is $100. " + "He joined Toronto on Labor day, his tasks are acting and dancing. " + "He also works out of Montreal and Bombay. " + "Krithik roshan is another employee based in Chennai, his tasks are jumping and Gym, " + "he joined on Indian Independence Day"; // Convert to Organization object Organization org = (Organization) transformer.transformIntoPojo(promptText, Organization.class); // The system automatically extracts: // - Employee names and their locations // - Salary information // - Join dates // - Tasks/responsibilities // - Multiple office locations ``` -------------------------------- ### CompareCarService Example Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/6_SpringAndSelenium.md A service for comparing two cars, annotated with @Service, @Log, and @Predict. It logs creation and comparison actions. ```java @Service @Log @Predict(actionName ="compareCar", description = "Provide 2 cars and compare them") public class CompareCarService implements JavaMethodAction { public CompareCarService() { log.info("created compare car service"); } public String compareCar(String car1, String car2) { log.info(car2); log.info(car1); // implement the comparison logic here return "this is better - " + car2; } } ``` -------------------------------- ### Example: Low-Risk Car Comparison Action Source: https://github.com/vishalmysore/a2ajava/wiki/Handling-Risks-in-A2A-Java-Agents-for-A2A-and-MCP-servers Demonstrates a Java service class with a method annotated as a LOW-risk action for comparing cars. This is suitable for general AI interactions. ```java @Service @Log @Agent public class CompareCarService { public CompareCarService() { log.info("Created CompareCarService"); } @Action(description = "Compare two cars", riskLevel = ActionRisk.LOW) public String compareCar(String car1, String car2) { log.info(car1); log.info(car2); // Implement the comparison logic here return "This is better - " + car2; } } ``` -------------------------------- ### Prompt Transformer Implementation in Java Source: https://github.com/vishalmysore/a2ajava/wiki/A2AJava:-Bridging-A2A-and-MCP-Protocols-for-Intelligent-Agent-Development Example of implementing a PromptTransformer for AI integration, specifically using GeminiV2PromptTransformer. This is part of the AI integration features. ```java // Example of using PromptTransformer @Override public PromptTransformer getPromptTransformer() { return new GeminiV2PromptTransformer(); } ``` -------------------------------- ### Select and Use AI Processors in Java Source: https://context7.com/vishalmysore/a2ajava/llms.txt Demonstrates how to instantiate and use different AI processors (Gemini, OpenAI, Anthropic, Local) for processing actions and querying information. Includes examples for both direct processors and Spring-integrated ones. ```java import com.t4a.processor.*; public class ProcessorSelectionExample { public static void main(String[] args) throws Exception { // Available processors based on AI provider // Google Gemini AIProcessor geminiProcessor = new GeminiV2ActionProcessor(); // OpenAI AIProcessor openAIProcessor = new OpenAiActionProcessor(); // Anthropic Claude AIProcessor anthropicProcessor = new AnthropicActionProcessor(); // Local AI AIProcessor localProcessor = new LocalAiActionProcessor(); // Spring-integrated processors (auto-configured) // SpringGeminiProcessor, SpringOpenAIProcessor // Use processor for actions Object result = geminiProcessor.processSingleAction( "What is the capital of France?" ); System.out.println("Result: " + result); // Query method for simple responses String answer = geminiProcessor.query("Explain quantum computing in one sentence"); System.out.println("Answer: " + answer); } } ``` -------------------------------- ### Spring Boot Application Setup for A2A/MCP Server Source: https://github.com/vishalmysore/a2ajava/blob/main/README.MD Use this annotation to quickly set up an A2A and MCP server. It exposes services annotated with @Action as A2A tasks and MCP tools. ```java @SpringBootApplication @EnableAgent public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` -------------------------------- ### Define Basic Agent Structure with @Agent and @Action Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/1_introduction.md Create a Java class annotated with @Agent for grouping and @Action for defining agent capabilities. This example shows a basic booking agent. ```java @Agent(groupName = "ticket-booking", groupDescription = "Handles airline ticket booking operations") public class BookingAgent { @Action(description = "Book a flight ticket") public String bookFlight(String from, String to, String date) { // Your implementation here } } ``` -------------------------------- ### SAM Controller Example Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/6_SpringAndSelenium.md Example of a Spring REST controller that uses SpringGeminiProcessor to process natural language prompts and return results. Requires ApplicationContext and RestaurantBookingService. ```java package io.github.vishalmysore; import com.t4a.api.ActionGroup; import com.t4a.api.GroupInfo; import com.t4a.predict.GeminiPromptTransformer; import com.t4a.predict.PredictionLoader; import com.t4a.predict.PromptTransformer; import com.t4a.processor.*; import io.swagger.annotations.ApiResponses; import io.swagger.v3.oas.annotations.Operation; import lombok.extern.java.Log; import io.github.vishalmysore.pojo.Customer; import io.github.vishalmysore.pojo.RestaurantPojo; import io.github.vishalmysore.service.RestaurantBookingService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.web.bind.annotation.*; import java.util.List; @Log @RestController public class SAMController { @Autowired private ApplicationContext applicationContext; @Autowired private RestaurantBookingService restaurantBookingService; @Operation(summary = "Execute any action based on prompt", description = "Try out with any of these prompts:\n" + "1) My Customer name is Vishal, his computer needs repair\n" + "2) Can you compare Honda City to Toyota Corolla\n" + "3) Can i Go out without Jacket in Toronto today\n" + "4) what would vishal want to eat today?") public String actOnPrompt(@RequestParam("prompt") String prompt) { AIProcessor processor = new SpringGeminiProcessor(applicationContext); try { return (String) processor.processSingleAction(prompt); } catch (AIProcessingException e) { throw new RuntimeException(e); } } // ... other controller methods ... } ``` -------------------------------- ### Complex Example: Vehicle Management Service Actions Source: https://github.com/vishalmysore/a2ajava/wiki/Handling-Risks-in-A2A-Java-Agents-for-A2A-and-MCP-servers Shows a Java service with multiple actions of varying risk levels (LOW, MEDIUM, HIGH) for managing vehicles, including checking status, scheduling service, and initiating payments. ```java @Agent public class VehicleManagementService { public VehicleManagementService() { log.info("Created VehicleManagementService"); } @Action(description = "Check vehicle status", riskLevel = ActionRisk.LOW) public String checkVehicleStatus(String vehicleId) { log.info("Checking status for vehicle: " + vehicleId); return "Vehicle " + vehicleId + " is in good condition."; } @Action(description = "Schedule a service appointment", riskLevel = ActionRisk.MEDIUM) public String scheduleService(String vehicleId, String date) { log.info("Scheduling service for vehicle: " + vehicleId + " on " + date); return "Service for vehicle " + vehicleId + " scheduled on " + date; } @Action(description = "Initiate payment for service", riskLevel = ActionRisk.HIGH) public String initiatePayment(String vehicleId, double amount) { log.info("Initiating payment of " + amount + " for vehicle: " + vehicleId); return "Payment of " + amount + " initiated for vehicle " + vehicleId; } } ``` -------------------------------- ### Define a Booking Agent with @Agent and @Action Annotations Source: https://github.com/vishalmysore/a2ajava/wiki/A2AJava:-Bridging-A2A-and-MCP-Protocols-for-Intelligent-Agent-Development Use the @Agent annotation to define an agent and @Action to define its capabilities. This example shows how to create a booking agent with a flight booking action. ```java @Agent(groupName = "ticket booking", groupDescription = "actions related to ticket booking") public class BookingAgent { @Action(description = "Book a flight ticket") public String bookFlight(String from, String to, String date) { // Implementation } } ``` -------------------------------- ### Handle Transaction Processing with Status Updates and Error Handling Source: https://github.com/vishalmysore/a2ajava/wiki/A2AJava:-Bridging-A2A-and-MCP-Protocols-for-Intelligent-Agent-Development This example demonstrates processing a transaction, sending status updates at various stages (validation, payment), and handling potential validation or processing errors. ```java @Action(description = "Process complex transaction") public TransactionResult processTransaction(Transaction tx) { try { actionCallback.sendtStatus("Validating transaction", ActionState.WORKING); validateTransaction(tx); actionCallback.sendtStatus("Processing payment", ActionState.WORKING); processPayment(tx); actionCallback.sendtStatus("Transaction completed", ActionState.COMPLETED); return new TransactionResult(true, "Success"); } catch (ValidationException ve) { actionCallback.sendtStatus("Validation failed: " + ve.getMessage(), ActionState.ERROR); return new TransactionResult(false, ve.getMessage()); } catch (ProcessingException pe) { actionCallback.sendtStatus("Processing failed: " + pe.getMessage(), ActionState.ERROR); return new TransactionResult(false, pe.getMessage()); } } ``` -------------------------------- ### Example: High-Risk Order Placement Action Source: https://github.com/vishalmysore/a2ajava/wiki/Handling-Risks-in-A2A-Java-Agents-for-A2A-and-MCP-servers Illustrates a Java service class including a HIGH-risk action for placing car orders. High-risk actions require careful consideration and potentially human oversight. ```java @Agent public class CompareCarService { public CompareCarService() { log.info("Created CompareCarService"); } @Action(description = "Compare two cars", riskLevel = ActionRisk.LOW) public String compareCar(String car1, String car2) { log.info(car1); log.info(car2); // Implement the comparison logic here return "This is better - " + car2; } @Action(description = "Place an order for the car", riskLevel = ActionRisk.HIGH) public String compareAndPlaceOrder(String car1, String car2) { log.info(car1); log.info(car2); // Implement the order placement logic here return "This is better, so sending a buy order - " + car2; } } ``` -------------------------------- ### Defining a Simple A2A Service with @Agent Source: https://github.com/vishalmysore/a2ajava/blob/main/README.MD Annotate a Spring service with @Agent to create an agent registered with the A2A server. This example defines a service to get a person's favorite food. ```java @Service @Agent(groupName ="whatThisPersonFavFood", groupDescription = "Provide persons name and then find out what does that person like") @Slf4j public class SimpleService { /** * Each action has access to AIProcessor and ActionCallback which are autowired by tools4ai */ private ActionCallback callback; /** * Each action has access to AIProcessor and ActionCallback which are autowired by tools4ai */ private AIProcessor processor; public SimpleService(){ log.info(" Created Simple Service"); } @Action(description = "Get the favourite food of a person") public String whatThisPersonFavFood(String name) { if("vishal".equalsIgnoreCase(name)) return "Paneer Butter Masala"; else if ("vinod".equalsIgnoreCase(name)) { return "aloo kofta"; }else return "something yummy"; } } ``` -------------------------------- ### Maven Dependency Setup for A2A Java Source: https://context7.com/vishalmysore/a2ajava/llms.txt Add the core A2A Java library and annotation tools to your Spring Boot project. Include the security module for optional agent authentication features. ```xml io.github.vishalmysore a2ajava 0.1.8.2 io.github.vishalmysore tools4ai-annotations 0.0.2 io.github.vishalmysore tools4ai-security 0.0.3 ``` -------------------------------- ### Send Status Updates with ActionCallback Source: https://github.com/vishalmysore/a2ajava/wiki/A2AJava:-Bridging-A2A-and-MCP-Protocols-for-Intelligent-Agent-Development Implement status updates for actions using the ActionCallback interface. This example demonstrates sending working, completed, and error statuses during order processing. ```java @Action(description = "Process an order") public void processOrder(String orderId) { actionCallback.sendtStatus("Starting order processing", ActionState.WORKING); try { // Processing logic actionCallback.sendtStatus("Order processed successfully", ActionState.COMPLETED); } catch (Exception e) { actionCallback.sendtStatus("Error processing order: " + e.getMessage(), ActionState.ERROR); } } ``` -------------------------------- ### Java Image Processing with GeminiImageActionProcessor Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/5_UISeleniumI.md This example demonstrates multiple ways to process images using the GeminiImageActionProcessor. It covers single and multiple field extraction into JSON, as well as converting image data directly into POJO objects for specific data structures like AutoRepairScreen and MyGymSchedule. Ensure necessary AIProcessingException is handled. ```java public static void main(String[] args) throws AIProcessingException { GeminiImageActionProcessor processor = new GeminiImageActionProcessor(); // Single field extraction String jsonStr = processor.imageToJson( GeminiImageExample.class.getClassLoader().getResource("images/auto.png"), "Full Inspection" ); log.info(jsonStr); // Multiple field extraction jsonStr = processor.imageToJson( GeminiImageExample.class.getClassLoader().getResource("images/auto.png"), "Full Inspection", "Tire Rotation", "Oil Change" ); log.info(jsonStr); // Full POJO conversion for auto repair screen jsonStr = processor.imageToJson( GeminiImageExample.class.getClassLoader().getResource("images/auto.png"), AutoRepairScreen.class ); log.info(jsonStr); // Full POJO conversion for fitness schedule jsonStr = processor.imageToJson( GeminiImageExample.class.getClassLoader().getResource("images/fitness.png"), MyGymSchedule.class ); log.info(jsonStr); // Direct POJO creation from images Object pojo = processor.imageToPojo( GeminiImageExample.class.getClassLoader().getResource("images/fitness.png"), MyGymSchedule.class ); log.info(pojo.toString()); pojo = processor.imageToPojo( GeminiImageExample.class.getClassLoader().getResource("images/auto.png"), AutoRepairScreen.class ); log.info(pojo.toString()); } ``` -------------------------------- ### Integrate AI for Property Valuation Estimation Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/10_ComplexAgents.md A service class that uses AIProcessor to estimate property values. It constructs a prompt with property details and uses PredictionLoader to get a predicted AI action for Gemini platform. ```java @Service public class PropertyAIService { @Autowired private AIProcessor aiProcessor; public ValuationEstimate getPropertyValuation(PropertyDetails details) { String prompt = String.format( "Analyze the following property details and provide a valuation estimate:\n" + "Location: %s\n" + "Square Footage: %d\n" + "Bedrooms: %d\n" + "Year Built: %d\n" + "Recent Renovations: %s", details.getLocation(), details.getSquareFootage(), details.getBedrooms(), details.getYearBuilt(), details.getRenovations() ); try { AIAction action = PredictionLoader.getInstance() .getPredictedAction(prompt, AIPlatform.GEMINI); return (ValuationEstimate) aiProcessor.processSingleAction( prompt, action, new PropertyValuationHumanVerification(), new ValuationExplanationProvider() ); } catch (AIProcessingException e) { log.severe("AI Valuation failed: " + e.getMessage()); throw new ValuationException("Failed to estimate property value", e); } } } ``` -------------------------------- ### Transform Natural Language to POJO with OpenAIPromptTransformer Source: https://context7.com/vishalmysore/a2ajava/llms.txt Use OpenAIPromptTransformer to convert natural language text into structured Java objects. Ensure necessary annotations are used on your POJO classes for proper mapping. This example demonstrates extracting organization details, schedule information, and performing multi-language translations. ```java import com.t4a.transform.OpenAIPromptTransformer; import com.t4a.annotations.ListType; import com.t4a.annotations.Prompt; import com.t4a.annotations.MapKeyType; import com.t4a.annotations.MapValueType; import lombok.Data; import java.time.DayOfWeek; import java.util.*; @Data public class Organization { String companyName; @ListType(Employee.class) List employees; @ListType(String.class) List officeLocations; } @Data public class Employee { String name; double salary; Date joinDate; @ListType(String.class) List responsibilities; } @Data public class WeeklySchedule { @MapKeyType(DayOfWeek.class) @MapValueType(String.class) Map schedule; } @Data public class TranslationResult { @Prompt(describe = "translate to Hindi") String hindi; @Prompt(describe = "translate to Spanish") String spanish; @Prompt(describe = "translate to French") String french; } public class PromptTransformExample { public static void main(String[] args) throws Exception { OpenAIPromptTransformer transformer = new OpenAIPromptTransformer(); // Extract organization data from natural language String orgText = "TechCorp Inc has offices in Toronto, Montreal, and Vancouver. " + "John Smith works there earning $85000, joined on January 15th 2024, " + "handles development and code reviews. " + "Jane Doe is another employee earning $92000, joined Labor Day, " + "responsible for design and UX research."; Organization org = (Organization) transformer.transformIntoPojo(orgText, Organization.class); System.out.println("Company: " + org.getCompanyName()); System.out.println("Employees: " + org.getEmployees().size()); System.out.println("Locations: " + org.getOfficeLocations()); // Transform schedule text to Map structure String scheduleText = "Monday is for swimming, Wednesday for gym, Friday for yoga"; WeeklySchedule schedule = (WeeklySchedule) transformer.transformIntoPojo( scheduleText, WeeklySchedule.class ); System.out.println("Schedule: " + schedule.getSchedule()); // Multi-language translation TranslationResult translations = (TranslationResult) transformer.transformIntoPojo( "Hello, how are you today?", TranslationResult.class ); System.out.println("Hindi: " + translations.getHindi()); System.out.println("Spanish: " + translations.getSpanish()); } } ``` -------------------------------- ### Integrate REST APIs with OpenAPI using OpenAiActionProcessor Source: https://context7.com/vishalmysore/a2ajava/llms.txt Automatically convert REST APIs defined in OpenAPI specifications into callable AI actions. Configure external API integrations using a JSON file specifying swagger URLs, base URLs, and group information. This example shows how to process natural language commands to interact with a pet store API. ```json { "endpoints": [ { "swaggerurl": "https://petstore3.swagger.io/api/v3/openapi.json", "baseurl": "https://petstore3.swagger.io/", "group": "Petstore API", "description": "Pet store management operations", "id": "petstore" }, { "swaggerurl": "https://api.example.com/v1/swagger.json", "baseurl": "https://api.example.com/", "group": "Enterprise API", "description": "Internal enterprise services", "id": "enterprise" } ] } ``` ```java import com.t4a.processor.OpenAiActionProcessor; public class SwaggerIntegrationExample { public static void main(String[] args) throws Exception { OpenAiActionProcessor processor = new OpenAiActionProcessor(); // Natural language automatically maps to Swagger-defined endpoints String result = (String) processor.processSingleAction( "Add a new pet named Buddy who is a golden retriever, available for sale" ); System.out.println("Pet added: " + result); // Query operations result = (String) processor.processSingleAction( "Find all available pets in the store" ); System.out.println("Available pets: " + result); // Complex operations with automatic parameter extraction result = (String) processor.processSingleAction( "Post a book titled 'AI Agents' with ID 500, published March 2024, " + "description about building intelligent systems, 350 pages" ); System.out.println("Book created: " + result); } } ``` -------------------------------- ### Get Agent Card Source: https://context7.com/vishalmysore/a2ajava/llms.txt Fetch the agent's card information by making a GET request to the well-known agent endpoint. ```shell curl http://localhost:8080/.well-known/agent.json ``` -------------------------------- ### Get task status Source: https://context7.com/vishalmysore/a2ajava/llms.txt Retrieve the status of a task by sending a GET request to the RPC endpoint with the task ID and history length. ```shell curl -X POST http://localhost:8080/rpc \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "method": "tasks/get", "params": { "id": "task-123", "historyLength": 5 }, "id": 4 }' ``` -------------------------------- ### PromptTransformer for Complex Type Conversion Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/0_FAQ.md Implement `PromptTransformer` to handle complex type conversions for prompt processing. The `GeminiV2PromptTransformer` is an example implementation. ```java import com.vishalmysore.a2a.core.PromptTransformer; import com.vishalmysore.a2a.gemini.GeminiV2PromptTransformer; public class MyAgent { // ... other agent methods public PromptTransformer getPromptTransformer() { return new GeminiV2PromptTransformer(); } } ``` -------------------------------- ### Base Task Controller for House Buying Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/10_ComplexAgents.md Extends DyanamicTaskContoller to handle house buying tasks, including asynchronous processing, real-time updates via SSE, and risk-aware task handling. ```java @Service public class HouseBuyingTaskController extends DyanamicTaskContoller { @Autowired private RiskManager riskManager; @Override public SendTaskResponse sendTask(TaskSendParams taskSendParams, ActionCallback callback) { String taskId = taskSendParams.getId(); Task task = new Task(); task.setId(taskId); task.setSessionId(UUID.randomUUID().toString()); // Configure real-time updates task.setPushNotificationConfig(new TaskPushNotificationConfig()); // Process task asynchronously nonBlockingService.execute(() -> { try { TextPart textPart = (TextPart) taskSendParams.getMessage().getParts().get(0); String prompt = textPart.getText(); SSEEmitterCallback sseCallback = new SSEEmitterCallback(taskId, getEmitter(taskId)); sseCallback.setContext(task); // Process with risk awareness if (riskManager.requiresApproval(task, getCurrentAgent())) { processHighRiskTask(task, prompt, sseCallback); } else { getBaseProcessor().processSingleAction(prompt, sseCallback); } } catch (Exception e) { handleTaskError(task, e); } }); return createResponse(task); } } ``` -------------------------------- ### ActionCallback Interface Definition Source: https://github.com/vishalmysore/a2ajava/wiki/A2AJava:-Bridging-A2A-and-MCP-Protocols-for-Intelligent-Agent-Development The ActionCallback interface defines methods for setting and getting context, sending status updates, and managing the type of an action. ```java public interface ActionCallback { void setContext(Object obj); Object getContext(); void sendtStatus(String status, ActionState state); String getType(); String setType(String type); } ``` -------------------------------- ### MCPToolsController: Building MCP Servers Source: https://context7.com/vishalmysore/a2ajava/llms.txt Extend MCPToolsController to create custom MCP server endpoints. This allows exposing your agents as MCP-compatible tools for clients like Claude Desktop. ```java import io.github.vishalmysore.mcp.server.MCPToolsController; import io.github.vishalmysore.mcp.domain.*; import io.github.vishalmysore.common.MCPActionCallback; import org.springframework.web.bind.annotation.*; import org.springframework.http.ResponseEntity; import java.util.*; @RestController @RequestMapping("/mcp") public class CustomMCPController extends MCPToolsController { @GetMapping("/server-config") public ResponseEntity> getConfig() { return super.getServerConfig(); } @GetMapping("/list-tools") public ResponseEntity>> listAllTools() { Map> response = new HashMap<>(); response.put("tools", getToolsResult().getTools()); return ResponseEntity.ok(response); } @PostMapping("/call-tool") public ResponseEntity executeTool(@RequestBody ToolCallRequest request) { CallToolResult result = callToolWithCallback(request, new MCPActionCallback()); JSONRPCResponse response = new JSONRPCResponse(); response.setId(UUID.randomUUID().toString()); response.setResult(result); return ResponseEntity.ok(response); } } // Configure in tools4ai.properties: // mcp.tools.servername=MyCustomMCPServer // mcp.tools.version=1.0.0 // mcp.tools.protocolversion=2024-11-05 ``` -------------------------------- ### Expose Action Method as MCP Tool in Java Source: https://github.com/vishalmysore/a2ajava/wiki/A2AJava:-Bridging-A2A-and-MCP-Protocols-for-Intelligent-Agent-Development An @Action annotated method is automatically exposed as an MCP tool. This example shows a method for booking a flight ticket. ```java @Action(description = "Book a flight ticket") public String bookFlight(String from, String to, String date) { // Implementation } ``` -------------------------------- ### Process Actions with High-Risk Verification in Java Source: https://github.com/vishalmysore/a2ajava/wiki/Handling-Risks-in-A2A-Java-Agents-for-A2A-and-MCP-servers Illustrates a Java method for processing AI actions, including a check for HIGH-risk actions that require explicit human approval before proceeding. This ensures safety for critical operations. ```java public Object processSingleAction(String prompt, AIAction action, HumanInLoop humanVerification, ExplainDecision explain) throws AIProcessingException { if (action == null) { action = PredictionLoader.getInstance().getPredictedAction(prompt, AIPlatform.OPENAI); if (action == null) { return "No action found for the prompt: " + prompt; } if (action.getActionRisk() == ActionRisk.HIGH) { log.warn("This is a high-risk action and requires explicit approval."); return "This is a high-risk action and will not proceed without human intervention: " + action.getActionName(); } } // ... rest of the processing logic } ``` -------------------------------- ### Create an A2A Booking Agent in Java Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/0_FAQ.md Define an agent class with actions using the @Agent and @Action annotations. Use actionCallback to send status updates. ```java @Agent(groupName = "ticket-booking", groupDescription = "Handles airline ticket booking operations") public class BookingAgent { @Action(description = "Book a flight ticket") public String bookFlight(String from, String to, String date) { actionCallback.sendtStatus("Starting booking process", ActionState.WORKING); try { // Booking implementation actionCallback.sendtStatus("Booking completed", ActionState.COMPLETED); return "Booking confirmed"; } catch (Exception e) { actionCallback.sendtStatus("Booking failed: " + e.getMessage(), ActionState.ERROR); throw e; } } } ``` -------------------------------- ### Process Gym Schedule Screenshot to POJO Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/5_UISeleniumI.md This code demonstrates using Tools4AI's imageToPojo method to extract gym schedule data from a screenshot into the MyGymSchedule POJO. The resulting POJO is then logged. ```java GeminiImageActionProcessor processor = new GeminiImageActionProcessor(); Object pojo = processor.imageToPojo( GeminiImageExample.class.getClassLoader().getResource("fitness.png"), MyGymSchedule.class ); log.info(pojo.toString()); ``` -------------------------------- ### Claude Desktop Configuration for MCP Server Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/mcp/11_MCP.md Configure Claude Desktop settings to run the Node.js MCP server script. Specify the command and arguments required to launch the server. ```json { "customerserviceagent": { "command": "node", "args": [ "/work/springactions/src/main/resources/mcpserver.js" ] } } ``` -------------------------------- ### List available MCP tools Source: https://context7.com/vishalmysore/a2ajava/llms.txt Use this curl command to list available MCP tools by sending a POST request to the RPC endpoint. ```shell curl -X POST http://localhost:8080/rpc \ -H "Content-Type: application/json" \ -H "A2A-Version: 1.0" \ -d '{ "jsonrpc": "2.0", "method": "tools/list", "params": {}, "id": 1 }' ``` -------------------------------- ### Capture Screenshot with Selenium Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/5_UISeleniumI.md This snippet demonstrates how to set up a headless Chrome browser using Selenium, navigate to a URL, and capture a screenshot as byte array. Ensure WebDriverManager is configured and necessary ChromeOptions are applied for headless execution. ```java WebDriverManager.chromedriver().setup(); ChromeOptions options = new ChromeOptions(); options.addArguments("--headless"); // Setting headless mode options.addArguments("--disable-gpu"); // GPU hardware acceleration isn't useful in headless mode options.addArguments("--window-size=1920,1080"); // Set the window size WebDriver driver = new ChromeDriver(options); driver.get("https://google.com"); // Take screenshot and save it as file or use as bytes TakesScreenshot ts = (TakesScreenshot) driver; byte[] screenshotBytes = ts.getScreenshotAs(OutputType.BYTES); GeminiImageActionProcessor imageActionProcessor = new GeminiImageActionProcessor(); imageActionProcessor.imageToText(screenshotBytes); // Alternatively, save to file: // File srcFile = ts.getScreenshotAs(OutputType.FILE); // File destFile = new File("screenshot.png"); // FileHandler.copy(srcFile, destFile); driver.quit(); ``` -------------------------------- ### Configure AI Provider in tools4ai.properties Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/1_introduction.md Specify the AI provider (e.g., gemini, openai) in the tools4ai.properties file. ```properties agent.provider=gemini # or openai ``` -------------------------------- ### Message Handling Source: https://github.com/vishalmysore/a2ajava/wiki/A2AJava:-Bridging-A2A-and-MCP-Protocols-for-Intelligent-Agent-Development Demonstrates flexible message handling for different part types. ```APIDOC ## Message Handling ### Description Handles multi-part messages, processing TextPart, FilePart, and DataPart. ### Method N/A (Internal method) ### Endpoint N/A ### Parameters #### Request Body - **Message** (object) - Required - The incoming message object. - **Parts** (array) - Required - An array of message parts. - **TextPart** (object) - Represents plain text content. - **text** (string) - The text content. - **FilePart** (object) - Represents file content. - **fileName** (string) - The name of the file. - **DataPart** (object) - Represents structured data. ### Response #### Success Response (200) - Status updates are sent via ActionCallback. #### Response Example { "example": "Processing text: Hello World" } ``` -------------------------------- ### Call a specific tool/action Source: https://context7.com/vishalmysore/a2ajava/llms.txt Execute a specific tool or action by sending a POST request to the RPC endpoint with the tool's name and arguments. ```shell curl -X POST http://localhost:8080/rpc \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "createTicket", "arguments": { "provideAllValuesInPlainEnglish": "Create urgent ticket for Alice about server downtime" } }, "id": 2 }' ``` -------------------------------- ### Test A2A Agent with Curl: List Tools Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/0_FAQ.md Use this Curl command to verify your agent is running and to retrieve a list of available tools. ```bash curl -H "Content-Type: application/json" -d '{ "jsonrpc": "2.0", "method": "tools/list", "params": {}, "id": 1 }' https://vishalmysore-a2amcpspring.hf.space/ ``` -------------------------------- ### Create a Custom Agent Card in Java Source: https://context7.com/vishalmysore/a2ajava/llms.txt Use this Java code to create and configure an AgentCard object. It demonstrates setting various properties like name, description, version, provider details, capabilities, authentication, input/output modes, skills, A2UI support, and supported interfaces. ```java import io.github.vishalmysore.a2a.domain.*; import java.util.*; public class AgentCardCustomization { public AgentCard createCustomAgentCard() { AgentCard card = new AgentCard(); // Basic information card.setName("Enterprise Support Agent"); card.setDescription("AI-powered customer support and ticket management"); card.setVersion("2.0.0"); card.setProtocolVersion("1.0"); card.setDocumentationUrl("https://docs.example.com/agent"); // Provider information Provider provider = new Provider(); provider.setOrganization("Acme Corp"); provider.setUrl("https://acme.example.com"); card.setProvider(provider); // Capabilities Capabilities capabilities = new Capabilities(); capabilities.setStreaming(true); capabilities.setPushNotifications(true); capabilities.setStateTransitionHistory(true); card.setCapabilities(capabilities); // Authentication Authentication auth = new Authentication(); auth.setSchemes(new String[]{"Bearer", "ApiKey"}); card.setAuthentication(auth); // Input/Output modes card.setDefaultInputModes(new String[]{"text", "file", "data"}); card.setDefaultOutputModes(new String[]{"text", "file"}); // Skills (auto-generated from @Action annotations, but can customize) card.addSkill("createTicket", "Create support tickets", "support", "tickets"); card.addSkill("queryStatus", "Check ticket and order status", "status", "query"); card.addSkill("processRefund", "Handle refund requests", "billing", "refunds"); // Add A2UI extension support card.addA2UISupport( Arrays.asList("dashboard-ui", "ticket-form-ui"), true // accepts inline catalogs ); // Supported interfaces (A2A v1.0) List interfaces = new ArrayList<>(); AgentInterface jsonRpc = new AgentInterface(); jsonRpc.setUrl("https://agent.example.com/rpc"); jsonRpc.setType("jsonrpc"); interfaces.add(jsonRpc); card.setSupportedInterfaces(interfaces); return card; } } ``` -------------------------------- ### Create an MCP Property Valuation Agent in Java Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/0_FAQ.md Define an agent for MCP endpoints using @Agent and @Action annotations. Use @ActionParameter for defining input parameters with descriptions. ```java @Agent(groupName = "property-valuation", groupDescription = "Property valuation services") public class PropertyAgent { @Action(description = "Estimate property value", riskLevel = ActionRisk.MEDIUM) public ValuationResult estimateValue( @ActionParameter(name = "propertyDetails", description = "Property details including location, size") PropertyDetails details) { // Implementation } } ``` -------------------------------- ### Node.js package.json for MCP Server Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/mcp/11_MCP.md Configure the package.json file for Node.js components, specifying dependencies for the Model Context Protocol SDK. ```json { "name": "mcp-sqlagent-server", "version": "0.1.1", "description": "MCP server for interacting with SQL databases.", "license": "MIT", "type": "module", "dependencies": { "@modelcontextprotocol/sdk": "^1.0.3" } } ``` -------------------------------- ### Configure Agent Authentication with Bearer Token Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/1_introduction.md Set up agent authentication by defining the supported authentication schemes, such as Bearer tokens. ```java agentCard.setAuthentication(new Authentication(new String[]{"Bearer"})); ``` -------------------------------- ### Spring State Machine Configuration Source: https://github.com/vishalmysore/a2ajava/wiki/Human-In-Loop-Validation-for-Google-A2A-protocol-with-Java-and-Spring-State-Machines Configures the states and transitions for the approval workflow using Spring State Machine. ```java @Configuration @EnableStateMachine public class ApprovalStateMachineConfig extends StateMachineConfigurerAdapter { @Override public void configure(StateMachineStateConfigurer states) throws Exception { states .withStates() .initial(ApprovalStates.PENDING) .states(EnumSet.allOf(ApprovalStates.class)); } @Override public void configure(StateMachineTransitionConfigurer transitions) throws Exception { transitions .withExternal() .source(ApprovalStates.PENDING) .target(ApprovalStates.UNDER_REVIEW) .event(ApprovalEvents.START_REVIEW) .and() .withExternal() .source(ApprovalStates.UNDER_REVIEW) .target(ApprovalStates.APPROVED) .event(ApprovalEvents.APPROVE) .and() .withExternal() .source(ApprovalStates.UNDER_REVIEW) .target(ApprovalStates.REJECTED) .event(ApprovalEvents.REJECT); } } ``` -------------------------------- ### Configure HTTP Actions with Swagger/OpenAPI Source: https://github.com/vishalmysore/a2ajava/wiki/Enterprise-Integration-with-Google-A2A-Protocol-and-Java Define external REST APIs using Swagger/OpenAPI URLs for automatic action conversion. Ensure the swaggerurl, baseurl, group, description, and id are correctly specified for each endpoint. ```json { "endpoints": [ { "swaggerurl": "https://fakerestapi.azurewebsites.net/swagger/v1/swagger.json", "group": "Books Author Activity", "description": "Actions for managing books, authors, photos and user activities", "baseurl": "https://fakerestapi.azurewebsites.net/", "id": "fakerestapi" }, { "swaggerurl": "https://petstore.swagger.io/v2/swagger.json", "baseurl": "https://petstore.swagger.io/", "group": "Petstore API", "description": "Actions for managing pets and pet-related operations", "id": "petstore" }, { "swaggerurl": "https://vishalmysore-instaservice.hf.space/v3/api-docs", "baseurl": "https://vishalmysore-instaservice.hf.space/", "group": "Enterprise Support and Ticketing System", "description": "Actions for creating and tracking enterprise support tickets", "id": "InstaService" } ] } ``` -------------------------------- ### MCP Tools Controller Implementation Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/10_ComplexAgents.md Extends MCPToolsController to handle tool calls for AI processing, including human verification and explanation. Requires AIProcessor, AIAction, PredictionLoader, etc. ```java import org.springframework.stereotype.Service; import java.util.Map; import java.util.List; import java.util.ArrayList; // Assuming MCPToolsController, CallToolResult, ToolCallRequest, ActionCallback, AIProcessor, AIAction, PredictionLoader, AIProcessingException, Content, TextContent, LoggingHumanDecision, LogginggExplainDecision are defined elsewhere @Service public class HouseBuyingMCPController extends MCPToolsController { @Override public CallToolResult callTool(ToolCallRequest request, ActionCallback callback) { // Configure AI processing based on tools4ai.properties AIProcessor processor = getBaseProcessor(); Map predictions = PredictionLoader.getInstance().getPredictions(); AIAction action = predictions.get(request.getName()); try { // Process with human verification and explanation Object result = processor.processSingleAction( request.toString(), action, new LoggingHumanDecision(), new LogginggExplainDecision(), callback ); return createToolResponse(result, callback); } catch (AIProcessingException e) { return handleAIError(e); } } private CallToolResult createToolResponse(Object result, ActionCallback callback) { CallToolResult callToolResult = new CallToolResult(); List content = new ArrayList<>(); TextContent textContent = new TextContent(); textContent.setText(result.toString()); textContent.setType("text"); content.add(textContent); callToolResult.setContent(content); callback.setContext(callToolResult); return callToolResult; } // Dummy methods for compilation private AIProcessor getBaseProcessor() { return null; } private CallToolResult handleAIError(AIProcessingException e) { return null; } } ``` -------------------------------- ### Configure Shell Actions Source: https://github.com/vishalmysore/a2ajava/wiki/Enterprise-Integration-with-Google-A2A-Protocol-and-Java Define shell scripts as actions in a YAML file, specifying script name, action name, parameters, and a description. This allows triggering shell commands via natural language prompts. ```yaml groups: - name: Employee Actions description: Actions for managing employee operations scripts: - scriptName: "test_script.cmd" actionName: saveEmployeeInformation parameters: employeeName,employeeLocation description: Saves new employee information to the system ``` -------------------------------- ### Automatic Action Selection Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/2_AnnotationsDeepDive.md Illustrates the A2AJava system automatically selecting and processing an appropriate action based on a natural language prompt. ```java // The system automatically chooses the appropriate action String prompt = "Schedule a team meeting for tomorrow at 3 PM"; Object result = processor.processSingleAction(prompt); ``` -------------------------------- ### Selenium Test with Tools4AI Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/6_SpringAndSelenium.md Automate web interactions using plain English commands processed by SeleniumProcessor. Requires WebDriver and SeleniumProcessor initialization. ```java WebDriver driver = new ChromeDriver(options); SeleniumProcessor processor = new SeleniumProcessor(driver); processor.processWebAction("go to website https://the-internet.herokuapp.com"); boolean buttonPresent = processor.trueFalseQuery("do you see Add/Remove Elements?"); if(buttonPresent) { processor.processWebAction("click on Add/Remove Elements"); // perform other function in simple english } //else { // processor.processSingleAction("Create Jira by taking screenshot"); //} processor.processWebAction("go to website https://the-internet.herokuapp.com"); boolean isCheckboxPresent = processor.trueFalseQuery("do you see Checkboxes?"); if(isCheckboxPresent) { processor.processWebAction("click on Checkboxes"); processor.processWebAction("select checkbox 1"); } ``` -------------------------------- ### ExplainDecision Interface Source: https://github.com/vishalmysore/a2ajava/wiki/Human-In-Loop-Validation-for-Google-A2A-protocol-with-Java-and-Spring-State-Machines The ExplainDecision interface enables AI to explain its decision-making process to humans. ```APIDOC ## ExplainDecision Interface ### Description This interface allows AI to explain its decision-making process regarding a particular prompt, method, and reason. ### Method - `explain(String promptText, String methodName, String reason)`: Provides an explanation from the AI for a decision made based on the given prompt, method, and reason. ``` -------------------------------- ### ExplainDecision Interface Source: https://github.com/vishalmysore/a2ajava/blob/main/tutorial/8_HumanInLoop.md The ExplainDecision interface enables AI to explain its decision-making process to a human regarding a specific prompt, method, and reason. ```APIDOC ## ExplainDecision Interface ### Description This interface allows AI to explain its decision-making process. It defines a method to provide an explanation to a human regarding a decision made based on a prompt text, method name, and reason. ### Method - `explain(String promptText, String methodName, String reason)`: Provides an explanation for a decision. ```