TellWorldAI World Archive
Ask中文

Home›Practice›Practice

Practice

The tool use design pattern for agents

Tool use lets an agent call functions and outside services such as databases, APIs and code execution. This guide walks through the function calling loop in Python and the access limits to set before going live.

Who this is for and what you will be able to do

This guide is for developers who already call a large language model and now want it to query a database, call an API or run code. By the end you should be able to explain the Tool Use Design Pattern, list the building blocks it needs, follow the full function calling flow with code, and know which security limits to put on database access [1].

What the tool use pattern is

The Tool Use Design Pattern gives an LLM a way to interact with external tools in order to reach a specific goal. A tool is code that an agent can execute to perform an action. It can be a simple function such as a calculator, or an API call to a third-party service, such as a stock price lookup or a weather forecast [1]. In an agent, tools run in response to function calls that the model generates [1].

Where tools are useful

Tools let an agent complete complex tasks, retrieve information and make decisions. The pattern is common when an agent has to interact with external systems dynamically, such as databases, web services or code interpreters [1]. Typical uses include:

  • Dynamic information retrieval: querying an API or database for up-to-date data, such as a SQLite database for data analysis, or stock prices and weather information [1].
  • Code execution: running code or scripts to solve maths problems, generate reports or run simulations [1].
  • Workflow automation: connecting task schedulers, email services or data pipelines to handle repetitive or multi-step work [1].
  • Customer support: working with CRM systems, ticketing platforms and knowledge bases to resolve user questions [1].
  • Content generation and editing: using grammar checkers, text summarizers or content safety evaluators to help with writing [1].

The building blocks you need

Implementing the pattern requires six kinds of component [1].

  • Function and tool schemas define each tool's name, purpose, required parameters and expected outputs. They tell the LLM what tools exist and how to build a valid request [1].
  • Function execution logic decides how and when a tool is invoked, based on the user's intent and the conversation context. It can include planner modules, routing or conditional flows [1].
  • The message handling system manages the flow between user input, model replies, tool calls and tool outputs [1].
  • The tool integration framework connects the agent to tools, whether they are simple functions or complex external services [1].
  • Error handling and validation deal with failed tool runs, check parameters and handle unexpected responses [1].
  • State management tracks the conversation context and earlier tool interactions, so multi-turn conversations stay consistent [1].

Walk through one function call

Function calling is the main way an LLM uses tools. The two words "function" and "tool" are often used interchangeably, because functions are the reusable blocks of code that agents use to carry out tasks [1]. For the model to call a function, it compares the user's request with the function descriptions and returns the name and arguments of the function it judges most suitable. The application then runs that function and sends the result back to the model, which writes the final answer [1].

To build this, you need three things: an LLM that supports function calling, a schema that describes the functions, and the code for each function [1]. Not every model supports function calling. Azure OpenAI does, and the example uses the Responses API on the stable /openai/v1/ endpoint, which does not need an api_version [1].

The example for asking the time in San Francisco has three steps.

  1. Initialize the client. The code is [1]:
# Initialize the OpenAI client for Azure OpenAI (Responses API, v1 endpoint)
client = OpenAI(
    base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/",
    api_key=os.environ["AZURE_OPENAI_API_KEY"],
)
deployment_name = os.environ["AZURE_OPENAI_DEPLOYMENT"]
  1. Define the function schema. It holds the function name, a description of what it does, and the names and descriptions of its parameters [1]:
# Function description for the model to read (Responses API flat tool format)
tools = [
    {
        "type": "function",
        "name": "get_current_time",
        "description": "Get the current time in a given location",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "The city name, e.g. San Francisco",
                },
            },
            "required": ["location"],
        },
    }
]
  1. Read the response. The model's first reply is a tool call, not the answer. It names the function and gives the arguments. Your code runs that function, sends the output back as a function call output, and makes a second request to get the final answer [1].

In short, the model chooses and describes the call, and your code does the work and returns the result [1].

Using the Microsoft Agent Framework

The Microsoft Agent Framework lets you turn a Python function into a tool with the @tool decorator. The framework handles the back-and-forth between the model and your code, and it generates the schema from the function and its parameters [1]. It also gives access to pre-built tools such as File Search and Code Interpreter through FoundryChatClient [1]. The sample below turns the time function into a tool [1]:

import os
from agent_framework import tool
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential

@tool(approval_mode="never_require")
def get_current_time(location: str) -> str:
    """Get the current time for a given location"""
    ...

# Create the client
provider = FoundryChatClient(
    project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
    model=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
    credential=AzureCliCredential(),
)

# Create an agent and run with the tool
agent = provider.as_agent(name="TimeAgent", instructions="Use available tools to answer questions.", tools=get_current_time)
response = await agent.run("What time is it?")

The ... in the function body stands for the logic you write yourself. The sample leaves it out.

What Foundry Agent Service adds

Microsoft Foundry Agent Service is a fully managed service. You build, deploy and scale agents without managing the underlying compute and storage, and it offers enterprise-grade security [1]. Compared with calling the model API directly, it has three practical advantages [1]:

  • Automatic tool calling: parsing a tool call, invoking the tool and handling the response all happen on the server side.
  • Managed conversation data: threads store the information a conversation needs, so you do not manage conversation state yourself.
  • Ready-made tools: such as Bing, Azure AI Search and Azure Functions for working with data sources [1].

The service's tools fall into two groups [1]. Knowledge tools include Grounding with Bing Search, File Search and Azure AI Search. Action tools include Function Calling, Code Interpreter, OpenAPI defined tools and Azure Functions [1]. The service can combine these tools into a toolset, and threads keep the message history for each conversation [1].

In the Contoso sales example, the LLM chooses between a function the developer wrote, fetch_sales_data_using_sqlite_query, and the built-in Code Interpreter, depending on what the user asks [1].

Security limits for model-written SQL

The main concern with SQL generated by an LLM is security. The risks include SQL injection, and actions such as dropping or changing data in the database [1]. You can reduce these risks a lot by setting database access permissions correctly, which for most databases means making the database read-only [1]. For a service such as PostgreSQL or Azure SQL, give the app a read-only (SELECT) role [1].

Running the app in a secure environment adds another layer of protection [1]. In enterprise settings, data is usually moved from operational systems into a read-only database or data warehouse with a clear structure. The app then has restricted, read-only access [1].

Next step

The sample code is in the repository's code_samples folder, as a Python notebook for the Agent Framework and a .NET file [1]. Run the Python notebook first if you use Python.

Adapted from lesson 4 of Microsoft's open-source course *AI Agents for Beginners*[1], released under the MIT License.

Sources

  1. 1
    Tool Use Design PatternMicrosoft ai-agents-for-beginners (MIT)

Cite this page: The tool use design pattern for agents. TellWorld, https://www.tellworld.net/practice/practice-agent-tool-use. Updated 2026-11-14

Related news

View all