1. The Tool Execution Loop
A tool execution sequence requires a multi-turn lifecycle. The LLM acts as an orchestrator, signaling tool calls back to the application server for physical execution before ingesting the returned payload to formulate a final user-facing response.
Selects tool & generates JSON arguments. LLM-->>App: Stop Reason: tool_calls [name, args_json, call_id] App->>Tool: Execute function locally with parsed args Tool-->>App: Execution Output Payload (JSON / String) App->>LLM: Append Tool Result Turn (role='tool', call_id, content) Note over LLM: Synthesizes final answer
incorporating tool data. LLM-->>App: Final Natural Language / Structured Response
2. Tool Declaration Schema Architecture
Tools are declared using JSON Schema specifications. The model reads the descriptions to determine suitability during inference:
| Schema Element | System Function | Design Best Practice |
|---|---|---|
name |
Unique identifier used by the router to route execution to a handler. | Use snake_case action verbs: get_user_account_balance. |
description |
Semantic documentation read by the model to decide whether to call the tool. | Explicitly document edge cases and required formats (e.g., ISO-8601 dates). |
parameters |
JSON schema object defining types, descriptions, and required keys. | Mark mandatory parameters in the required list; provide strict enums where applicable.
|
3. Parallel Tool Calling vs. Sequential Execution
Modern models support Parallel Tool Calling, emitting multiple tool invocations within a single inference response.
4. Dual-Stack Implementations: Full Function Calling Loop
Registering a mock database lookup tool, processing the model's call request, executing the handler, and returning the final synthesized answer:
import json
from openai import OpenAI
client = OpenAI()
# 1. Local Tool Implementation
def query_user_tier(user_id: str) -> dict:
# Simulated database lookup
database = {"usr_42": {"tier": "PLATINUM", "retention_score": 0.94}}
return database.get(user_id, {"tier": "FREE", "retention_score": 0.10})
# 2. Tool Schema Declaration
tools = [{
"type": "function",
"function": {
"name": "query_user_tier",
"description": "Fetch user loyalty tier and retention metrics by user ID.",
"parameters": {
"type": "object",
"properties": {
"user_id": {"type": "string", "description": "The unique user identifier (e.g. usr_42)"}
},
"required": ["user_id"]
}
}
}]
# 3. Initial Inference Turn
messages = [{"role": "user", "content": "What is the membership tier of usr_42?"}]
response = client.chat.completions.create(model="gpt-4o-mini", messages=messages, tools=tools)
choice = response.choices[0]
# 4. Handle Tool Calling Loop
if choice.message.tool_calls:
messages.append(choice.message) # Append assistant's tool-request turn
for tool_call in choice.message.tool_calls:
if tool_call.function.name == "query_user_tier":
args = json.loads(tool_call.function.arguments)
result = query_user_tier(args["user_id"])
# Append tool result turn
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result)
})
# 5. Final Synthesis
final_response = client.chat.completions.create(model="gpt-4o-mini", messages=messages)
print(final_response.choices[0].message.content)
import dev.langchain4j.agent.tool.Tool
import dev.langchain4j.memory.chat.MessageWindowChatMemory
import dev.langchain4j.model.openai.OpenAiChatModel
import dev.langchain4j.service.AiServices
// 1. Define Tool Service with Annotations
class UserMembershipTools {
@Tool("Fetch user loyalty tier and retention metrics by user ID")
fun queryUserTier(userId: String): String {
return if (userId == "usr_42") {
"""{"tier": "PLATINUM", "retention_score": 0.94}"""
} else {
"""{"tier": "FREE", "retention_score": 0.10}"""
}
}
}
// 2. High-Level AI Service Interface
interface CustomerSupportAgent {
fun chat(message: String): String
}
fun main() {
val chatModel = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-4o-mini")
.build()
// 3. Bind Service with Reflective Tool Dispatch
val agent = AiServices.builder(CustomerSupportAgent::class.java)
.chatLanguageModel(chatModel)
.tools(UserMembershipTools())
.chatMemory(MessageWindowChatMemory.withMaxMessages(10))
.build()
// LangChain4j automatically extracts JSON schema, detects tool calls,
// runs queryUserTier() on JVM, and feeds the response back to the LLM.
val response = agent.chat("What is the membership tier of usr_42?")
println(response)
}
5. Exception Handling & Sandboxed Execution
- Graceful Degradation: If a downstream tool (such as a database query or external REST API)
fails with a 500 error or timeout, do not crash the LLM conversation loop. Package the exception into a JSON
error response:
{"error": "Database query timed out after 3000ms"}and pass it back in the tool turn. The model can then apologize to the user or attempt an alternate strategy. - Least Privilege Execution: Tools should never run un-sanitized raw arbitrary SQL or shell commands. Wrap operations in typed functions with strict parameter bounds to avoid privilege escalation.
6. Progressive Glossary
| Term | Technical Definition | Mobile / Systems Analogy |
|---|---|---|
| Tool Calling | Inference mode where the model returns an operational command and typed parameters instead of text. | Android Explicit Intent creation with serialized Bundle arguments. |
| Tool Call ID | A unique transaction token pairing an LLM tool request with its subsequent execution output. | requestCode in startActivityForResult() or a Coroutine Job handle. |
| Parallel Tool Calling | Emitting multiple tool requests in a single forward pass to execute independent side-effects concurrently. | kotlinx.coroutines.awaitAll() over multiple concurrent async network requests. |
| Tool Choice Constraint | Forcing the model to invoke a specific tool (tool_choice: {"name": "..."}) or generate
plain text (tool_choice: "none"). |
Explicit Intent targeting an exact ComponentName vs. Implicit Intent broadcast resolution. |
Sources & Reference Standards
- OpenAI Developer Platform: Function Calling and Structured Tool Execution
- Anthropic Documentation: Tool Use (Function Calling) Implementation Patterns
- LangChain4j Architecture: Declarative Tool Annotations and Dispatch Loop