Spring AI Tutorials
    Tutorial 09

    Building Effective Agents with Spring AI

    Create intelligent AI agents that can reason, plan, use tools, and execute complex multi-step tasks autonomously

    1
    What are AI Agents?

    An AI Agent is an autonomous system that uses a Large Language Model (LLM) as its "brain" to reason about problems, make decisions, and take actions. Unlike simple chatbots that just respond to queries, agents can:

    Reason & Plan

    Break down complex tasks into smaller steps and determine the best approach

    Use Tools

    Call external APIs, databases, and services to gather information or perform actions

    Execute Autonomously

    Carry out multi-step workflows without constant human intervention

    Achieve Goals

    Work towards specific objectives, adapting their approach as needed

    Agent vs Chatbot

    A chatbot responds to individual messages. An agent takes a goal like "Book me a flight to Paris next week" and autonomously searches flights, compares prices, selects options, and completes the booking.

    2
    Agent Architecture in Spring AI

    Agent Loop Architecture

    User Goal

    "Analyze sales data"

    LLM Reasoning

    Plan & decide action

    Tool Execution

    Call APIs/functions

    Result/Loop

    Complete or continue

    Core Components

    1. ChatClient

    The main interface to interact with the LLM. Handles prompts, responses, and tool calling.

    2. Tools (Functions)

    Java methods annotated with @Tool that the agent can invoke. These extend the agent's capabilities.

    3. Memory/Chat History

    Maintains conversation context so the agent remembers previous interactions and tool results.

    4. System Prompt

    Defines the agent's persona, capabilities, and behavioral guidelines.

    3
    Building Your First Agent

    Step 1: Define Tools

    Create tools that your agent can use. Each tool is a method annotated with @Tool.

    Java Example
    importorg.springframework.ai.tool.annotation.Tool;importorg.springframework.ai.tool.annotation.ToolParam;importorg.springframework.stereotype.Component;@ComponentpublicclassWeatherTools{@Tool(description ="Get the current weather for a specific city")publicStringgetCurrentWeather(@ToolParam(description ="The city name, e.g., 'London'")String city){// In production, call a real weather APIreturn"The weather in "+ city +" is 22°C and sunny.";}@Tool(description ="Get the weather forecast for the next N days")publicStringgetWeatherForecast(@ToolParam(description ="The city name")String city,@ToolParam(description ="Number of days (1-7)")int days){return"Weather forecast for "+ city +" for the next "+ days +" days: Mostly sunny with temperatures between 18-25°C.";}}

    Step 2: Create the Agent Service

    Java Example
    importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;importorg.springframework.ai.chat.memory.InMemoryChatMemory;importorg.springframework.stereotype.Service;@ServicepublicclassWeatherAgentService{privatefinalChatClient chatClient;publicWeatherAgentService(ChatClient.Builder chatClientBuilder,WeatherTools weatherTools){this.chatClient = chatClientBuilder
    .defaultSystem("""
    You are a helpful weather assistant agent. 
    You can check current weather and forecasts for any city.
    Always be friendly and provide helpful weather advice.
    If asked about activities, suggest based on the weather.
    """).defaultTools(weatherTools)// Register tools.defaultAdvisors(newMessageChatMemoryAdvisor(newInMemoryChatMemory())).build();}publicStringchat(String userMessage){return chatClient.prompt().user(userMessage).call().content();}}

    Step 3: Agent Controller

    Java Example
    @RestController@RequestMapping("/api/agent")@RequiredArgsConstructorpublicclassWeatherAgentController{privatefinalWeatherAgentService agentService;@PostMapping("/chat")publicResponseEntity<AgentResponse>chat(@RequestBodyChatRequest request){String response = agentService.chat(request.message());returnResponseEntity.ok(newAgentResponse(response));}}recordChatRequest(String message){}recordAgentResponse(String response){}

    How It Works

    When you ask "What's the weather in Paris?", the LLM recognizes it needs weather data, calls the getCurrentWeather tool, receives the result, and formulates a natural response.

    4
    Advanced Agent Patterns

    Multi-Tool Agent Example

    Build agents with multiple specialized tools for complex tasks:

    Java Example
    @ComponentpublicclassTravelAgentTools{@Tool(description ="Search for available flights between two cities")publicStringsearchFlights(@ToolParam(description ="Departure city")String from,@ToolParam(description ="Destination city")Stringto,@ToolParam(description ="Date in YYYY-MM-DD format")String date){return"Found 5 flights from "+ from +" to "+to+" on "+ date +". Prices range from $250 to $450.";}@Tool(description ="Search for hotels in a city")publicStringsearchHotels(@ToolParam(description ="City name")String city,@ToolParam(description ="Check-in date")String checkIn,@ToolParam(description ="Check-out date")String checkOut){return"Found 10 hotels in "+ city +" from "+ checkIn +" to "+ checkOut +". Prices from $80/night to $300/night.";}@Tool(description ="Book a flight with the given details")publicStringbookFlight(@ToolParam(description ="Flight ID")String flightId,@ToolParam(description ="Passenger name")String passengerName){return"Flight "+ flightId +" booked for "+ passengerName +". Confirmation: TRV-"+System.currentTimeMillis();}@Tool(description ="Get current exchange rate between currencies")publicStringgetExchangeRate(@ToolParam(description ="Source currency code")String from,@ToolParam(description ="Target currency code")Stringto){return"1 "+ from +" = 0.85 "+to;}}

    ReAct Pattern (Reasoning + Acting)

    Implement the ReAct pattern where the agent explicitly reasons before taking actions:

    Java Example
    @ServicepublicclassReActAgentService{privatefinalChatClient chatClient;publicReActAgentService(ChatClient.Builder builder,TravelAgentTools tools){this.chatClient = builder
    .defaultSystem("""
    You are an intelligent travel planning agent using the ReAct pattern.
    For each user request, follow this process:
    1. THOUGHT: Analyze what the user needs and plan your approach
    2. ACTION: Use the appropriate tool to gather information
    3. OBSERVATION: Review the tool result
    4. Repeat steps 1-3 until you have enough information
    5. ANSWER: Provide a comprehensive response to the user
    Always explain your reasoning before taking actions.
    """).defaultTools(tools).defaultAdvisors(newMessageChatMemoryAdvisor(newInMemoryChatMemory())).build();}publicStringplanTrip(String userRequest){return chatClient.prompt().user(userRequest).call().content();}}

    Example Interaction

    User: "Plan a trip from NYC to London next month"

    Agent: THOUGHT: I need to search for flights first, then find hotels...

    ACTION: searchFlights("NYC", "London", "2024-02-15")

    5
    Best Practices

    Clear Tool Descriptions

    Write detailed descriptions for each tool so the LLM knows when and how to use them.

    Limit Tool Count

    Keep the number of tools manageable (5-10). Too many tools can confuse the model.

    Handle Errors Gracefully

    Tools should return helpful error messages that the agent can interpret and act upon.

    Set Execution Limits

    Limit the number of tool calls per request to prevent infinite loops and runaway costs.

    Security Considerations

    • Validate all tool inputs before execution
    • Implement rate limiting to prevent abuse
    • Use proper authentication for sensitive operations
    • Log all agent actions for auditing and debugging

    What You've Learned

    Agent Fundamentals

    What makes agents different from chatbots

    Architecture

    The agent loop and core components

    Tool Development

    Creating tools with @Tool annotation

    Agent Service

    Building agents with ChatClient

    ReAct Pattern

    Explicit reasoning before actions

    Best Practices

    Security and production considerations

    💬 Comments & Discussion