Skip to content

What Is Spring AI Tool Argument Augmenter and How Does It Work

What Problem Does It Solve?

When I started building AI agents with Spring AI, I noticed a gap in observability. The tool calling worked great, but I couldn’t see the decision-making process.

My application knew:

  • Which tool was called
  • What arguments were passed
  • What result was returned

But it didn’t know:

  • Why the LLM chose that specific tool
  • What alternatives it considered
  • How confident it was in the decision

The Tool Argument Augmenter solves this by letting you inject metadata capture into the tool calling flow.

What Is the Tool Argument Augmenter?

The Tool Argument Augmenter is a Spring AI component that dynamically extends tool JSON schemas with additional parameters. It intercepts tool definitions before they reach the LLM, adds extra arguments, and extracts the LLM’s responses to those arguments.

Think of it as an “explainability layer” on top of standard tool calling.

How It Works

Here’s the complete flow:

flowchart TD
A[Spring AI sends tool definitions] --> B[Augmenter intercepts schemas]
B --> C[Extend schemas with metadata args]
C --> D[Send extended definitions to LLM]
D --> E[LLM selects tool and fills all args]
E --> F[Augmenter extracts metadata args]
F --> G[Forward metadata to consumer]
G --> H[Invoke tool with original args only]
H --> I[Return tool result]

Step-by-Step Breakdown

  1. Spring AI prepares tool definitions - Your @Tool annotated methods get converted to JSON schemas

  2. Augmenter intercepts and extends - Before sending to the LLM, the augmenter adds extra parameters to each schema

  3. LLM receives extended schemas - The LLM sees both original tool arguments and the augmented metadata arguments

  4. LLM makes a decision - When selecting a tool, the LLM fills in all arguments, including your metadata fields

  5. Augmenter extracts metadata - The augmenter pulls out the metadata arguments before tool invocation

  6. Tool is invoked normally - Your tool method receives only its expected arguments, unaware of the augmentation

A Concrete Example

Let’s say you have a tool for retrieving patient information:

PatientTools.java
@Tool(description = "Get patient health status")
public String retrievePatientHealthStatus(String patientId) {
return HEALTH_DATA.get(patientId).status();
}

Without augmentation, the JSON schema sent to the LLM looks like this:

tool_schema_without_augmentation.json
{
"name": "retrievePatientHealthStatus",
"description": "Get patient health status",
"parameters": {
"type": "object",
"properties": {
"patientId": {
"type": "string"
}
},
"required": ["patientId"]
}
}

With the augmenter, the schema becomes:

tool_schema_with_augmentation.json
{
"name": "retrievePatientHealthStatus",
"description": "Get patient health status",
"parameters": {
"type": "object",
"properties": {
"patientId": {
"type": "string"
},
"innerThought": {
"type": "string",
"description": "Your step-by-step reasoning for why you're calling this tool."
},
"confidence": {
"type": "string",
"description": "Your confidence level (low, medium, high)"
}
},
"required": ["patientId", "innerThought", "confidence"]
}
}

The LLM fills in all fields, and the augmenter extracts innerThought and confidence before calling your tool.

Setting Up the Augmenter

1. Define Your Metadata Structure

AgentThinking.java
public record AgentThinking(
@ToolParam(description = "Your reasoning for selecting this tool", required = true)
String innerThought,
@ToolParam(description = "Confidence level (low, medium, high)", required = true)
String confidence
) {}

2. Configure the Provider

ToolConfiguration.java
@Configuration
public class ToolConfiguration {
@Bean
public AugmentedToolCallbackProvider<AgentThinking> toolProvider(
Object... toolObjects) {
return AugmentedToolCallbackProvider
.<AgentThinking>builder()
.toolObjects(toolObjects)
.argumentType(AgentThinking.class)
.argumentConsumer(event -> {
AgentThinking thinking = event.arguments();
// Store in database
reasoningRepository.save(new ReasoningRecord(
event.toolDefinition().name(),
thinking.innerThought(),
thinking.confidence(),
Instant.now()
));
})
.build();
}
}

3. Use in ChatClient

AgentService.java
@Service
public class AgentService {
private final ChatClient chatClient;
public AgentService(
ChatClient.Builder builder,
AugmentedToolCallbackProvider<AgentThinking> provider) {
this.chatClient = builder
.defaultToolCallbacks(provider)
.build();
}
public String process(String input) {
return chatClient.prompt()
.user(input)
.call()
.content();
}
}

What Can You Do With the Captured Data?

Debugging

.argumentConsumer(event -> {
log.debug("Tool decision: {}", event.arguments().innerThought());
})

Auditing

.argumentConsumer(event -> {
auditLog.record(
"Tool call: %s, Reasoning: %s".formatted(
event.toolDefinition().name(),
event.arguments().innerThought()
)
);
})

Performance Analysis

.argumentConsumer(event -> {
metrics.counter("tool.calls",
"tool", event.toolDefinition().name(),
"confidence", event.arguments().confidence()
).increment();
})

Prompt Improvement

Collect reasoning data to understand where your tool descriptions confuse the LLM:

.argumentConsumer(event -> {
if ("low".equals(event.arguments().confidence())) {
lowConfidenceEvents.add(event);
}
})

Common Mistake: Adding Parameters to Tool Methods

I see this mistake often. Developers add reasoning parameters directly to their tool signatures:

WrongApproach.java
// DON'T DO THIS
@Tool(description = "Get patient status")
public String retrievePatientHealthStatus(
String patientId,
String reasoning, // This is wrong
String confidence // This is wrong
) {
// Now your tool has mixed concerns
}

Why this is problematic:

  1. Coupling: Tools become tied to your observability strategy
  2. Reuse: You can’t use the tool elsewhere without the reasoning baggage
  3. Testing: Tests must mock reasoning arguments
  4. Clarity: The tool’s purpose becomes ambiguous

The augmenter pattern keeps tools focused on business logic while enabling enterprise-grade observability.

When to Use It

Use the Tool Argument Augmenter when:

  • You need to audit AI decisions for compliance
  • You’re debugging unexpected tool selections
  • You want to improve your tool descriptions based on LLM confusion
  • You’re building production AI systems that require explainability

Skip it when:

  • You’re prototyping quickly
  • Your tools are trivial (single tool, obvious selection)
  • You don’t need to explain the AI’s behavior

Summary

The Tool Argument Augmenter extends tool JSON schemas to capture metadata during LLM tool selection. It intercepts tool definitions, adds extra arguments, extracts the LLM’s responses, and forwards metadata to a consumer. Your tools remain unaware of the augmentation, keeping business logic clean. Use it for debugging, auditing, compliance, and improving your AI agents.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments