도구 호출 및 에이전트 조언자
호출 가능한 Java 도구로 모델을 확장하고 요청 및 응답 조언자를 조합해 동작을 구성합니다.
도구 호출 및 에이전트 조언자은(는) CoddyKit의 무료 Spring Boot 4 Complete Guide 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Spring Boot 4 Complete Guide 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Spring Boot 4 Complete Guide 강의에는 총 4개의 강의가 포함되어 있습니다.
이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.
Why Tool Calling Matters
Large language models can reason over text, but they cannot fetch a live order status, query your database, or call a payment gateway on their own. Tool calling (also called function calling) bridges that gap.
- The model decides when a tool is needed based on the user's request.
- Spring AI invokes the matching Java method and feeds the result back into the conversation.
- The model then produces a grounded, final answer.
In Spring AI, a tool is just an ordinary Java method annotated with @Tool. The framework reads the method signature and JavaDoc-style description, generates a JSON schema, and exposes it to the model.
Defining a Tool with @Tool
Annotate a method with @Tool and give it a clear description. The model uses that description to decide whether to call it, so write it as if you were instructing a junior developer.
- Use
@ToolParamto describe individual arguments. - Return types are serialized to JSON automatically.
- Keep the method deterministic and side-effect-aware.
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
@Component
class DateTools {
@Tool(description = "Get the number of days between today and a given target date")
int daysUntil(@ToolParam(description = "Target date in ISO-8601 format, e.g. 2026-12-31") String targetDate) {
LocalDate target = LocalDate.parse(targetDate);
return (int) java.time.temporal.ChronoUnit.DAYS.between(LocalDate.now(), target);
}
}Registering Tools on a ChatClient Call
Tools are attached per request through the fluent ChatClient API. Pass an instance whose annotated methods become callable tools for that exchange.
.tools(Object...)registers one or more tool-bearing beans.- The model may issue zero, one, or several tool calls before answering.
- Spring AI runs the full call loop transparently and returns the final text.
import org.springframework.ai.chat.client.ChatClient;
class AssistantService {
private final ChatClient chatClient;
AssistantService(ChatClient.Builder builder, DateTools dateTools) {
this.chatClient = builder.build();
}
String ask(String userText, DateTools dateTools) {
return chatClient.prompt()
.user(userText)
.tools(dateTools)
.call()
.content();
}
}The Tool Call Loop
Understanding the loop is essential for C2-level work. When the model requests a tool, Spring AI does not return control to you by default; it executes the tool and continues the conversation automatically.
- The model returns an assistant message containing one or more tool call requests.
- Spring AI matches each request to a registered method and invokes it.
- Results are wrapped as tool response messages and appended to the prompt.
- The model is called again with the enriched context until it emits a normal text answer.
This default behavior is driven by the framework's ToolCallingManager.
Programmatic Tools with FunctionToolCallback
Annotations are convenient, but sometimes you need tools defined at runtime or from a lambda. Use FunctionToolCallback to register a Function with an explicit name, description, and input type.
- The input type drives JSON schema generation.
- You stay in full control of serialization and naming.
- Useful for dynamically discovered capabilities.
import org.springframework.ai.tool.function.FunctionToolCallback;
import java.util.function.Function;
record WeatherRequest(String city) {}
record WeatherResponse(String city, double tempC) {}
class WeatherTool {
static FunctionToolCallback<WeatherRequest, WeatherResponse> callback() {
Function<WeatherRequest, WeatherResponse> fn =
req -> new WeatherResponse(req.city(), 21.5);
return FunctionToolCallback.builder("currentWeather", fn)
.description("Get the current temperature in Celsius for a city")
.inputType(WeatherRequest.class)
.build();
}
}Controlling Execution: returnDirect
Sometimes a tool's raw result should be returned straight to the caller without another model round-trip, for example when the tool already produced the final user-facing payload.
- Set
returnDirect = trueon@Toolto short-circuit the loop. - The framework returns the tool result instead of feeding it back to the model.
- This saves tokens and latency but skips the model's natural-language framing.
import org.springframework.ai.tool.annotation.Tool;
class TicketTools {
@Tool(description = "Open a support ticket and return its tracking id", returnDirect = true)
String openTicket(String summary) {
// Persist and return immediately; the id is the final answer
return "TICKET-" + Math.abs(summary.hashCode() % 100000);
}
}Introducing Advisors
Where tools extend what the model can do, advisors intercept and shape how each request and response flows. An advisor is a middleware in the ChatClient pipeline.
- Request advisors mutate the prompt before it reaches the model (inject context, retrieve documents, add system instructions).
- Response advisors post-process the model's output (logging, redaction, safety checks).
- Advisors are chained and ordered, much like servlet filters.
Spring AI ships several built-in advisors and lets you write your own by implementing the advisor interfaces.
Built-in Memory and RAG Advisors
Two of the most used built-in advisors:
MessageChatMemoryAdvisor— injects prior conversation turns so the model has memory across requests, backed by aChatMemorystore.QuestionAnswerAdvisor— performs retrieval-augmented generation by querying aVectorStoreand prepending relevant documents.
You register them on the builder so they apply to every call, or per-prompt for one-off behavior.
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
import org.springframework.ai.vectorstore.VectorStore;
class RagChatConfig {
ChatClient chatClient(ChatClient.Builder builder, ChatMemory memory, VectorStore store) {
return builder
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(memory).build(),
QuestionAnswerAdvisor.builder(store).build())
.build();
}
}Writing a Custom Advisor
Implement CallAdvisor to participate in the synchronous call chain. The key method receives the request, calls chain.nextCall(...), and can transform the response.
getName()identifies the advisor.getOrder()controls position; lower runs earlier on the request side.- Wrap
nextCallto add logging, timing, or content filtering.
import org.springframework.ai.chat.client.ChatClientRequest;
import org.springframework.ai.chat.client.ChatClientResponse;
import org.springframework.ai.chat.client.advisor.api.CallAdvisor;
import org.springframework.ai.chat.client.advisor.api.CallAdvisorChain;
class LoggingAdvisor implements CallAdvisor {
@Override
public ChatClientResponse adviseCall(ChatClientRequest request, CallAdvisorChain chain) {
long start = System.nanoTime();
ChatClientResponse response = chain.nextCall(request);
long ms = (System.nanoTime() - start) / 1_000_000;
System.out.println("[advisor] call took " + ms + "ms");
return response;
}
@Override
public String getName() { return "logging"; }
@Override
public int getOrder() { return 0; }
}Advisor Ordering and the Chain
Advisors form an ordered chain. Picture an onion: on the way in advisors run from lowest order to highest, and on the way out the responses unwind in reverse.
- A memory advisor with a low order injects history early so RAG and tools see it.
- A safety/redaction advisor often sits at a high order to inspect the final text last.
- Order ties are resolved by registration sequence; be explicit with
getOrder()to avoid surprises.
Because tools and advisors both operate on the same prompt, design their interaction deliberately: advisors prepare context, tools fetch live data, and a final response advisor can sanitize the merged result.
Composing Tools and Advisors Together
Real agents combine both mechanisms in a single fluent call. Here the client carries default memory and RAG advisors, while a domain tool is attached for this request.
- Advisors enrich the prompt with history and retrieved knowledge.
- The model may still call the tool to obtain live, authoritative data.
- The result is an agent that remembers, grounds, and acts.
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.api.Advisor;
class OrderAgent {
private final ChatClient chatClient;
OrderAgent(ChatClient chatClient) { this.chatClient = chatClient; }
String handle(String conversationId, String userText, OrderTools tools) {
return chatClient.prompt()
.user(userText)
.advisors(a -> a.param("chat_memory_conversation_id", conversationId))
.tools(tools)
.call()
.content();
}
}
class OrderTools { /* @Tool methods omitted */ }Quick Check
Test your understanding of the tool call loop and advisor design.
Recap
You now know how to extend models with callable Java code and compose request/response behavior:
- Tools are Java methods marked with
@Tool(or built viaFunctionToolCallback) that the model invokes to fetch data or act. - Spring AI runs the tool call loop automatically;
returnDirect = trueshort-circuits it. - Advisors are pipeline middleware: request advisors enrich the prompt (memory, RAG), response advisors post-process output (logging, safety).
- Advisors are ordered and unwind like an onion; design tool/advisor interaction deliberately.
- Combine memory + RAG advisors with domain tools to build agents that remember, ground, and act.
자주 묻는 질문
“도구 호출 및 에이전트 조언자” 강의는 무료인가요?
네 — “도구 호출 및 에이전트 조언자” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Spring Boot 4 Complete Guide 강의 전체를 잠금 해제할 수 있습니다. Spring Boot 4 Complete Guide 강의에는 총 4개의 강의가 포함되어 있습니다.
“도구 호출 및 에이전트 조언자”에서 뭘 배우나요?
호출 가능한 Java 도구로 모델을 확장하고 요청 및 응답 조언자를 조합해 동작을 구성합니다. 브라우저에서 직접 실행하는 실습 코드로 Spring Boot 4 Complete Guide을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Spring Boot 4 Complete Guide을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Spring Boot 4 Complete Guide은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“도구 호출 및 에이전트 조언자” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Spring Boot 4 Complete Guide 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Spring Boot 4 Complete Guide 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- ChatClient, 프롬프트 및 구조화된 출력
- 임베딩 및 벡터 저장소 검색
- 검색 증강 생성 파이프라인
- 도구 호출 및 에이전트 조언자