# Spring AI Tools Agents

> A complete guide for implementing tools and function calling in Spring AI, covering tool definition, execution, and building autonomous agents.

- Skill: `mat-garcia/spring-ai-tools-agents` (Agent Skill)
- Install (CLI): `npx skillmds@latest add mat-garcia/spring-ai-tools-agents`
- Raw SKILL.md: https://api.skillmd.com/api/skills/mat-garcia/spring-ai-tools-agents/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: Complete terms in LICENSE.txt
- Author: mat-garcia (https://skillmd.com/u/mat-garcia)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/mat-garcia/spring-ai-tools-agents

---


# Spring AI - Tools, Function Calling & Agents

## Description

Complete guide for implementing tools and function calling in Spring AI. Covers multiple tool definition patterns, tool execution strategies, error handling, and building autonomous agents with reasoning capabilities.

## When to Use

- Enabling models to call functions/APIs
- Building autonomous AI agents
- Implementing tool-use patterns (ReAct)
- Multi-step reasoning with actions
- API integration with LLMs
- Custom command execution
- Workflow automation
- Decision support systems

## Topics Covered

### 1. Tool Definition Patterns

#### @Tool Annotation (Simplest)

```java
@Component
public class MathTools {
    @Tool(description = "Calculates sum of two numbers")
    public int add(int a, int b) {
        return a + b;
    }
}
```

#### Functional Interface (Spring 6)

```java
@Configuration
public class ToolConfig {
    @Bean
    public java.util.function.Function<Request, Response> calculator() {
        return request -> { /* implementation */ };
    }
}
```

#### MethodToolCallback (Fine-grained)

```java
var addTool = MethodToolCallback.builder()
    .description("Add two numbers")
    .method(calculator::add)
    .inputType(AddRequest.class)
    .build();
```

#### Dynamic Tool Definition

- Runtime tool registration
- Plugin architecture
- Tool marketplace integration
- User-defined tools

### 2. Tool Specification Formats

- **OpenAI Function Calling**: JSON Schema format
- **Anthropic Tool Use**: Tool definition with input schema
- **Google Gemini Tools**: Function declarations
- **Bedrock Tools**: Tool specifications
- **Model-agnostic**: Adapter pattern

### 3. Tool Execution Modes

#### Framework-Controlled Execution

```java
chatClient.prompt()
    .user("Search for Spring Boot docs")
    .functions("searchWeb")
    .call()
    .content();
```

#### Advisor Pattern

- Tools automatically applied
- Middleware-style execution
- Configurable tool stack
- Error recovery

#### User-Controlled Execution

- Explicit function call detection
- Manual execution flow
- Fine-grained control
- Custom retry logic

### 4. Tool Response Handling

- **Text responses**: Direct content
- **Structured responses**: JSON objects
- **Media responses**: Images, files
- **Error responses**: Exception handling
- **Streaming responses**: Token-by-token

### 5. Tool Context & Metadata

- **Tool execution context**: Available context during execution
- **Tool state**: Maintaining state across calls
- **Tool metadata**: Versioning, dependencies
- **Security context**: Authorization, validation
- **Tracing**: Execution logging and debugging

### 6. Advanced Patterns

#### Tool Use Iterations (ReAct)

```
Thought → Action (Tool Call) → Observation → Repeat until Answer
```

#### Conditional Tool Chains

```
IF condition → Tool A → Tool B → Result
ELSE → Tool C → Result
```

#### Parallel Tool Execution

```
Execute Tool A, B, C in parallel → Aggregate results
```

#### Tool Exception Handling

- Graceful degradation
- Retry strategies
- Fallback tools
- Error reporting

## Code Patterns

### Basic Tool Definition

```java
@Component
public class WeatherTool {
    @Tool(description = "Get current weather for a location")
    public String getWeather(
            @Param(description = "City name") String city,
            @Param(description = "Country code") String country) {
        return "Sunny, 72°F in " + city;
    }
}
```

### Tool with ChatModel

```java
@Service
public class AgentService {
    @Autowired
    private ChatModel chatModel;

    @Autowired
    private WeatherTool weatherTool;

    public String runAgent(String query) {
        var tools = List.of(
            MethodToolCallback.builder()
                .description("Get weather")
                .method(weatherTool::getWeather)
                .inputType(WeatherRequest.class)
                .build()
        );

        Prompt prompt = new Prompt(
            new UserMessage(query),
            new ChatOptions() { }
        );

        ChatResponse response = chatModel.call(prompt);
        return response.getResult().getOutput().getContent();
    }
}
```

### Tool Calling with ChatClient

```java
String result = chatClient.prompt()
    .user("What's the weather in San Francisco?")
    .functions("getWeather", "getLocation")
    .call()
    .content();
```

### ReAct Loop (Autonomous Agent)

```java
public String reagentLoop(String question, int maxIterations) {
    String currentThought = question;

    for (int i = 0; i < maxIterations; i++) {
        // LLM generates thought + action
        var response = chatClient.prompt()
            .user(currentThought)
            .functions("tool1", "tool2", "tool3")
            .call();

        String content = response.getResult().getOutput().getContent();

        // Check if we have final answer
        if (content.contains("Final Answer:")) {
            return content;
        }

        // Extract tool call and execute
        var toolCall = parseToolCall(content);
        var observation = executeTool(toolCall);

        currentThought = "Observation: " + observation + "\nThink about next step";
    }

    return "Max iterations reached";
}
```

### Streaming Function Calls

```java
chatClient.prompt()
    .user("Run analysis tools")
    .stream()
    .toolCall()
    .subscribe(toolCall -> {
        Object result = executeTool(toolCall);
        logger.info("Tool {} returned: {}", toolCall.getName(), result);
    });
```

### Error Handling in Tools

```java
@Tool(description = "Divide two numbers")
public double divide(double a, double b) {
    if (b == 0) {
        throw new IllegalArgumentException("Cannot divide by zero");
    }
    return a / b;
}
```

### Tool with Return Direct

```java
// Return result directly without LLM further processing
@Tool(description = "Execute SQL query",
      returnDirect = true)
public String executeSql(String query) {
    return database.executeQuery(query);
}
```

## Tool Advisor Pattern

```java
@Configuration
public class ToolAdvisorConfig {
    @Bean
    public ChatClientRequestAdvisor toolAdvisor(ChatModel chatModel) {
        return new ToolsAdvisor(
            chatModel,
            List.of(weatherTool, databaseTool, webTool)
        );
    }
}
```

## Configuration

### Tool Execution Properties

```properties
spring.ai.tool.max-iterations=10
spring.ai.tool.timeout=30s
spring.ai.tool.error-recovery=true
spring.ai.tool.streaming.enabled=true
```

### Tool Registration

```java
@Configuration
public class ToolRegistration {
    @Bean
    public ToolCallbackRegistry toolRegistry(
            WeatherTool weather,
            DatabaseTool database) {
        return new ToolCallbackRegistry()
            .register("getWeather", weather::getWeather)
            .register("queryDb", database::query);
    }
}
```

## Tool Discovery & Composition

### Auto-discovery

```java
// Spring automatically discovers @Tool annotated methods
@Component
public class ToolLibrary {
    @Tool
    public String tool1() { }

    @Tool
    public String tool2() { }
}
```

### Manual Registration

```java
registry.register("custom", customToolCallback);
```

## Best Practices

- Keep tools focused and composable
- Provide clear descriptions for LLM understanding
- Validate input parameters
- Implement proper error handling
- Monitor tool execution
- Cache tool results when appropriate
- Version tools appropriately
- Test tools independently

## Related Skills

- `advisors/SKILL.md` - Advisor pattern
- `chat-models/SKILL.md` - Chat models
- `agents/SKILL.md` - Agent patterns
- `rag-retrieval/SKILL.md` - RAG integration

## References

- API: `/pages/api/tools.adoc`
- Migration: `/pages/api/tools-migration.adoc`
- ChatModel: `/pages/api/chatmodel.adoc`
- Examples: Tool calling examples in provider docs

