Tool use

2 min read
On trails:AGENTSstep 6/9

A model on its own only produces text. Tool use, also called function calling, gives it hands: the model describes the call it wants as JSON, and ordinary code carries it out.

Three parts

  1. A list of tools as JSON schemas: the name, description and parameters of each.
  2. The LLM, which reads those schemas, reasons, decides whether a tool is needed, and outputs the call as JSON.
  3. An orchestrator, the executor, which parses the JSON, maps it to the real function, runs it and returns the data.
The tool schemas go to the LLM, which outputs a JSON tool call. The orchestrator parses it, executes the real function, and returns the result to the LLM. Tool schemas name, desc, params in prompt LLM reasons, decides JSON call Orchestrator parse, map, execute execute Real function returns data tool result REASON, PARSE, MAP, EXECUTE, RETURN
The model only asks. The orchestrator runs the function and returns the result.

The schema

This is what the model is given. The description is the only thing it has to decide with, so it is part of the interface. Anthropic’s advice is to write it as you would for a new hire, and that small edits to a description can change tool use a lot.

JSON
{
  "type": "function",
  "function": {
    "name": "get_order_status",
    "description": "Look up the shipping status of an order.",
    "parameters": {
      "type": "object",
      "properties": { "order_id": { "type": "string" } },
      "required": ["order_id"]
    }
  }
}

In LangChain

The @tool decorator builds that schema from the function’s name, docstring and type hints. reply is what the model emits: structured data with a name, arguments and an id, nothing more. The orchestrator then runs it and gets a result tagged with the same id.

Python
from langchain.messages import AIMessagefrom langchain.tools import toolfrom langchain_core.utils.function_calling import convert_to_openai_tool @tooldef get_order_status(order_id: str) -> str:    """Look up the shipping status of an order."""    return "shipped" schema = convert_to_openai_tool(get_order_status) reply = AIMessage(content="", tool_calls=[    {"name": "get_order_status", "args": {"order_id": "A-1042"}, "id": "call_1"},]) call = reply.tool_calls[0]result = get_order_status.invoke(call)

The orchestrator is where real code runs, so the arguments the model produced are untrusted input. Validate them and limit what each tool can touch (see secure toolingSecure toolingTools are where an agent touches the world, so each one is described, versioned and watched.Opens in a new tab). Repeating this until the model stops asking is the loop in ReActReActReason, act, observe, repeat: planning, tool use and a loop in one pattern.Opens in a new tab. Tools can also be served over a standard protocol (see MCPMCPModel Context Protocol: one standard way for an agent to reach tools and data.Opens in a new tab).


Sources