Function Calling and Tool Use via the API: Let an LLM Execute Actions

Last updated: July 2026 Read time: 7 minutes Category: API Architecture

Traditional language models only generate text as a response. With function calling (also called tool use), we break this boundary. A Large Language Model no longer returns free text, but a structured JSON object that allows your software application to call external functions, databases, or APIs.

Via LLMNet's central aggregation API, you include tool definitions in your request payload. The model analyzes the user's query, determines whether external data or action is required, and formulates a targeted function call.

How Function Calling Works (Conceptually)

The interaction between your application, the LLMNet API, and the language model takes place in four logical steps:

  1. Definition: You send the user prompt along with an array of available tools (including JSON schemas for the parameters).
  2. Analysis: The LLM assesses whether the tool is needed. If so, it interrupts text generation and returns a signal with the chosen function name and arguments.
  3. Execution: Your application receives the JSON and executes the actual action (e.g., a database query or external API call).
  4. Synthesis: You send the tool's result back to the model, which then formulates a final, human-readable response for the end user.

JSON Schema for Tool Definitions

To instruct the model on which arguments are required or optional, you define tools using strict JSON schemas. Below is a representative definition for a tool that retrieves the current weather:

{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "Retrieves the current weather forecast for a specified location.",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state/province, e.g., 'Amsterdam, North Holland'"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
}
}
}

Pseudocode Example: The Request-Response Loop

In practice, you implement function calling with a robust execution loop in your backend. This simplified pseudocode example shows how to call the API and respond to tool calls:

import requests

api_url = "https://api.llmnet.nl/v1/chat/completions"
headers = {"Authorization": "Bearer DUMMY_API_KEY"}

payload = {
"model": "deepseek-chat",
"messages": [{"role": "user", "content": "What is the weather in Utrecht?"}],
"tools": [weather_tool_definition]
}

response = requests.post(api_url, json=payload, headers=headers).json()
message = response["choices"][0]["message"]

if "tool_calls" in message:
tool_call = message["tool_calls"][0]
func_name = tool_call["function"]["name"]
arguments = parse_json(tool_call["function"]["arguments"])

# Execute the local function
result = execute_local_function(func_name, arguments)

# Send the result back to the LLM for the final conclusion
print(f"Tool result: {result}")

Important Security and Architectural Considerations

  • Never trust blindly: An LLM generates text and arguments based on probability. Validate all received parameters in your backend with strict schema validators before executing SQL queries or destructive API calls.
  • Prompt Injection via Tools: External data (such as web pages or emails retrieved via a tool) can contain malicious instructions. Ensure a clear separation between system instructions and dynamic tool output.
  • Timeouts and Rate Limiting: Implement strict timeouts on external tool calls to prevent your application from blocking due to slow external services.

More background information on setting up robust architectures and designing learning paths around AI integration can be found in our comprehensive guide at llmnet.nl/leren/.