Updated on June 3, 2026

Summarize this blog post with: ChatGPT | Perplexity | Claude | Grok

TL;DR: OpenAI function calling lets a model decide which of your backend functions to run and what arguments to pass, but your code does the actual execution. The model returns structured JSON, you run the function, and the result goes back so it can write a natural reply. That five-step loop is what turns an AI agent that talks into an AI agent that acts. For production, three features matter most: strict: true guarantees the arguments match your schema, parallel_tool_calls handles bundled questions in one turn, and tool_choice controls when the model is allowed to act.

You have probably already set up an OpenAI-powered AI agent that answers customer questions from your knowledge base. But the moment a customer asks “Where is my order?” or “Can you freeze my card?”, the agent stalls. It can talk about your return policy, but it cannot actually check the order status. That gap between knowing and doing is exactly what function calling closes. In this guide, you will learn precisely how OpenAI function calling works, see working Python and JavaScript code for every step of the process, and understand how to apply it to real customer support scenarios, from e-commerce order tracking to fintech card management.

Key Takeaways

  • OpenAI function calling (also called tool calling) lets the model decide which backend function to run and what arguments to pass. Your code does the actual execution, not the model.
  • The 5-step loop (define schema, send request, model returns tool call, execute function, send result back) is the foundation of every AI agent that takes real action on behalf of customers.
  • strict: true guarantees the model’s arguments match your JSON schema exactly, eliminating the most common production failure mode. OpenAI’s own evaluation shows gpt-4o with Structured Outputs scores 100% on complex schema adherence vs. less than 40% for older models without it.
  • Parallel tool calls let the model handle bundled customer questions in a single turn, reducing multiple sequential round trips to the time of the slowest single call.
  • tool_choice gives you precise control, from letting the model decide (auto) to forcing a specific function, which is essential for support workflows with compliance or safety requirements.
  • Python developers can use Pydantic to auto-generate schemas; JavaScript and TypeScript developers can use Zod. Both approaches prevent your types and tool definitions from drifting apart over time.

Platforms like Kommunicate implement the same function-calling principles through intent detection, workflow automation, and built-in human handoff, so support teams get identical outcomes without writing orchestration code from scratch.

What Is OpenAI Function Calling?

OpenAI function calling is the capability that lets an AI model decide which of your backend functions to run and what arguments to pass, while your application code does the actual execution. The model itself never touches your database, your APIs, or your business logic. It reads a structured description of your functions, interprets the user’s natural language request, and returns a precise JSON object specifying exactly which function it wants called and with what parameters.

For example, when a customer asks “Where is my order?”, the model does not guess an answer. Instead, it returns a structured call like:

{
  "name": "get_order_status",
  "arguments": "{\"order_id\": \"ORD-12345\"}"
}

Your backend then runs the real lookup, retrieves live data, and sends the result back so the model can compose a natural, accurate reply: “Your order ORD-12345 is out for delivery and should arrive tomorrow.”This is the shift that transforms an AI agent that only talks into one that actually acts. Traditional FAQ AI agents can only surface static knowledge. Function calling connects the AI directly to live systems, such as your order management platform, your CRM, or your payment processor, and lets it take real actions on behalf of your customers.

Why FAQ-Only AI Agents Fail for Operational Queries

A knowledge base AI agent can answer questions about your return policy, but it cannot execute a return. That distinction matters enormously in customer support. The most common high-volume support queries, including order status, card management, appointment booking, and account updates, all require live data retrieval or system actions, not just text retrieval. Function calling is what bridges that gap. Without it, your generative AI agent for customer support remains a sophisticated search engine rather than an action-capable agent.

Function Calling vs Tool Calling: What Is the Difference?

Function calling and tool calling refer to the exact same OpenAI capability. The two terms are fully interchangeable in 2026. OpenAI originally launched the feature in June 2023 under the name “function calling,” using a functions parameter and a function_call control parameter. In late 2023, OpenAI renamed the API to use tools and tool_choice instead, to accommodate a broader range of tool types beyond just custom functions, including web search, file search, computer use, and MCP server connections.The legacy functions and function_call parameters were deprecated with the release of the 2023-12-01-preview API version. Modern code should always use tools and tool_choice. Every code example in this guide uses the current syntax.

How Function Calling Compares Across AI Providers

OpenAI, Anthropic, and Google all offer equivalent function-calling capabilities, though they use different terminology. The mechanics across all providers are essentially the same: define a JSON schema, receive structured arguments, execute the function, and return the result.

ProviderTerm UsedControl Parameter
OpenAIFunction calling / Tool callingtool_choice
Anthropic (Claude)Tool usetool_choice
Google (Gemini)Function callingtool_config
Microsoft (Azure OpenAI)Tool callingtool_choice

If you are migrating between providers or building a multi-provider system, cross-provider abstraction libraries like LangChain or LiteLLM normalize these differences for you.

How Does OpenAI Function Calling Work? (5-Step Flow)

OpenAI function calling works through a five-step conversation loop between your application and the model. Your backend executes the logic, while the model handles intent recognition and natural language generation. Understanding this loop is the foundation for building any AI support agent. The example throughout this section uses a customer asking: “Where is my order ORD-12345?”

Step 1: Define Your Function Schema

Python (using Pydantic, recommended):

The first step is describing your available functions to the model using a JSON Schema definition inside the tools parameter. The schema has three critical parts: a name, a description that the model uses to decide when to call the function, and a parameters block. The description is doing real cognitive work. The more specific it is, the more accurately the model selects the right function.

Python (using Pydantic, recommended):

# Step 1: Define function schema using Pydantic
from pydantic import BaseModel
from openai import OpenAI

client = OpenAI()

class GetOrderStatus(BaseModel):
    """Returns shipping status for a customer order.
    Use when a customer asks about delivery, tracking, or order location.
    Do NOT use for refund or return inquiries.
    """
    order_id: str  # Customer order ID, e.g. "ORD-12345"

tools = [client.pydantic_function_tool(GetOrderStatus)]

JavaScript (using Zod, recommended):

// Step 1: Define function schema using Zod
import OpenAI from "openai";
import { z } from "zod";
import { zodFunction } from "openai/helpers/zod";

const client = new OpenAI();

const GetOrderStatusParams = z.object({
  order_id: z.string().describe("Customer order ID, e.g. 'ORD-12345'")
});

const tools = [zodFunction({
  name: "get_order_status",
  description: "Returns shipping status. Use for delivery or tracking queries. NOT for refunds.",
  parameters: GetOrderStatusParams
})];

Using Pydantic or Zod is strongly recommended over writing raw JSON schemas by hand. When your type definition changes, the schema automatically updates with it, preventing drift. Also note that the description field is part of your prompt and counts against your token budget on every single request, so keep descriptions specific but concise.

Step 2: Send the Request with the User’s Message

The second step sends the user’s message and your tool definitions to the OpenAI API in a single call. Nothing executes yet. You are simply giving the model context about what the user said and what tools are available to it.

Python:

# Step 2: Send request with user message and tools
messages = [{"role": "user", "content": "Where is my order ORD-12345?"}]

response = client.chat.completions.create(
    model="gpt-4.1",        # or gpt-4o, gpt-5, gpt-5.4-mini
    messages=messages,
    tools=tools
)

JavaScript:

// Step 2: Send request with user message and tools
const messages = [{ role: "user", content: "Where is my order ORD-12345?" }];

const response = await client.chat.completions.create({
  model: "gpt-4.1",         // or gpt-4o, gpt-5, gpt-5.4-mini
  messages,
  tools
});

Step 3: The Model Returns a Tool Call (Not an Answer)

This is the step that surprises most developers the first time: the model does not reply with text. Instead, it returns a structured tool_calls array. Each entry in the array has a unique id, the name of the function it wants called, and the arguments as a JSON string.

{
  "tool_calls": [{
    "id": "call_abc123",
    "type": "function",
    "function": {
      "name": "get_order_status",
      "arguments": "{\"order_id\": \"ORD-12345\"}"
    }
  }]
}

Two things are critical here. First, arguments is a JSON string, not an object. Always JSON.parse() it before use. Second, store the id, because you will need it in Step 5 to pair your result back to the right call.

Step 4: Execute the Function in Your Code

Step 4 is where your backend runs. The model has no access to this code path. You parse the arguments, look up the matching function, and execute it. This is also where business validation belongs: check that the order ID exists, that the requesting customer owns it, and that the values are within expected bounds. strict: true validates shape, not values. That business logic is still entirely your responsibility.

Python:

# Step 4: Execute backend function with dispatched arguments
import json

def get_order_status(order_id: str) -> dict:
    # Real database or API call goes here
    return {
        "order_id": order_id,
        "status": "Out for delivery",
        "eta": "Tomorrow"
    }

function_map = {"get_order_status": get_order_status}
tool_calls = response.choices[0].message.tool_calls or []
results = []

for call in tool_calls:
    fn = function_map.get(call.function.name)
    try:
        args = json.loads(call.function.arguments)
        result = fn(**args) if fn else {"error": "UNKNOWN_FUNCTION"}
    except Exception as e:
        result = {"error": "EXECUTION_FAILED", "detail": str(e)}
    results.append({"call_id": call.id, "result": result})

JavaScript:

// Step 4: Execute backend function with dispatched arguments
const functionMap = {
  get_order_status: async ({ order_id }) => ({
    order_id,
    status: "Out for delivery",
    eta: "Tomorrow"
  })
};

const toolCalls = response.choices[0].message.tool_calls || [];
const results = await Promise.all(toolCalls.map(async (call) => {
  const fn = functionMap[call.function.name];
  try {
    const args = JSON.parse(call.function.arguments);
    const result = fn ? await fn(args) : { error: "UNKNOWN_FUNCTION" };
    return { call_id: call.id, result };
  } catch (e) {
    return { call_id: call.id, result: { error: "EXECUTION_FAILED" } };
  }
}));

Notice the error handling pattern: return errors as structured tool results, not as exceptions. If you throw an exception and bail out, the customer sees a generic error page. If you return {"error": "ORDER_NOT_FOUND"} as the tool result, the model reads it and responds naturally: “I could not find an order with that ID. Could you double-check it?” That is a significantly better customer experience.

Step 5: Send the Result Back and Get the Final Response

The final step sends your function results back to the model so it can compose a natural-language reply. Each result must be paired with the correct call_id so the model knows which result corresponds to which call.

Chat Completions API (stateless, you manage the messages array):

# Step 5a: Chat Completions API approach (stateless)
messages.append(response.choices[0].message)  # append assistant's tool call

for item in results:
    messages.append({
        "role": "tool",
        "tool_call_id": item["call_id"],
        "content": json.dumps(item["result"])
    })

final = client.chat.completions.create(
    model="gpt-4.1",
    messages=messages,
    tools=tools    # pass tools again with Chat Completions
)
print(final.choices[0].message.content)
# "Your order ORD-12345 is out for delivery and should arrive tomorrow."

Responses API (stateful, server manages conversation state):

# Step 5b: Responses API approach (stateful, recommended for new projects)
# Build the tool output items
tool_outputs = [
    {
        "type": "function_call_output",
        "call_id": item["call_id"],
        "output": json.dumps(item["result"])
    }
    for item in results
]

final = client.responses.create(
    model="gpt-4.1",
    previous_response_id=response.id,  # OpenAI carries tools and context forward
    input=tool_outputs                  # no need to re-pass tools or messages
)
print(final.output_text)
# "Your order ORD-12345 is out for delivery and should arrive tomorrow."

JavaScript (Responses API):

// Step 5b: Responses API - JavaScript
const toolOutputs = results.map(({ call_id, result }) => ({
  type: "function_call_output",
  call_id,
  output: JSON.stringify(result)
}));

const final = await client.responses.create({
  model: "gpt-4.1",
  previous_response_id: response.id,
  input: toolOutputs
});
console.log(final.output_text);
// "Your order ORD-12345 is out for delivery and should arrive tomorrow."

The key difference between the two APIs: With the Chat Completions API, conversation state is stateless. You manage the full messages array yourself and must re-pass tools on every request. With the Responses API, conversation state is managed server-side. You pass previous_response_id and OpenAI carries the context and tools forward automatically. For new projects, OpenAI recommends the Responses API. Note that the Assistants API was deprecated in 2025 and will shut down on August 26, 2026. If you are still using it, migrate to the Responses API.The complete five-step lifecycle is: User question, model selects function, backend executes logic, result sent back, AI generates final response. That loop is the architectural foundation of every AI agent that takes real action in customer support.

What Is strict: true in OpenAI Function Calling and Why Does It Matter?

strict: true is the Structured Outputs flag that upgrades the model’s schema adherence from a best-effort attempt to a hard guarantee. Without it, the model usually returns arguments that match your schema. But in a system handling thousands of conversations daily, “usually” is not good enough. With strict: true enabled, the model is constrained at the token-generation level, making it structurally impossible to return arguments that violate your schema.OpenAI’s own evaluation data makes the difference stark. gpt-4o with Structured Outputs scores 100% on complex JSON schema adherence; gpt-4-0613 without it scores less than 40%. That 60-percentage-point gap is the difference between a reliable production system and an unpredictable one. Source: OpenAI, 2024.

How to Enable Strict Mode

Enabling strict mode requires one flag plus two schema rules that OpenAI enforces:

# Strict mode: add strict=True and follow the two required rules
tools = [{
    "type": "function",
    "function": {
        "name": "get_order_status",
        "description": "Returns shipping status for a customer order.",
        "parameters": {
            "type": "object",
            "properties": {
                "order_id": {"type": "string"},
                "include_history": {
                    "type": ["boolean", "null"]  # null = optional field
                }
            },
            "required": ["order_id", "include_history"],  # ALL fields must be required
            "additionalProperties": False                 # must be False
        },
        "strict": True
    }
}]

Rule 1: Every property in your schema must appear in the required array. If a field is genuinely optional, type it as [“string”, “null”] rather than omitting it from required.

Rule 2: additionalProperties must be set to False. This prevents the model from inventing fields that do not exist in your schema.

JSON Mode vs Structured Outputs: Why JSON Mode Is Now Legacy

JSON mode (response_format: {“type”: “json_object”}) only guarantees that the model returns valid JSON. It does not guarantee the JSON matches your schema. Structured Outputs with strict: true guarantees both. As of 2026, JSON mode is considered a legacy feature kept for backward compatibility. For any new production code, use strict: true exclusively.

FeatureJSON ModeStrict Mode (strict: true)
Guarantees valid JSONYesYes
Guarantees schema adherenceNoYes
Required fields enforcedNoYes
Field types enforcedNoYes
Recommended for productionNo (Legacy)Yes

Strict Mode and Parallel Calls: The Important Nuance

For non-fine-tuned models, strict mode and parallel function calling are now compatible. OpenAI added this support in 2025. For fine-tuned models, however, strict mode may be disabled when the model calls multiple functions in one turn. If you are using a fine-tuned model and schema reliability matters more than parallelism, set parallel_tool_calls: false to be safe. Source: OpenAI documentation and changelog, 2025.

How Does Parallel Function Calling Work in OpenAI?

Parallel function calling lets the model return multiple tool call requests in a single response, allowing your application to execute them simultaneously rather than sequentially. This is valuable whenever a customer’s question bundles multiple independent queries. For example: “Where is my order, what is my next delivery date, and can you update my shipping address?” Without parallel calls, the model handles each sequentially with a separate round trip. With parallel calls, it issues all three requests at once and you execute them simultaneously.

Parallel tool calls are enabled by default on gpt-4o, gpt-4.1, and the GPT-5 family. Source: OpenAI documentation. You do not need to enable it; you need to decide when to disable it.

Handling Parallel Calls in Code

Python:

# Parallel call handler: execute all tool calls concurrently
import asyncio
import json

async def handle_parallel_calls(tool_calls, function_map):
    async def execute_one(call):
        fn = function_map.get(call.function.name)
        args = json.loads(call.function.arguments)
        if not fn:
            result = {"error": "UNKNOWN_FUNCTION"}
        else:
            result = await fn(**args)
        return {
            "role": "tool",
            "tool_call_id": call.id,
            "content": json.dumps(result)
        }
    return await asyncio.gather(*[execute_one(c) for c in tool_calls])

JavaScript:

// Parallel call handler: execute all tool calls concurrently
const toolMessages = await Promise.all(
  toolCalls.map(async (call) => {
    const fn = functionMap[call.function.name];
    const args = JSON.parse(call.function.arguments);
    const result = fn ? await fn(args) : { error: "UNKNOWN_FUNCTION" };
    return {
      role: "tool",
      tool_call_id: call.id,
      content: JSON.stringify(result)
    };
  })
);

When to Disable Parallel Function Calling

Set parallel_tool_calls: false in three specific scenarios.

First, when calls have ordering dependencies. If function B requires the result of function A (for example, you need to look up a customer_id before fetching their orders), parallel execution misfires. Disable it and let the model chain calls sequentially.

Second, when using fine-tuned models with strict mode. As noted above, strict mode may be disabled on fine-tuned models during parallel calls. If schema reliability matters more than latency savings, which it usually does in customer support, turn parallel calls off for fine-tuned models.Third, for destructive or irreversible actions. If your tools can freeze a card, cancel a subscription, or process a refund, you do not want the model firing multiple destructive calls simultaneously on an ambiguous query. Either disable parallel calls for those tools or add a confirmation step before execution.

# Disable parallel calls for destructive or ordered workflows
response = client.chat.completions.create(
    model="gpt-4.1",
    messages=messages,
    tools=tools,
    parallel_tool_calls=False  # model returns at most one call per turn
)

How to Control Function Calling with tool_choice

tool_choice is the parameter that controls when and how the model is allowed to call your tools, giving you precise governance over AI agent behavior. By default it is set to “auto”, meaning the model decides for itself. In production customer support systems, you often need tighter control.

OpenAI offers four modes:

ValueBehaviorWhen to Use
“auto” (default)Model decides whether to call a tool, which one, and how manyGeneral-purpose conversations where query types vary
“required”Model must call at least one tool and cannot return plain textWorkflows where every turn must produce a structured action
{“type”: “function”, “name”: “get_order_status”}Forces one specific function with no exceptionsSingle-purpose endpoints and classification pipelines
“none”Disables all tool calls for this requestChat-only fallback when tools should not fire

For example, if you are building a dedicated order status endpoint, you would use tool_choice: {“type”: “function”, “name”: “get_order_status”} to guarantee the model always calls that exact function, regardless of how the customer phrases their question.

Function Calling Best Practices for Production Systems

Production function calling fails in predictable ways, and almost all failures come down to a handful of avoidable mistakes. Here are the five rules that matter most.

1. Write Function Descriptions Like API Documentation

The function description field is the primary signal the model uses for tool selection. Vague descriptions are the single most common cause of wrong function calls. A description like “Gets order info” gives the model almost nothing. A description like “Returns the current shipping status, carrier, and estimated delivery date for a customer’s order. Use this when a customer asks where their order is, when it will arrive, or about delivery delays. Do NOT use for refund or return inquiries” gives the model everything it needs. Describe parameter values precisely too: order_id: “Customer order ID, e.g. ‘ORD-12345′” prevents the model from passing “12345” instead of “ORD-12345”.

2. Keep Your Tool List Under 10 Functions Per Request

Every tool definition is part of your prompt and consumes input tokens on every request. Beyond token cost, the more tools you give the model, the more likely it is to confuse similar-sounding ones. For large tool catalogs of 20 or more functions, only pass the tools relevant to the current conversation context rather than your full catalog. The GPT-5.4 series introduced a tool search feature that defers tool definitions until the model decides it needs them. Check OpenAI’s documentation if you are working with very large tool sets.

3. Validate Arguments Before Executing: Strict Mode Validates Shape, Not Values

strict: true guarantees that {“order_id”: “ORD-99999999”} is structurally correct. It does not guarantee that order ORD-99999999 actually exists in your database. Always validate existence, authorization (does this customer own this resource?), and business bounds (is this refund amount within the original transaction total?) before executing any function call. Treat model-generated arguments as untrusted input, because that is what they are.

4. Add a Confirm-Before-Execute Pattern for Destructive Actions

For any irreversible action (freezing a card, canceling a subscription, processing a refund), split the operation into a prepare function and an execute function. prepare_refund(order_id, amount) returns a draft with no money moving. execute_refund(refund_token) only fires after the customer explicitly confirms. The model can call prepare_refund freely; execute_refund requires human confirmation. This protects against ambiguous customer queries, prompt injection attempts, and edge cases where the model is overly eager.

5. Always Handle Zero, One, or Many Tool Calls

Write your handler as a loop from day one. Never assume tool_calls[0] will exist or that there will be exactly one call. Model responses can include zero, one, or multiple calls in a single turn. Source: OpenAI documentation. A handler that crashes on a parallel response causes hard-to-debug production failures. The pattern tool_calls = response.choices[0].message.tool_calls or [] followed by a loop is the correct default for the Chat Completions API.

OpenAI Function Calling in Real Customer Support: Industry Use Cases

Function calling is most powerful in customer support because support queries are overwhelmingly operational. They require live data retrieval or system actions, not just information retrieval. Here is how it applies across three major industries where Kommunicate AI agents have delivered measurable results.

E-Commerce: Order Tracking, Returns, and Refunds

E-commerce support teams handle high volumes of repetitive operational queries including order status, return initiation, refund status, and address updates. These questions cannot be answered from a knowledge base. They require live system access.Consider a customer who messages at 11 PM: “Where is my package? It was supposed to arrive today.” Without function calling, the AI agent offers a generic response about checking the tracking page. With function calling:

This is why the feature is still commonly referred to as “function calling.”

# E-commerce: order tracking function
def get_order_status(order_id: str, customer_id: str) -> dict:
    # Queries live OMS (Order Management System)
    return {
        "order_id": order_id,
        "status": "In transit",
        "carrier": "FedEx",
        "eta": "Tomorrow by 8 PM",
        "tracking_url": f"https://tracking.fedex.com/{order_id}"
    }

The AI agent calls get_order_status(), retrieves live carrier data, and responds: “Your package is in transit with FedEx and is expected by 8 PM tomorrow. Here is your tracking link.” That answer resolves the query completely, at 11 PM, without a human agent.

Using the e-commerce AI agent capabilities built on this model, Kommunicate customers have automated the vast majority of operational queries. Lula, a mobility company, increased CSAT by 40% by providing instant resolution without human intervention. Source: Kommunicate case study.

FinTech: Card Management and Sensitive Account Actions

FinTech support requires accuracy, compliance, and speed in equal measure. Function calling enables all three by connecting the AI agent directly to your banking backend, not just your FAQ database.When a customer messages “Freeze my debit card immediately, I think it has been stolen,” speed matters. The function calling flow:

# FinTech: card freeze with identity validation
def freeze_card(card_id: str, customer_id: str, reason: str) -> dict:
    # Validates identity, calls banking API, logs compliance record
    return {
        "card_id": card_id,
        "status": "Frozen",
        "timestamp": "2026-06-01T10:32:00Z"
    }

The AI agent calls freeze_card(), the banking backend validates identity and executes the freeze, and the agent responds: “Your card ending in 4521 has been frozen as of 10:32 AM today. We have also flagged this for your fraud protection team.”

For this type of query, the confirm-before-execute pattern is strongly recommended. prepare_card_freeze() first, then execute_card_freeze() after the customer confirms. Kommunicate’s banking AI agent handles exactly this pattern, with built-in compliance logging and automatic escalation to a human agent for high-risk actions.

Healthcare: Appointment Booking and Patient Operations

Healthcare support is one of the highest-stakes support environments. Patients need accurate, specific information, and wrong answers have real consequences. Function calling ensures the AI agent connects to real scheduling systems rather than guessing at availability.When a patient messages “Book a dermatologist appointment for this Friday evening,” the AI agent should not guess. It should call your scheduling backend:

# Healthcare: appointment booking with real availability check
def book_appointment(specialty: str, preferred_date: str, patient_id: str) -> dict:
    # Queries live scheduling system for real slots
    return {
        "doctor": "Dr. Sarah Scott",
        "specialty": "Dermatology",
        "datetime": "Friday, May 30, 2026 at 6:30 PM",
        "confirmation": "APT-78291"
    }

The AI agent calls book_appointment(), your scheduling system checks real availability, and the agent responds: “Dr. Sarah Scott has a dermatology slot available this Friday at 6:30 PM. I have booked it for you. Your confirmation is APT-78291.”

Oklahoma City Community College achieved an 8.33 CSAT score by deploying Kommunicate AI agents with real system integrations for 24/7 student support. Source: Kommunicate case study, 2025. The principle is the same for healthcare: connecting the AI agent to real backend systems, not just knowledge bases, is what generates high satisfaction scores. Explore how Kommunicate’s healthcare AI agent handles these scenarios in production.

How Kommunicate Implements Function Calling for Enterprise Customer Support

Kommunicate implements the same function-calling principles covered in this guide (intent detection, backend function execution, human handoff, and omnichannel deployment) through a managed platform layer that removes the orchestration burden from your engineering team.

Building function calling from scratch requires your team to manage the full loop: schema definitions, argument validation, function dispatch, error handling, conversation state, human escalation logic, and multi-channel deployment. For many teams, that is weeks of engineering work before you handle your first real customer query.

The OpenAI integration with Kommunicate provides the same capability through:

  • Intent detection that maps natural language queries to the right workflow, equivalent to well-described tool definitions
  • Backend workflow automation through the Kompose AI Agent Builder, a no-code visual interface for connecting your APIs and triggering actions
  • Built-in human handoff that activates automatically when the AI agent reaches its confidence boundaries, equivalent to the confirm-before-execute pattern for complex cases
  • Omnichannel deployment across web, mobile, WhatsApp, Telegram, and email from a single dashboard, without duplicating your function definitions for each channel

The results from Kommunicate customers reflect what real backend integration delivers.

  • Conte.it (Insurance): Automated 90% of customer queries related to insurance purchases, renewals, and refunds, freeing human agents to focus on genuinely complex cases. Source: Kommunicate case study.
  • Lula (Mobility): Increased CSAT by 40% by resolving customer and partner queries instantly without human intervention. Source: Kommunicate case study.
  • TelOne (Telecom): Reduced agent workload by 25% by handling billing queries, technical support, and service outage assistance across web and WhatsApp. Source: Kommunicate case study.
  • Brash Solutions: Automated 500 daily queries and diverted phone calls to the AI agent, freeing the support team for complex cases. Source: Kommunicate case study.

The Before and After of Function Calling in Customer Support

Customer QueryWithout Function CallingWith Function Calling (Kommunicate)
“Where is my order?”“Please visit our tracking page.”Fetches live data, gives exact status and ETA
“Freeze my card.”“Please call our helpline to freeze your card.”Validates identity, freezes card, logs action
“Book an appointment.”“Our booking page is available at [URL].”Checks real availability, books, confirms
“What is my account balance?”“Please log in to your account to view your balance.”Fetches live account data, responds directly
After-hours queryNo resolution until next business dayResolved instantly, 24/7

Kommunicate automates over 80% of repetitive customer queries using this approach. Source: Kommunicate product documentation, 2026. The remaining 20% (complex, sensitive, or high-stakes cases) route automatically to human agents with full conversation context, so the agent never has to ask the customer to repeat themselves. Explore live chat with human handoff to see how the transition works in practice.

Start your 30-day free trial to see how function calling-powered AI agents perform on your support queries. No credit card required.

Frequently Asked Questions About OpenAI Function Calling

Does OpenAI actually run my function?

No. The model only outputs a JSON object describing which function it wants called and what arguments to pass. Your application is responsible for executing the function. This separation is intentional. It keeps your authentication, database credentials, and business logic on your own servers, where the model never has direct access.

Which OpenAI models support function calling?

Function calling is supported across all modern OpenAI chat models, including gpt-4o, gpt-4.1 (released April 2025), and the GPT-5 family (GPT-5, released August 2025; GPT-5.2, released December 2025; GPT-5.4, released March 2026). The o-series reasoning models (o3, o4-mini) also support function calling through the Responses API, integrating tool calls directly into their chain-of-thought reasoning. Source: OpenAI, 2025.

What is the difference between the Responses API and Chat Completions API for function calling?

Both APIs support function calling with the same tools parameter. The key difference is state management. The Responses API manages conversation state server-side. You pass previous_response_id and OpenAI carries the context and tools forward automatically. The Chat Completions API is stateless. You manage the full messages array yourself, appending tool call messages and tool result messages manually between turns. For new projects, OpenAI recommends the Responses API. The Assistants API has been deprecated and will shut down on August 26, 2026. Source: OpenAI changelog.

How much does function calling cost?

There is no separate charge for function calling itself. However, your function definitions count as input tokens on every request. A tool list with 10 verbose function descriptions can add hundreds of tokens to every API call. Keep descriptions specific but concise, and only pass the tools relevant to the current conversation context to manage costs.

Can I use strict: truewith parallel function calling?

On non-fine-tuned models, yes. OpenAI added support for strict mode with parallel tool calling for standard models in 2025. On fine-tuned models, strict mode may be disabled when the model calls multiple functions in one turn. If reliability matters more than parallelism (which it usually does in customer support), set parallel_tool_calls: false when using fine-tuned models. Source: OpenAI documentation.

Why does my function calling keep picking the wrong function?

Almost always, the cause is vague function descriptions. The model uses the description field as its primary signal for tool selection. A description that states when to use and when NOT to use the function dramatically improves accuracy. The second most common cause is having too many tools in a single request. Keep it under 10 where possible.

What is the difference between OpenAI function calling and Anthropic tool use?

The mechanics are essentially identical. Both define tools via JSON Schema, return structured arguments, and require your code to execute the function and return the result. The parameter names differ slightly (OpenAI uses tools and tool_choice; Anthropic uses tools and tool_choice with slightly different schema structures), and the response shapes differ. The conceptual model (model decides, your code executes) is the same across both providers.

How do I handle errors in function calling?

Return errors as structured tool result objects, not as code exceptions. If your function throws an exception and you bail out, the customer receives a generic error. If you return {“error”: “ORDER_NOT_FOUND”, “message”: “No order with that ID exists”} as the tool result, the model reads it and generates a helpful response: “I could not find an order with that ID. Could you double-check the number?”

What’s Next: Applying Function Calling to Your Support Stack

The path from reading this guide to having a function-calling-powered AI agent is shorter than most teams expect, especially if you already have backend APIs that expose the data your customers ask about most.

Here is the practical sequence to follow.

  1. Identify your top 3 high-volume queries that require live data. Typically these are order status, account information, or booking and scheduling. These become your first three functions.
  2. Define one function schema for each, using Pydantic (Python) or Zod (JavaScript). Enable strict mode from day one.
  3. Build the 5-step loop following the code in this guide. Decide upfront whether you want the Chat Completions API (stateless, more control) or Responses API (stateful, recommended for new projects). Test manually with 10 to 15 realistic customer queries before going to production.
  4. Add argument validation before each function executes. Check existence, authorization, and business logic bounds. Do not rely on strict: true alone.
  5. Add a confirmation step for any function that takes a destructive action (freeze, cancel, refund). prepare_action() first, execute_action() only after customer confirms.
  6. Evaluate using real queries. Track which functions the model selects correctly vs. incorrectly, and refine your descriptions based on failures, not on what seems intuitive.

If your team needs to move faster, or if building and maintaining the orchestration layer is not your core engineering focus, book a demo with Kommunicate to see how the platform handles steps 3 through 6 out of the box, including human handoff, multi-channel deployment, and conversation analytics. You can also view pricing to find the plan that fits your team size.


Conclusion

OpenAI function calling is the capability that transforms an AI agent from a knowledge retrieval tool into an action-capable support agent. The model decides what to call and what arguments to pass; your backend executes the logic; the result comes back and the model composes a natural, accurate reply. That five-step loop (define, request, receive, execute, return) is repeatable, predictable, and production-ready with the right guardrails in place.

The guardrails that matter most are strict: true for schema reliability, thoughtful function descriptions for accurate tool selection, business-logic validation before execution, and a confirm-before-execute pattern for destructive actions. Apply those four, and function calling becomes the most reliable component in your support stack.

The industry use cases in this guide (e-commerce order tracking, fintech card management, healthcare appointment booking) are not aspirational. They are what teams are shipping today, with measurable outcomes: 90% query automation at Conte.it, 40% CSAT improvement at Lula, and 25% workload reduction at TelOne. The underlying technology is the same whether you build the orchestration layer yourself or use a platform like Kommunicate to manage it.

The gap between an AI agent that talks and one that acts is one well-defined function schema away. Start building for free. No credit card required, 30-day trial on all plans.


Write A Comment

You’ve unlocked 30 days for $0
Kommunicate Offer
Kommunicate Blog
×