Skip to main content
Back to Blog
AI & ML

Function Calling and Tool Use: How to Make AI Actually Do Things

2026-03-2211 min read
Daniyal Alam

Daniyal Alam

CEO & Founder

Function Calling and Tool Use: How to Make AI Actually Do Things

An LLM without tools is a text generator. With tools, it becomes an agent that can search the web, query your database, send emails, call external APIs, write and execute code, and take actions in the real world. Function calling — the mechanism that enables tool use — is the most important concept to understand when building AI applications beyond basic Q&A chatbots. This is the guide we use to onboard engineers at DanixSoft.

How function calling works

When you define tools for an LLM, you are not giving it the ability to call functions directly. You are giving it a schema — a JSON description of what tools are available, what parameters they take, and what they do. The model decides whether to use a tool and returns a structured JSON object with the tool name and arguments. Your code then executes the actual function and passes the result back to the model. The model never directly executes code — it only recommends what to execute.

// 1. Define the tool schema
const tools = [{
  type: "function",
  function: {
    name: "search_database",
    description: "Search for products by name or category",
    parameters: {
      type: "object",
      properties: {
        query: { type: "string", description: "Search query" },
        category: { type: "string", enum: ["electronics", "clothing", "food"] },
        max_results: { type: "integer", default: 10 }
      },
      required: ["query"]
    }
  }
}];

// 2. Model decides to call the tool
const response = await openai.chat.completions.create({
  model: "gpt-4o",
  messages: [{ role: "user", content: "Find me wireless headphones under $100" }],
  tools
});

// 3. Execute the tool call in your code
const toolCall = response.choices[0].message.tool_calls[0];
const args = JSON.parse(toolCall.function.arguments);
const results = await searchDatabase(args.query, args.category);

// 4. Pass results back to the model
const finalResponse = await openai.chat.completions.create({
  model: "gpt-4o",
  messages: [
    { role: "user", content: "Find me wireless headphones under $100" },
    response.choices[0].message,
    { role: "tool", tool_call_id: toolCall.id, content: JSON.stringify(results) }
  ]
});

Tool design principles

How you design your tool schemas has a huge impact on how reliably the model uses them. Follow these principles:

  • One tool, one clear purpose — a tool that does two things confuses the model. Split it.
  • Descriptions are prompts — the tool description is part of the model's context. Be precise: "Search for products in the inventory database" is better than "Search products".
  • Use enums to constrain choices — whenever a parameter has a fixed set of valid values, use an enum. This eliminates an entire class of invalid tool calls.
  • Return normalised data — tool return values feed back into the model's context. Return clean, structured data (JSON), not raw API responses full of noise.

Parallel tool calling

GPT-4o and Claude 3.5+ support parallel tool calling — the model can request multiple tools in a single turn. This is essential for performance in multi-tool agents. Instead of: search → wait → analyse → wait → summarise (three sequential round trips), the model can request search AND analyse in one call when the operations are independent. Always implement parallel tool execution on your side:

const toolCalls = response.choices[0].message.tool_calls;

// Execute all tool calls in parallel
const toolResults = await Promise.all(
  toolCalls.map(call =>
    executeToolCall(call.function.name, JSON.parse(call.function.arguments))
      .then(result => ({
        role: "tool",
        tool_call_id: call.id,
        content: JSON.stringify(result)
      }))
  )
);

Tool use with Anthropic Claude

Claude's tool use API follows the same pattern as OpenAI but with slightly different field names (input_schema instead of parameters, tool_use blocks instead of tool_calls). Claude tends to be more conservative about when it calls tools — it will ask for clarification rather than guess, which makes it better for high-stakes agentic applications where an incorrect tool call has real consequences.

Security: what tools should an agent never have?

Tools that can cause irreversible harm require human confirmation before execution. DanixSoft's agent safety policy: any tool that sends external communications (email, Slack, SMS), modifies or deletes production data, makes financial transactions, or deploys code must require explicit human approval. Implement a human-in-the-loop checkpoint for these tools — the agent proposes the action, a human approves it, then the agent executes. Never give an agent autonomous access to destructive capabilities, regardless of how good the underlying model is. AI reliability is improving but is not yet at the level where unattended destructive actions are safe at scale. Get in touch to build a safe, production-ready AI agent for your business.

#Function Calling#AI Agents#Tool Use#OpenAI#Anthropic Claude

Share this article

Related Articles

Daniyal Alam

Written by Daniyal Alam

CEO & Founder at DanixSoft

Passionate about building scalable software solutions and sharing knowledge with the developer community.

Get in Touch

Ready to start your project?

Let's turn your vision into reality. Contact us today for a free consultation.

Contact Us