09 — Function Calling & Tool Calling¶
Learn how Large Language Models (LLMs) can interact with external functions, APIs, databases, enterprise services, and tools through structured function and tool calling mechanisms.
📖 Overview¶
Large Language Models are powerful at understanding natural language and generating responses.
However, an LLM by itself cannot reliably perform actions such as:
Query a database
Call an enterprise API
Check an order
Retrieve inventory
Calculate a complex value
Create a support ticket
Send a notification
Search internal documents
Retrieve monitoring metrics
Execute an approved business operation
This is where Function Calling and Tool Calling become important.
Instead of allowing the model to directly execute operations, the model generates a structured request describing the operation it wants the application to perform.
The application then:
Receives the request
↓
Validates the request
↓
Checks authorization
↓
Executes the function/tool
↓
Returns the result to the LLM
↓
Generates the final response
The fundamental architecture is:
User
↓
LLM
↓
Tool / Function Request
↓
Application
↓
Tool Execution
↓
Tool Result
↓
LLM
↓
Final Response
This pattern is one of the most important foundations for:
- AI assistants
- Enterprise copilots
- RAG applications
- AI agents
- Workflow automation
- Backend AI services
- Agentic AI systems
1. What Is Function Calling?¶
Function Calling allows an LLM to generate a structured request to invoke a predefined function.
For example, suppose an application exposes:
A user asks:
The model does not need to know the weather itself.
Instead, it can request:
The application executes:
and returns the result to the model.
2. What Is Tool Calling?¶
Tool Calling is the broader concept of allowing an LLM to request the execution of external capabilities.
A tool can represent:
Function
API
Database Query
Search Engine
Retriever
Calculator
Code Execution
Enterprise Service
Cloud Service
Workflow
Conceptually:
Modern LLM platforms and AI frameworks often use the term tool calling because it better represents the broader capability model.
3. Function Calling vs Tool Calling¶
These terms are frequently used interchangeably, but there is a useful distinction.
| Concept | Meaning |
|---|---|
| Function Calling | Model requests execution of a specific function |
| Tool Calling | Model requests execution of an external capability |
| Tool | Capability exposed to the LLM |
| Function | Implementation behind a capability |
| Tool Schema | Defines inputs and sometimes outputs |
| Tool Executor | Application component that executes the tool |
A useful mental model is:
4. Why Function Calling Matters¶
Without function calling:
The application might receive:
It then has to determine:
With function calling:
For example:
The intent is much easier for the application to process.
5. Function Calling Architecture¶
flowchart TD
A["User"] --> B["Application"]
B --> C["LLM"]
C --> D["Function / Tool Call"]
D --> E["Application Tool Executor"]
E --> F["Enterprise Function"]
F --> G["Tool Result"]
G --> C
C --> H["Final Response"]
H --> B
B --> A
The application remains responsible for execution.
6. The Most Important Principle¶
A critical production principle is:
The LLM should request an action; the application should decide whether and how that action is executed.
Do not design the architecture as:
Prefer:
The LLM is therefore a decision-making interface, not the security boundary.
7. Basic Function Calling Flow¶
Consider:
The LLM identifies that it needs external information.
It generates:
The application executes:
The function returns:
The application sends this result back to the model.
The model generates:
8. Complete Function Calling Loop¶
sequenceDiagram
participant U as User
participant A as Application
participant L as LLM
participant T as Tool
participant S as Enterprise Service
U->>A: User Request
A->>L: Prompt + Tool Definitions
L->>A: Tool Call
A->>T: Execute Tool
T->>S: Service Request
S->>T: Service Response
T->>A: Tool Result
A->>L: Tool Result
L->>A: Final Response
A->>U: Answer
9. Tool Definitions¶
Before the model can call a tool, the application needs to describe the tool.
A tool definition generally includes:
For example:
{
"name": "get_order",
"description": "Retrieve the current status of an order.",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "Unique order identifier"
}
},
"required": [
"order_id"
]
}
}
The model uses this description to determine:
and:
10. Tool Name¶
A tool name should be:
Good:
Poor:
Tool names are part of the model-facing interface.
11. Tool Description¶
The description should clearly explain:
Example:
{
"name": "get_inventory",
"description": "Retrieve the current available inventory quantity for a product using its product ID."
}
A vague description can lead to incorrect tool selection.
12. Tool Input Schema¶
Tool arguments should be strongly typed.
Example:
{
"type": "object",
"properties": {
"product_id": {
"type": "string"
},
"warehouse_id": {
"type": "string"
}
},
"required": [
"product_id",
"warehouse_id"
]
}
The model can now produce:
13. Tool Schema as a Contract¶
The schema acts as a contract between:
and:
The flow becomes:
This is significantly safer than parsing natural-language instructions.
14. Function Calling vs Natural Language Instructions¶
Natural Language¶
The application has to infer:
Function Calling¶
The application receives a structured request.
15. Multiple Tools¶
An enterprise AI application may expose multiple tools:
get_customer
get_order
get_inventory
get_payment
search_documents
calculate
create_ticket
get_metrics
The model can choose the appropriate tool.
flowchart TD
A["User Request"] --> B["LLM"]
B --> C["Customer Tool"]
B --> D["Order Tool"]
B --> E["Inventory Tool"]
B --> F["Payment Tool"]
B --> G["Search Tool"]
B --> H["Calculator"]
C --> I["Tool Results"]
D --> I
E --> I
F --> I
G --> I
H --> I
I --> B
B --> J["Final Response"]
16. Tool Selection¶
Tool selection is a key capability.
Suppose the application exposes:
User asks:
The correct tool is:
User asks:
The correct tool is:
The model should not call unrelated tools.
17. Tool Selection Is Not Authorization¶
The model may select:
But that does not mean the operation should be executed.
The application must independently check:
Therefore:
18. Tool Execution Boundary¶
flowchart LR
A["LLM"] --> B["Tool Request"]
B --> C["Tool Gateway"]
C --> D["Schema Validation"]
D --> E["Authorization"]
E --> F["Business Rules"]
F --> G["Tool Execution"]
G --> H["External System"]
The tool gateway provides an important control boundary.
19. Tool Calling and Structured Outputs¶
The previous chapter introduced structured outputs.
Tool calling builds directly on the same idea.
A tool request is itself structured.
Example:
The application validates:
before execution.
20. Structured Output vs Tool Call¶
Structured Output¶
The model returns structured information.
Tool Call¶
{
"name": "create_support_ticket",
"arguments": {
"category": "payment_issue",
"priority": "high"
}
}
The model requests an operation.
21. Tool Calling + Structured Final Output¶
Both can be combined:
flowchart TD
A["User"] --> B["LLM"]
B --> C["Tool Call"]
C --> D["Tool"]
D --> E["Tool Result"]
E --> B
B --> F["Structured Final Output"]
F --> G["Schema Validation"]
G --> H["Application"]
This is common in enterprise AI systems.
22. Function Calling and ReAct¶
The previous chapter introduced ReAct.
ReAct:
Tool calling provides the mechanism for:
The combined architecture is:
Therefore:
Tool calling is an execution mechanism that can participate in a ReAct-style loop.
23. ReAct + Tool Calling¶
flowchart TD
A["User Request"] --> B["LLM"]
B --> C["Reason"]
C --> D["Tool Call"]
D --> E["Tool Executor"]
E --> F["External System"]
F --> G["Observation"]
G --> B
B --> H["Final Answer"]
This is one of the foundations of modern AI agent architectures.
24. Function Calling and RAG¶
Retrieval can also be exposed as a tool.
For example:
The model can request:
The application executes retrieval.
The returned documents become tool observations.
25. Tool-Based Retrieval¶
flowchart TD
A["User Question"] --> B["LLM"]
B --> C["search_knowledge_base"]
C --> D["Retriever"]
D --> E["Vector Database"]
E --> F["Retrieved Documents"]
F --> B
B --> G["Final Answer"]
This creates a bridge between:
and:
26. Function Calling and APIs¶
A tool can wrap an existing REST API.
For example:
may internally call:
The model does not need to know the internal API details.
Architecture:
27. API Tool Example¶
import requests
def get_customer(customer_id: str):
response = requests.get(
f"https://customer-service/customers/{customer_id}",
timeout=3
)
response.raise_for_status()
return response.json()
The tool hides infrastructure details from the LLM.
28. Function Calling and Microservices¶
In an enterprise environment, tools can expose capabilities of microservices.
Customer Service
↓
Customer Tool
Order Service
↓
Order Tool
Payment Service
↓
Payment Tool
Inventory Service
↓
Inventory Tool
The AI layer becomes an orchestration layer over selected business capabilities.
29. Enterprise Tool Architecture¶
flowchart TD
A["AI Application"] --> B["Tool Registry"]
B --> C["Customer Tool"]
B --> D["Order Tool"]
B --> E["Payment Tool"]
B --> F["Inventory Tool"]
C --> G["Customer Service"]
D --> H["Order Service"]
E --> I["Payment Service"]
F --> J["Inventory Service"]
30. Capability-Based Architecture¶
Instead of coupling the AI application directly to infrastructure, define capabilities.
For example:
Implementation:
@Component
public class OrderServiceProvider
implements OrderProvider {
@Override
public Order getOrder(String orderId) {
return orderRepository.findById(orderId);
}
}
The AI tool can invoke the capability.
31. Why Capability Interfaces Matter¶
This keeps:
separate from:
and:
For example:
This aligns well with a Ports & Adapters architecture.
32. Tool Registry¶
A production AI platform may maintain a registry:
Tool Registry
├── get_customer
├── get_order
├── get_inventory
├── search_documents
├── calculate
└── create_ticket
The registry can manage:
33. Tool Registry Architecture¶
flowchart TD
A["Agent / LLM"] --> B["Tool Registry"]
B --> C["Tool Metadata"]
B --> D["Tool Schema"]
B --> E["Permission Policy"]
B --> F["Tool Version"]
B --> G["Tool Gateway"]
G --> H["Tool Execution"]
This becomes increasingly useful as the number of tools grows.
34. Tool Gateway¶
A centralized tool gateway can provide:
Authentication
Authorization
Schema Validation
Rate Limiting
Timeouts
Retries
Audit Logging
Tracing
Policy Enforcement
Architecture:
35. Tool Gateway Architecture¶
flowchart TD
A["LLM"] --> B["Tool Gateway"]
B --> C["Authentication"]
C --> D["Authorization"]
D --> E["Schema Validation"]
E --> F["Rate Limiting"]
F --> G["Policy Enforcement"]
G --> H["Tool Executor"]
H --> I["Enterprise System"]
36. Read Tools vs Write Tools¶
Not all tools carry the same risk.
Read Tools¶
Write Tools¶
Write operations require stronger controls.
37. Risk Classification¶
Tools can be classified:
LOW RISK
↓
Read-only operations
MEDIUM RISK
↓
Limited updates
HIGH RISK
↓
Financial / infrastructure / destructive operations
High-risk tools may require:
38. Human Approval¶
For high-impact operations:
Example:
LLM:
Request refund of $25,000.
System:
Manager approval required.
Manager:
Approve.
System:
Execute refund.
Architecture:
flowchart TD
A["LLM"] --> B["Tool Request"]
B --> C["Risk Evaluation"]
C --> D{"Approval Required?"}
D -->|No| E["Execute"]
D -->|Yes| F["Human Approval"]
F --> G{"Approved?"}
G -->|Yes| E
G -->|No| H["Reject"]
E --> I["Result"]
39. Tool Argument Validation¶
Never trust model-generated arguments.
Suppose the tool expects:
The model could generate:
or:
The application must validate the arguments.
40. Python Validation Example¶
from pydantic import BaseModel, Field
class RefundRequest(BaseModel):
order_id: str
amount: float = Field(
gt=0,
le=100000
)
This establishes constraints:
Business rules may impose additional constraints.
41. Java Validation Example¶
public record RefundRequest(
@NotBlank
String orderId,
@Positive
@Max(100000)
BigDecimal amount
) {
}
The application can validate the tool request before execution.
42. Tool Result Validation¶
Tool results should also be validated.
Example:
from pydantic import BaseModel
class InventoryResult(BaseModel):
product_id: str
quantity: int
available: bool
The tool executor can validate the response before returning it to the LLM.
43. Tool Input and Output Contracts¶
A mature tool should define:
Example:
get_inventory
Input:
product_id: string
warehouse_id: string
Output:
product_id: string
warehouse_id: string
quantity: integer
available: boolean
This creates predictable tool behavior.
44. Tool Contract Architecture¶
flowchart LR
A["LLM"] --> B["Input Schema"]
B --> C["Tool"]
C --> D["Output Schema"]
D --> E["LLM"]
The tool contract is effectively an API contract.
45. Tool Errors¶
Tools can fail because of:
Timeout
Authentication Failure
Authorization Failure
Validation Error
Rate Limit
Network Failure
Service Unavailable
Database Error
Business Rule Failure
The application should convert infrastructure errors into controlled tool responses.
46. Tool Error Example¶
Instead of exposing:
the model may receive:
{
"error": {
"type": "timeout",
"message": "The order service did not respond within the allowed time."
}
}
This keeps infrastructure details controlled.
47. Tool Failure Workflow¶
flowchart TD
A["Tool Request"] --> B["Tool"]
B --> C{"Success?"}
C -->|Yes| D["Tool Result"]
C -->|No| E["Error Handler"]
E --> F{"Retryable?"}
F -->|Yes| G["Bounded Retry"]
G --> B
F -->|No| H["Controlled Error"]
D --> I["LLM"]
H --> I
48. Timeouts¶
Every external tool should have a bounded timeout.
Example:
def get_order(order_id: str):
response = requests.get(
f"https://order-service/orders/{order_id}",
timeout=3
)
response.raise_for_status()
return response.json()
A tool should not block the entire AI workflow indefinitely.
49. Retries¶
Retries should be applied only when appropriate.
For example:
But:
A production retry strategy should use:
50. Idempotency¶
Write operations need special care.
Suppose the model calls:
The request times out.
The model may retry.
Without idempotency:
may be created.
A production tool should use an idempotency key when appropriate.
51. Idempotent Tool Architecture¶
flowchart LR
A["LLM"] --> B["Tool Request"]
B --> C["Idempotency Check"]
C --> D{"Already Processed?"}
D -->|Yes| E["Return Existing Result"]
D -->|No| F["Execute Operation"]
F --> G["Persist Result"]
G --> H["Return Result"]
E --> I["LLM"]
H --> I
52. Tool Calling and Security¶
Function calling introduces an important security boundary.
The model can generate:
But the application must enforce:
The model cannot grant itself permissions.
53. Least Privilege¶
A tool should receive only the permissions required.
Prefer:
instead of:
Similarly:
instead of:
54. Tool Allowlists¶
An AI application can maintain an explicit allowlist:
Before execution:
This prevents arbitrary model-generated tool names from being executed.
55. Environment-Based Tool Access¶
Tool availability can differ between environments.
Example:
Development
├── search_documents
├── get_order
└── test_payment
Production
├── search_documents
└── get_order
Dangerous tools may be disabled entirely in production AI environments unless explicitly required.
56. Tool Versioning¶
Tools evolve.
Example:
Versioning helps maintain compatibility.
A tool registry can maintain:
57. Tool Ownership¶
Enterprise tools should have clear ownership.
Example:
get_order
Owner: Order Platform Team
get_customer
Owner: Customer Platform Team
get_inventory
Owner: Supply Chain Team
This improves:
58. Tool Observability¶
Every tool call should be observable.
Useful metrics include:
Tool Calls
Tool Success Rate
Tool Error Rate
Tool Latency
Tool Timeout Rate
Tool Retry Rate
Tool Selection Accuracy
Tool Cost
59. Tool Tracing¶
A distributed trace may look like:
Request
├── LLM Call
│
├── Tool: get_customer
│ └── Customer Service
│
├── Tool: get_order
│ └── Order Service
│
└── Final LLM Call
This makes multi-step AI workflows easier to debug.
60. Tool Logging¶
A useful tool log may contain:
{
"request_id": "REQ-1001",
"tool": "get_order",
"status": "success",
"latency_ms": 42,
"timestamp": "2026-08-10T10:30:00Z"
}
Avoid logging:
61. Prompt Injection and Tools¶
Tool calling creates additional prompt-injection risks.
Suppose a retrieved document contains:
The model may interpret this as an instruction.
The application must ensure that:
cannot directly override:
62. Tool Results Are Data¶
A critical security principle is:
Tool results should be treated as data, not as trusted instructions.
For example:
The application should treat:
as untrusted content.
63. Tool Result Injection¶
flowchart TD
A["External System"] --> B["Tool Result"]
B --> C["LLM"]
C --> D["Potential Instruction Injection"]
D --> E["Policy Enforcement"]
E --> F["Tool Gateway"]
F --> G["Authorization"]
The model should never be the final authority for privileged operations.
64. Tool Calling and PII¶
Tools may expose sensitive information.
For example:
The tool should return only what is required.
Prefer:
instead of:
65. Data Minimization¶
A good tool design follows:
This reduces:
66. Function Calling with Python¶
A simplified function:
Tool schema:
tool_definition = {
"name": "get_order",
"description": "Get the current status of an order.",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string"
}
},
"required": ["order_id"]
}
}
The model can use this definition to generate a structured tool request.
67. Generic Tool Executor¶
A simple application-side dispatcher:
TOOLS = {
"get_order": get_order
}
def execute_tool(name: str, arguments: dict):
if name not in TOOLS:
raise ValueError(
f"Unknown tool: {name}"
)
function = TOOLS[name]
return function(**arguments)
This illustrates the basic architecture.
Production systems require significantly stronger validation and authorization.
68. Tool Dispatcher¶
flowchart TD
A["Tool Call"] --> B["Dispatcher"]
B --> C{"Known Tool?"}
C -->|No| D["Reject"]
C -->|Yes| E["Validate Arguments"]
E --> F["Authorization"]
F --> G["Execute Function"]
G --> H["Tool Result"]
69. Framework Example — LangChain¶
LangChain provides abstractions for defining tools.
A simplified example:
from langchain_core.tools import tool
@tool
def get_order(order_id: str) -> str:
"""Retrieve the current status of an order."""
return f"Order {order_id}: SHIPPED"
The function becomes a tool that can be exposed to an LLM-driven workflow.
The conceptual architecture remains:
70. LangChain Tool Architecture¶
flowchart LR
A["User"] --> B["LangChain"]
B --> C["LLM"]
C --> D["Tool Call"]
D --> E["LangChain Tool"]
E --> F["Application Function"]
F --> E
E --> C
C --> G["Final Response"]
LangChain provides orchestration abstractions, while application-level authorization and business rules should remain under application control.
71. LangChain Tool with Structured Input¶
A tool can use a typed input model.
from pydantic import BaseModel, Field
from langchain_core.tools import StructuredTool
class OrderInput(BaseModel):
order_id: str = Field(
description="Unique order identifier"
)
def get_order(order_id: str):
return {
"order_id": order_id,
"status": "SHIPPED"
}
order_tool = StructuredTool.from_function(
func=get_order,
args_schema=OrderInput
)
This provides a structured argument contract.
72. Framework Example — LlamaIndex¶
LlamaIndex can expose Python functions as tools.
from llama_index.core.tools import FunctionTool
def get_order(order_id: str) -> str:
return f"Order {order_id}: SHIPPED"
order_tool = FunctionTool.from_defaults(
fn=get_order
)
The framework can use the function metadata as part of an agent or workflow.
73. LlamaIndex Tool Architecture¶
flowchart LR
A["LLM"] --> B["LlamaIndex"]
B --> C["Tool Selection"]
C --> D["FunctionTool"]
D --> E["Application Function"]
E --> D
D --> B
B --> F["Final Response"]
The detailed framework-specific architecture belongs to Part VIII — AI Engineering Frameworks & Tooling.
Here the focus is the underlying engineering concept.
74. Framework-Agnostic Tool Interface¶
Enterprise AI applications should ideally define capability interfaces independently of the framework.
For example:
public interface InventoryProvider {
Inventory getInventory(
String productId,
String warehouseId
);
}
Implementation:
@Component
public class InventoryServiceProvider
implements InventoryProvider {
@Override
public Inventory getInventory(
String productId,
String warehouseId) {
return inventoryService.getInventory(
productId,
warehouseId
);
}
}
The AI framework becomes an adapter around the capability.
75. Ports & Adapters Architecture¶
flowchart TD
A["LLM / AI Orchestrator"] --> B["Tool Adapter"]
B --> C["InventoryProvider Port"]
C --> D["Inventory Service Adapter"]
D --> E["Enterprise Inventory Service"]
This keeps the application architecture independent from:
76. Tool Calling and Spring Boot¶
A Spring Boot application can expose application capabilities through a service layer.
@Service
public class OrderService {
public Order getOrder(String orderId) {
return orderRepository.findById(orderId);
}
}
The AI tool adapter can call:
This maintains the standard enterprise layering:
77. Tool Calling in a Java Enterprise Application¶
flowchart TD
A["LLM"] --> B["AI Tool Adapter"]
B --> C["Spring Service"]
C --> D["Domain Logic"]
D --> E["Repository"]
E --> F["Database"]
F --> E
E --> D
D --> C
C --> B
B --> A
The LLM does not bypass application services.
78. Tool Calling and Cloud Services¶
Tools can expose controlled cloud capabilities.
Examples:
AWS
├── S3 Search
├── DynamoDB Query
├── CloudWatch Metrics
└── Lambda Invocation
Azure
├── Blob Search
├── Cosmos DB Query
├── Monitor Metrics
└── Function Invocation
GCP
├── Cloud Storage Search
├── BigQuery Query
├── Cloud Monitoring
└── Cloud Functions
The AI application should normally access these through capability interfaces.
79. Cloud Adapter Architecture¶
flowchart TD
A["AI Tool"] --> B["StorageProvider"]
B --> C["AWS S3 Adapter"]
B --> D["Azure Blob Adapter"]
B --> E["GCP Storage Adapter"]
C --> F["AWS S3"]
D --> G["Azure Blob"]
E --> H["Google Cloud Storage"]
This follows a provider-adapter approach.
80. Tool Calling and Databases¶
A database can be exposed as a controlled capability.
Instead of:
prefer:
This gives the application control over:
81. Safe Database Tool¶
The model does not generate arbitrary SQL.
This is generally easier to secure than unrestricted SQL generation.
82. SQL Tool with Controlled Access¶
If an application genuinely requires SQL generation, introduce a validation layer:
flowchart LR
A["LLM"] --> B["Generated SQL"]
B --> C["SQL Validator"]
C --> D["Table Allowlist"]
D --> E["Read-only DB"]
E --> F["Result"]
F --> A
Additional controls may include:
Read-only credentials
Query timeout
Row limits
Table allowlist
Column allowlist
Query complexity limits
Audit logging
83. Function Calling and Search¶
Search can be exposed as:
The LLM can request:
The tool returns relevant documents.
This is a foundation for tool-driven RAG.
84. Function Calling and Calculators¶
Calculations are another good tool candidate.
def calculate(expression: str):
# Use a safe deterministic calculator,
# not unrestricted eval().
return calculator.evaluate(expression)
The model requests:
The application performs the deterministic operation.
85. Never Use Unrestricted eval()¶
Avoid:
for model-generated expressions.
An LLM can generate malicious or unintended code.
Use:
where calculations are required.
86. Function Calling and Monitoring¶
Monitoring can be exposed through:
The model can request:
The tool returns:
87. Function Calling for Incident Analysis¶
A production incident assistant might execute:
get_service_metrics()
↓
get_database_metrics()
↓
get_recent_deployments()
↓
get_error_logs()
↓
LLM Analysis
This creates a multi-tool investigation workflow.
88. Multi-Tool Workflow¶
flowchart TD
A["Incident Question"] --> B["LLM"]
B --> C["Service Metrics"]
B --> D["Database Metrics"]
B --> E["Deployment History"]
B --> F["Error Logs"]
C --> G["Observations"]
D --> G
E --> G
F --> G
G --> B
B --> H["Incident Analysis"]
89. Sequential Tool Calls¶
Some tool calls depend on previous results.
Example:
This must be sequential.
flowchart LR
A["get_customer"] --> B["Customer ID"]
B --> C["get_customer_orders"]
C --> D["Order ID"]
D --> E["get_order"]
90. Parallel Tool Calls¶
Other tools may be independent.
Example:
These may execute in parallel.
flowchart TD
A["LLM"] --> B["Inventory"]
A --> C["Price"]
A --> D["Shipping"]
B --> E["Combined Results"]
C --> E
D --> E
E --> F["LLM"]
Parallel execution can reduce latency when dependencies permit it.
91. Tool Dependency Graph¶
A sophisticated orchestrator can represent dependencies:
Independent branches can execute concurrently.
Dependent branches must wait for required outputs.
92. Tool Budget¶
Production systems should limit:
Example:
These are illustrative values and should be tuned according to the application's SLA.
93. Preventing Tool Loops¶
A model may repeatedly call:
The application should enforce:
Example:
MAX_TOOL_CALLS = 10
if tool_call_count >= MAX_TOOL_CALLS:
raise RuntimeError(
"Tool call budget exceeded"
)
94. Tool Calling and State¶
Multi-step tool workflows need state.
Example:
from dataclasses import dataclass, field
@dataclass
class ToolExecutionState:
request: str
tool_calls: int = 0
observations: list = field(
default_factory=list
)
The state can track:
95. Tool Calling State Machine¶
stateDiagram-v2
[*] --> LLM
LLM --> ToolRequest
ToolRequest --> Validation
Validation --> ToolExecution
ToolExecution --> ToolResult
ToolResult --> LLM
LLM --> FinalResponse
FinalResponse --> [*]
This is a useful conceptual model for agent orchestration.
96. Tool Calling and Long-Running Workflows¶
Some operations cannot complete within one request.
Examples:
Large Document Processing
Data Analysis
Batch Processing
Deployment
Approval Workflow
Incident Investigation
The architecture may use:
Long-running agent workflows are covered in later modules.
97. Asynchronous Tool Execution¶
flowchart TD
A["LLM"] --> B["Tool Request"]
B --> C["Workflow Engine"]
C --> D["Async Job"]
D --> E["Enterprise System"]
E --> F["Completion Event"]
F --> G["Workflow State"]
G --> H["AI Application"]
The model should not be expected to keep an HTTP connection open for long-running work.
98. Tool Calling and Events¶
A tool can trigger an event:
The event-driven architecture can then notify downstream services.
99. Tool Calling + Event-Driven Architecture¶
flowchart LR
A["LLM"] --> B["Tool"]
B --> C["Application Service"]
C --> D["Event Publisher"]
D --> E["Kafka / Event Bus"]
E --> F["Consumer A"]
E --> G["Consumer B"]
E --> H["Consumer C"]
The AI system remains one participant in the enterprise event architecture.
100. Tool Calling and Human-in-the-Loop¶
A tool can explicitly return:
The application can then transition to:
rather than automatically executing the operation.
101. Function Calling and Workflow Engines¶
Tool calls can be integrated with:
The AI model proposes:
while the workflow engine controls:
102. Tool Calling vs Workflow Orchestration¶
These are different concerns.
Tool Calling¶
Workflow Engine¶
Therefore:
is often preferable to allowing the LLM to control the entire workflow.
103. Function Calling and MCP¶
Modern AI systems increasingly use standardized tool protocols.
Model Context Protocol (MCP) provides a standardized way for AI applications to discover and interact with tools and contextual resources.
Conceptually:
MCP is related to tool interoperability, but it does not eliminate the need for:
MCP is covered in more detail in the later AI Agents and framework/tooling modules.
104. Tool Calling and MCP Architecture¶
flowchart LR
A["LLM / Agent"] --> B["MCP Client"]
B --> C["MCP Server"]
C --> D["Tool"]
C --> E["Resource"]
C --> F["Prompt"]
D --> G["Enterprise System"]
E --> H["Enterprise Data"]
The key idea here is standardized capability access.
105. Tool Calling and Agent Architecture¶
A basic AI agent often consists of:
Architecture:
flowchart TD
A["User"] --> B["Agent"]
B --> C["LLM"]
B --> D["Tool Registry"]
B --> E["State"]
B --> F["Policy"]
C --> G["Tool Call"]
G --> D
D --> H["Tool Executor"]
H --> I["External Systems"]
I --> J["Observation"]
J --> C
This connects the current chapter directly to the upcoming agent modules.
106. Tool Calling and RAG Agents¶
A RAG agent may have:
The model decides which retrieval capability to use.
For example:
This becomes an agentic retrieval pattern.
107. Tool Calling and Multimodal Systems¶
Tools are not limited to text.
A multimodal application can expose:
OCR Tool
Image Analysis Tool
Speech-to-Text Tool
Text-to-Speech Tool
Video Analysis Tool
Document Parser
Architecture:
This provides a foundation for multimodal enterprise AI.
108. Tool Calling and Document Processing¶
For example:
could return:
The AI system can then reason over the structured result.
109. Tool Calling and Code Execution¶
Code execution is a powerful but high-risk tool.
Potential use cases:
Architecture:
The execution environment must be isolated.
110. Code Execution Security¶
A production sandbox may enforce:
CPU Limit
Memory Limit
Timeout
Filesystem Restrictions
Network Restrictions
Package Restrictions
Process Restrictions
Never give an LLM unrestricted access to the host operating system.
111. Tool Calling and External Search¶
Search tools can provide:
A search tool should define:
Example:
112. Result Limits¶
Tool results should be bounded.
Instead of returning:
return:
This controls:
113. Pagination¶
Tools accessing large datasets should support pagination where appropriate.
Example:
The AI workflow can request additional pages only when necessary.
114. Tool Result Summarization¶
Large tool responses can be summarized before returning them to the model.
For example:
This reduces context size and improves signal-to-noise ratio.
115. Tool Response Transformation¶
Instead of:
{
"headers": {},
"debug": {},
"internal_metadata": {},
"server_info": {},
"customer": {
"id": "C1001",
"status": "active"
}
}
return:
Only expose the fields the LLM needs.
116. Tool Calling and Caching¶
Some tool results can be cached.
For example:
Caching can reduce:
But never cache data beyond its acceptable freshness period.
117. Tool Calling and Rate Limits¶
External services may impose:
The tool gateway should enforce or respect these limits.
The LLM should not be allowed to generate unlimited API traffic.
118. Rate Limiting Architecture¶
flowchart LR
A["LLM"] --> B["Tool Gateway"]
B --> C["Rate Limiter"]
C --> D["Tool"]
D --> E["External API"]
Rate limiting protects both the AI application and downstream systems.
119. Circuit Breaker¶
If an external service repeatedly fails:
This prevents the AI system from continuously hammering an unhealthy service.
120. Tool Gateway Resilience¶
A production tool gateway can implement:
This applies standard distributed-system resilience principles to AI tool execution.
121. Tool Calling and Bulkheads¶
Different tools can have separate resource pools.
For example:
Payment Tools
↓
Payment Thread Pool
Search Tools
↓
Search Thread Pool
Monitoring Tools
↓
Monitoring Thread Pool
A slow search service should not consume all resources needed by payment operations.
122. Function Calling Evaluation¶
Tool calling should be evaluated separately from final answer quality.
Important metrics:
Correct Tool Selection
Correct Arguments
Tool Execution Success
Correct Number of Calls
Unnecessary Tool Calls
Tool Call Latency
Final Answer Accuracy
123. Tool Selection Evaluation¶
Example dataset:
test_cases = [
{
"request": "What is order ORD-1001 status?",
"expected_tool": "get_order"
},
{
"request": "Is product P100 in stock?",
"expected_tool": "get_inventory"
},
{
"request": "Calculate 125 * 42.",
"expected_tool": "calculate"
}
]
The system can measure tool-selection accuracy.
124. Tool Argument Evaluation¶
Suppose the expected call is:
The evaluation should verify:
125. Unnecessary Tool Calls¶
An efficient model should not call a tool when the answer is already available.
Example:
If the application has a calculator tool, calling it may not always be necessary.
The correct behavior depends on the application's reliability requirements.
Tool usage should be evaluated based on:
126. Tool Calling Cost¶
Cost can come from:
A multi-step workflow may become expensive.
Optimization techniques include:
Tool Result Caching
Parallel Execution
Smaller Routing Models
Tool Call Limits
Result Filtering
Context Compression
127. Tool Calling Latency¶
A workflow such as:
can be slow.
Optimization may involve:
128. Production Function Calling Workflow¶
A robust production workflow is:
1. Receive user request.
2. Determine available capabilities.
3. Provide appropriate tool definitions to the LLM.
4. Receive tool request.
5. Validate tool name.
6. Validate arguments.
7. Check authorization.
8. Apply business policies.
9. Check rate limits and budgets.
10. Execute the tool.
11. Validate the result.
12. Sanitize sensitive data.
13. Return the observation to the LLM.
14. Determine whether additional tools are required.
15. Enforce iteration and tool-call limits.
16. Generate final response.
17. Validate the final response.
18. Record telemetry and audit information.
129. Complete Production Architecture¶
flowchart TD
A["User"] --> B["API Gateway"]
B --> C["AI Application"]
C --> D["Prompt / Context Builder"]
D --> E["LLM"]
E --> F{"Tool Call?"}
F -->|No| G["Final Response"]
F -->|Yes| H["Tool Gateway"]
H --> I["Tool Validation"]
I --> J["Authorization"]
J --> K["Policy"]
K --> L["Rate Limit"]
L --> M["Tool Execution"]
M --> N["Enterprise Service"]
N --> O["Tool Result"]
O --> P["Result Validation"]
P --> E
E --> G
G --> Q["Response Validation"]
Q --> B
B --> A
130. Enterprise Example — Order Assistant¶
User:
The LLM receives:
It generates:
Application:
Result:
The model responds:
131. Enterprise Example — Customer Support¶
User:
The LLM may determine:
Tool call:
Tool result:
{
"transactions": [
{
"id": "TX1001",
"amount": 2500,
"status": "completed"
},
{
"id": "TX1002",
"amount": 2500,
"status": "completed"
}
]
}
The LLM may then request:
The application controls whether that action is allowed.
132. Enterprise Example — Incident Assistant¶
User:
The model may call:
Then:
Then:
The observations are combined.
flowchart TD
A["Incident Question"] --> B["LLM"]
B --> C["Service Metrics"]
B --> D["Database Metrics"]
B --> E["Deployment History"]
C --> F["Observations"]
D --> F
E --> F
F --> B
B --> G["Incident Analysis"]
The final response should distinguish:
from:
133. Enterprise Example — Knowledge Assistant¶
User:
The model calls:
Tool result:
The model generates:
A structured response can additionally include:
134. Tool Calling and RAG Pipeline¶
flowchart TD
A["User Question"] --> B["LLM"]
B --> C["Search Tool"]
C --> D["Retriever"]
D --> E["Vector Database"]
E --> F["Documents"]
F --> C
C --> B
B --> G["Answer"]
The detailed RAG architecture will be covered in the subsequent RAG chapters.
135. Tool Calling and AI Agents¶
A simple agent loop can be expressed as:
User Request
↓
LLM
↓
Select Tool
↓
Execute Tool
↓
Observe Result
↓
LLM
↓
Select Next Tool
↓
...
↓
Final Answer
This is the basic execution loop behind many agentic systems.
136. Tool Calling vs Agents¶
Tool calling itself is not an agent.
An agent typically adds:
Therefore:
137. Tool Calling vs ReAct¶
| Concept | Main Purpose |
|---|---|
| Function Calling | Request a function invocation |
| Tool Calling | Request an external capability |
| ReAct | Reason + Act + Observe |
| Agent | Complete decision-making system |
| RAG | Retrieve external knowledge |
| Structured Output | Return structured data |
These concepts can be combined.
138. Combined Enterprise AI Pattern¶
A modern AI application may use:
Prompt Engineering
+
Structured Outputs
+
Tool Calling
+
ReAct
+
RAG
+
Business APIs
+
Validation
+
Observability
Architecture:
flowchart TD
A["User"] --> B["AI Application"]
B --> C["Prompt Builder"]
B --> D["Retriever"]
B --> E["Tool Registry"]
C --> F["LLM"]
D --> F
E --> F
F --> G{"Action Required?"}
G -->|Yes| H["Tool Gateway"]
H --> I["Enterprise Capability"]
I --> F
G -->|No| J["Structured Output"]
J --> K["Validation"]
K --> L["Business Logic"]
L --> M["Enterprise Systems"]
139. Tool Design Principles¶
Good tools should be:
Small
Focused
Explicit
Deterministic where possible
Well-described
Schema-driven
Observable
Secure
Idempotent when necessary
Versioned
Avoid creating one giant tool such as:
with dozens of unrelated parameters.
Prefer focused capabilities:
140. Tool Granularity¶
Too coarse:
Too fine:
A useful level is:
which returns the required domain information.
141. Tool Descriptions Should Be Explicit¶
Good:
Retrieve the current inventory quantity
for a product at a specific warehouse.
Use this tool when the user asks whether
a product is currently available.
Poor:
Clear descriptions improve model tool selection.
142. Tool Naming Convention¶
A consistent naming strategy helps.
Examples:
get_customer
get_order
search_documents
calculate_shipping
create_ticket
update_customer
delete_document
Avoid inconsistent naming:
Choose a convention and apply it consistently.
143. Tool Ownership and Governance¶
Enterprise tools should have:
A tool is effectively another production API.
Therefore it should receive API-level engineering discipline.
144. Tool SLA¶
For production tools, define:
Example:
Values should be determined by the actual service requirements.
145. Tool Contracts and API Design¶
A useful mental model:
Therefore apply familiar backend engineering principles:
This is especially important for backend engineers building AI systems.
146. Contract Testing for Tools¶
Example:
def test_get_order_contract():
result = get_order("ORD-1001")
assert "order_id" in result
assert "status" in result
More advanced tests should validate:
147. Tool Integration Testing¶
A realistic test:
User Request
↓
LLM
↓
Tool Selection
↓
Tool Executor
↓
Mock Enterprise Service
↓
Tool Result
↓
LLM
↓
Final Answer
This tests the complete integration.
148. Tool Evaluation Dataset¶
Create representative scenarios:
Simple Tool Call
Multiple Tool Calls
Missing Parameters
Invalid Parameters
Unauthorized Operation
Tool Failure
Timeout
Ambiguous Request
No Tool Required
High-Risk Operation
This helps identify model and orchestration failures.
149. Ambiguous Requests¶
User:
The model may not know:
The correct response may be:
Do not force a tool call with an invented order ID.
150. Missing Tool Arguments¶
Suppose the tool requires:
but the user says:
If the authenticated application context already contains the customer identity, the application may safely provide it.
Otherwise:
Do not invent values.
151. User Context vs Tool Arguments¶
A useful enterprise pattern is:
The model should not be responsible for determining sensitive identity information.
For example:
may be injected by the application.
152. Tool Argument Injection¶
Avoid allowing the model to override protected fields.
For example, the model should not be able to generate:
when the authenticated user is:
The application should enforce:
over model-generated identity values where appropriate.
153. Authorization Context¶
flowchart TD
A["Authenticated User"] --> B["Application Context"]
B --> C["LLM"]
C --> D["Tool Request"]
D --> E["Authorization Layer"]
B --> E
E --> F["Validated Tool Request"]
F --> G["Tool"]
The authorization layer combines:
154. Tool Calling and Tenant Isolation¶
In multi-tenant enterprise systems:
must not access:
through a model-generated tool call.
The application should derive tenant identity from the authenticated context.
Example:
Do not rely on the model to provide the correct tenant ID.
155. Tool Calling and Multi-Tenant Architecture¶
flowchart LR
A["User"] --> B["Authentication"]
B --> C["Tenant Context"]
C --> D["AI Application"]
D --> E["LLM"]
E --> F["Tool Request"]
F --> G["Tenant Authorization"]
C --> G
G --> H["Tenant-scoped Service"]
This is critical for enterprise SaaS systems.
156. Tool Calling and Secrets¶
Never expose:
to the model.
The tool implementation should access credentials through secure infrastructure.
Architecture:
The model sees only the tool interface.
157. Secret Isolation¶
flowchart LR
A["LLM"] --> B["Tool"]
B --> C["Secret Manager / IAM"]
C --> D["External Service"]
This is a fundamental enterprise security boundary.
158. Tool Calling and Audit¶
For sensitive operations, audit:
Example:
{
"user_id": "U1001",
"tool": "create_refund",
"resource": "ORDER-1001",
"approval": "approved",
"status": "success"
}
Sensitive information should be appropriately protected.
159. Tool Calling and Compliance¶
Depending on the enterprise domain, tools may need:
Auditability
Data Retention
Access Controls
Approval Workflows
Data Residency
PII Protection
Encryption
Traceability
AI tool execution should inherit the same governance requirements as traditional backend services.
160. Common Mistakes¶
160.1 Giving the LLM Direct Database Access¶
Prefer controlled application capabilities.
160.2 Trusting Model-Generated Arguments¶
Always validate.
160.3 Treating Tool Selection as Authorization¶
Tool selection is not permission.
160.4 Exposing Secrets¶
Never send credentials to the LLM.
160.5 No Tool Allowlist¶
Unknown tools should be rejected.
160.6 No Timeout¶
Every external operation needs a bounded execution time.
160.7 Unlimited Retries¶
Retries must be bounded.
160.8 No Idempotency¶
Write operations may execute twice after a timeout.
160.9 Returning Excessive Tool Data¶
Return only the information the model needs.
160.10 Poor Tool Descriptions¶
Ambiguous descriptions cause incorrect tool selection.
160.11 Too Many Tools¶
An enormous tool registry can make selection difficult.
160.12 Giant Tools¶
Avoid tools that combine unrelated business capabilities.
160.13 No Observability¶
Tool failures become difficult to diagnose.
160.14 Treating Tool Results as Trusted Instructions¶
Tool results are data and may contain malicious or untrusted content.
160.15 Letting the Model Control Business Authorization¶
Business authorization must remain deterministic.
161. Best Practices¶
1. Treat tools as production APIs.
2. Define explicit tool contracts.
3. Use clear tool names.
4. Write detailed tool descriptions.
5. Use structured argument schemas.
6. Validate every tool request.
7. Validate tool results.
8. Enforce authorization outside the LLM.
9. Apply least privilege.
10. Use tool allowlists.
11. Separate read and write capabilities.
12. Require approval for high-risk operations.
13. Use timeouts.
14. Use bounded retries.
15. Implement idempotency for write operations.
16. Limit tool-call counts.
17. Limit execution time.
18. Limit response sizes.
19. Minimize sensitive data exposure.
20. Never expose secrets to the model.
21. Use rate limiting.
22. Use circuit breakers where appropriate.
23. Log and trace tool execution.
24. Version important tools.
25. Maintain clear tool ownership.
26. Test tool selection.
27. Test tool arguments.
28. Test failure scenarios.
29. Protect against prompt injection.
30. Keep domain capabilities framework-independent.
31. Prefer capability interfaces in enterprise architectures.
32. Keep workflow orchestration separate from model decisions.
33. Use deterministic services for deterministic operations.
34. Treat MCP and frameworks as integration mechanisms, not security boundaries.
162. Production Workflow¶
A production-grade function-calling architecture should follow:
1. Define the business capability.
2. Define the tool contract.
3. Define input schema.
4. Define output schema.
5. Define permissions.
6. Define error behavior.
7. Register the tool.
8. Expose the appropriate tool definition to the LLM.
9. Receive the model's tool request.
10. Validate tool name.
11. Validate arguments.
12. Enrich safe contextual information from the application.
13. Check authentication.
14. Check authorization.
15. Apply business policies.
16. Apply rate limits and budgets.
17. Execute the tool.
18. Validate the tool result.
19. Sanitize sensitive information.
20. Return the result to the model.
21. Determine whether another tool is required.
22. Enforce iteration and tool-call limits.
23. Generate the final response.
24. Validate the final response.
25. Record metrics, traces, and audit information.
26. Evaluate the workflow continuously.
163. Production Checklist¶
Before deploying function or tool calling:
[ ] Is the tool actually required?
[ ] Is the tool purpose clearly defined?
[ ] Is the tool name explicit?
[ ] Is the tool description clear?
[ ] Is the input schema defined?
[ ] Is the output schema defined?
[ ] Are required arguments enforced?
[ ] Are argument types validated?
[ ] Are unknown tools rejected?
[ ] Is authorization enforced independently?
[ ] Is least privilege applied?
[ ] Are read and write tools separated?
[ ] Are high-risk operations protected?
[ ] Is human approval implemented where required?
[ ] Are secrets isolated from the LLM?
[ ] Is tenant isolation enforced?
[ ] Is PII minimized?
[ ] Are tool results validated?
[ ] Are tool errors controlled?
[ ] Are timeouts configured?
[ ] Are retries bounded?
[ ] Is idempotency implemented where required?
[ ] Are rate limits configured?
[ ] Are circuit breakers considered?
[ ] Is the number of tool calls limited?
[ ] Is execution time limited?
[ ] Are tool results size-limited?
[ ] Are tool calls observable?
[ ] Are tool calls auditable?
[ ] Are prompt-injection risks considered?
[ ] Are tool definitions versioned?
[ ] Are tool owners defined?
[ ] Is tool selection evaluated?
[ ] Are tool arguments evaluated?
[ ] Are failure scenarios tested?
[ ] Are framework dependencies isolated from business logic?
164. Key Takeaways¶
- Function Calling allows an LLM to request execution of predefined functions.
- Tool Calling is the broader concept of allowing an LLM to interact with external capabilities.
- Tools can represent:
- Functions
- APIs
- Databases
- Search
- Retrievers
- Calculators
- Enterprise services
- Cloud services
- Workflow operations
- A tool should have:
- Name
- Description
- Input schema
- Output contract
- The LLM should request an action, not directly execute it.
- The application should remain responsible for:
- Validation
- Authorization
- Policy
- Execution
- Auditing
- Tool selection is not authorization.
- Tool arguments must be validated.
- Tool results should also be validated.
- Read and write tools should be treated differently.
- High-risk tools may require human approval.
- Write operations should consider idempotency.
- External operations need timeouts and bounded retries.
- Tool calls should have execution and cost limits.
- Tool results should be minimized.
- Secrets should never be exposed to the model.
- Tenant identity should come from trusted application context.
- Tool results should be treated as untrusted data.
- Tool calling can participate in a ReAct loop:
- Tool calling can also power RAG:
- Tool calling is a fundamental building block of AI agents.
- Tool calling itself is not a complete agent architecture.
- Production tool systems should follow normal enterprise API engineering practices.
- Frameworks such as LangChain and LlamaIndex provide abstractions, but business capabilities should remain framework-independent.
- Capability-based interfaces and Ports & Adapters help prevent framework lock-in.
- MCP can standardize tool and resource interaction, but does not replace application security or governance.
The central production principle is:
Let the LLM decide which capability may be useful, but let the application decide whether that capability is authorized, valid, safe, and executable.
165. Chapter Navigation¶
Part IV — Prompt Engineering & RAG Fundamentals¶
Previous Chapter: 08. Structured Outputs & Output Parsing
Current Chapter: 09 — Function Calling & Tool Calling
Next Chapter: 10. Embeddings in Practice
Part IV Chapters¶
- 01. Introduction to Prompt Engineering
- 02. Prompt Engineering Fundamentals
- 03. Advanced Prompt Engineering
- 04. Prompt Design Patterns
- 05. Zero-shot, One-shot & Few-shot Prompting
- 06. Chain-of-Thought Prompting
- 07. ReAct Prompting
- 08. Structured Outputs & Output Parsing
- 09. Function Calling & Tool Calling
- 10. Embeddings in Practice
- 11. Document Processing & Vectorization
- 12. Document Chunking Strategies
- 13. Vector Database Fundamentals
- 14. Similarity Search Techniques
- 15. RAG Pipeline Components
- 16. Retrieval & Generation Pipeline
- 17. Vector Databases in RAG
- 18. Building Your First RAG Pipeline
- 19. RAG Evaluation Fundamentals
- 20. Enterprise Generative AI Application Architecture
- 21. Deploying AI Applications with Gradio
References¶
- OpenAI — Function Calling and Tool Calling Documentation
- Anthropic — Tool Use Documentation
- Google — Gemini Function Calling Documentation
- Hugging Face — Transformers Documentation
- LangChain — Tools and Agents Documentation
- LlamaIndex — Tools and Agents Documentation
- Model Context Protocol — MCP Documentation
- JSON Schema — JSON Schema Specification
- Pydantic — Data Validation Documentation
- OWASP — Secure AI Application Development Guidance
Enterprise AI Engineering Handbook
Building Production-Grade Enterprise AI Systems — One Chapter at a Time.