LLM Function Calling and Tool Use: Build Reliable AI Agents with Schemas and Approval Steps
function-callingai-agentstool-usellm-developmentapi-integration

LLM Function Calling and Tool Use: Build Reliable AI Agents with Schemas and Approval Steps

DDigital Insight Editorial Team
2026-11-10
9 min read

Learn how to build reliable LLM tool use with clear schemas, validation, permissions, approval gates, retries, and recurring safety reviews.

LLM function calling lets a model request actions from APIs, databases, search systems, and internal services without giving the model direct, unrestricted access. This guide presents a practical workflow for defining tools, validating arguments, controlling permissions, handling multi-step calls, and adding approval steps so AI agents remain useful, observable, and safe to operate.

Overview

In a tool-using application, the language model usually does not execute a function itself. Instead, it selects a declared tool and returns structured arguments. Your application validates that request, decides whether the operation is allowed, executes the underlying code, and sends the result back to the model. The model can then produce an answer or request another tool.

A typical loop looks like this:

  1. Send the user request, system instructions, conversation context, and available tool definitions to the model.
  2. Inspect the model response for a tool call.
  3. Validate the tool name and every argument against a schema and application rules.
  4. Check authentication, authorization, rate limits, and approval requirements.
  5. Execute the tool in a controlled application layer.
  6. Return a bounded tool result to the model.
  7. Repeat only while the workflow remains within its step, time, and cost limits.

This separation is important. A prompt can describe what a tool should do, but it should not be the only security boundary. The application must enforce permissions and validation independently of the model's output.

Function calling, tool calling, and structured tool use are often used interchangeably, although provider APIs differ in naming, schema support, streaming behavior, and parallel-call handling. Treat the examples below as provider-neutral design patterns, then check the current documentation for the model and SDK you use.

Function calling compared with other approaches

ApproachBest suited toControl and trade-offs
Function callingConnecting a model to a defined set of application functionsDirect and flexible, but your team must implement validation, permissions, execution, and error handling
Plugins or provider-managed extensionsUsing an integration exposed through a model platformCan reduce integration work, but available controls, portability, and lifecycle depend on the platform
Workflow toolsSequencing known steps such as approvals, notifications, and data transfersGood for visible, repeatable processes; less suited to open-ended reasoning unless paired with a model
Agent frameworksManaging tool selection, memory, routing, and multi-step loopsUseful abstractions, but they do not remove the need for application-level security, testing, and observability

What to track

1. Define narrow tools with explicit schemas

Start with the smallest useful action. A tool named manage_account is difficult to reason about because it may combine unrelated operations. Separate tools such as get_account_status, create_support_ticket, and request_refund_review make intent, authorization, and testing clearer.

A schema should describe the tool's purpose, required arguments, allowed values, and meaningful constraints. For example:

{
  "name": "create_support_ticket",
  "description": "Create a support ticket for an authenticated customer. Use only after confirming the issue summary and customer identifier.",
  "parameters": {
    "type": "object",
    "properties": {
      "customer_id": {
        "type": "string",
        "description": "The internal customer identifier"
      },
      "summary": {
        "type": "string",
        "description": "A concise description of the customer's issue"
      },
      "priority": {
        "type": "string",
        "enum": ["low", "normal", "high"]
      }
    },
    "required": ["customer_id", "summary", "priority"],
    "additionalProperties": false
  }
}

Use descriptions to remove ambiguity, not to hide business rules in prose. Validate length, format, ownership, and permitted values in application code as well. Some providers support only a subset of JSON Schema features, so verify which constraints are actually enforced by the selected API.

2. Separate read tools from write tools

Read-only operations, such as retrieving an order status, generally have a different risk profile from writes, such as deleting data or sending a message. Label that distinction in your internal tool registry and use it in authorization and approval policies.

A useful registry can track:

  • Tool name, owner, version, and purpose.
  • Whether the tool reads, creates, modifies, or deletes data.
  • Required user identity, scopes, tenant boundaries, and service credentials.
  • Whether the tool can affect external parties or create financial, legal, or operational consequences.
  • Timeout, retry, rate-limit, and maximum-result settings.
  • Approval requirements and an audit-log destination.

3. Validate every model-generated argument

Schema validation is the first filter, not the last one. Before execution, check that the authenticated user can access the referenced resource, that identifiers belong to the correct tenant, and that the requested action is permitted in the current state.

Normalize values where appropriate, reject unexpected fields, and avoid passing raw model output directly into SQL, shell commands, URLs, or file paths. Use parameterized database queries and dedicated client libraries. For tools that accept text, enforce size limits and treat the text as untrusted input.

4. Add an approval gate for consequential actions

Require explicit human confirmation before a tool sends an external communication, changes permissions, deletes or overwrites data, commits a purchase, publishes content, or performs another difficult-to-reverse action. The approval screen should show the exact action, target, arguments, expected consequence, and identity under which it will run.

Do not ask for vague approval such as “Continue?” A better request is: “Send this message to 12 recipients from the support mailbox?” The approved payload should be bound to the reviewed action so the model cannot silently alter it between review and execution.

5. Manage multi-step calls deliberately

Multi-step tool use can be useful for workflows such as finding an order, checking eligibility, and preparing a support response. It can also create loops, duplicate writes, or unexpected chains of actions. Set a maximum number of tool rounds, an execution deadline, and a per-request budget. Maintain a clear state object that records completed steps and prevents an idempotent operation from being repeated unnecessarily.

When several read-only tools are requested together, parallel execution may reduce latency if the provider and application support it. Do not parallelize operations with ordering dependencies or shared mutable state without explicit coordination.

6. Return useful but bounded tool results

Tool results should contain the fields the model needs, not an unrestricted database dump. Redact secrets and unnecessary personal data, cap result size, and include a clear status such as success, not_found, or temporary_failure. A structured error gives the model a chance to recover without exposing stack traces or internal credentials.

For retrieval-heavy applications, pair tool use with a deliberate retrieval design rather than allowing the model to search every system indiscriminately. The RAG tutorial for developers explains how retrieval can be separated from generation and evaluated as its own workflow.

Cadence and checkpoints

Tool integrations change over time. Review them on a monthly or quarterly cadence, and perform an additional review whenever a model provider, SDK, database, API contract, permission model, or business process changes.

At each monthly review

  • Inspect tool-call failures, validation rejections, timeouts, retries, and approval declines.
  • Look for repeated incorrect arguments, ambiguous tool descriptions, and calls that should have been handled by a simpler path.
  • Review latency, token or usage cost, result sizes, and the number of tool rounds per request.
  • Sample audit logs to confirm that the user, tool, arguments, decision, and result are recorded without exposing secrets.

At each quarterly review

  • Re-run a regression set covering normal requests, missing information, malformed arguments, unauthorized resources, prompt-injection attempts, and provider errors.
  • Reconfirm each tool's owner, scope, credential, data access, approval policy, and retirement status.
  • Test fallback behavior when a tool is unavailable or returns incomplete data.
  • Check current provider API documentation for changes to function-calling syntax, supported schema features, parallel calls, streaming, and SDK behavior.

Keep a versioned tool contract and a small evaluation dataset. This makes it possible to tell whether a change improved reliability or merely shifted failures elsewhere. For broader prompt regression work, see the guide to prompt testing frameworks.

How to interpret changes

A higher tool-call rate is not automatically a success. It may mean the agent is solving more tasks, or it may indicate that the instructions are causing unnecessary searches and repeated calls. Interpret tool metrics alongside task completion, user corrections, approval outcomes, latency, and operational cost.

Observed changeLikely questions to investigatePossible response
More invalid argumentsIs the schema ambiguous? Did an API contract change? Are examples inconsistent?Clarify descriptions, tighten enums and validation, and add targeted test cases
More repeated callsIs the result unclear? Is the model missing a completion signal? Is the operation non-idempotent?Return explicit statuses, add idempotency keys, and cap repeated attempts
More approval declinesAre users seeing unexpected targets, excessive permissions, or unclear previews?Improve the confirmation summary and reduce the action's scope
Higher latency or costAre tool rounds expanding? Are results too large? Can independent reads run in parallel?Trim outputs, set budgets, cache safe reads, and simplify the workflow
Successful calls with poor answersIs the tool returning authoritative, relevant data in a format the model can use?Improve result structure and test the complete tool-to-answer path

Prompt-injection defenses deserve separate attention. Content retrieved from a web page, document, ticket, or email is data, not an instruction to change the agent's policy. State this distinction in the system design, isolate untrusted content, restrict tool permissions, and require application-side authorization even when the model appears confident. A useful prompt is not a substitute for a permission check.

For reliability outside the tool loop, pair structured tool results with robust timeout, retry, and fallback handling. The guide to LLM API error handling covers those operational concerns in more detail.

When to revisit

Revisit this implementation whenever you add a tool, change a schema, migrate model providers, update an SDK, modify authentication, or introduce a new class of external action. Also return to it after an incorrect argument reaches production, an approval is bypassed, a tool call loops, or an incident reveals that logs do not contain enough context.

Use this production checklist as a final review:

  • Tool selection: Each tool has one clear purpose, a named owner, a documented risk level, and a defined retirement process.
  • Schema: Required fields, enums, limits, and unexpected-property behavior are explicit and tested against the provider's supported features.
  • Authentication: Credentials are stored outside prompts, scoped to the minimum required access, and separated by environment or tenant where appropriate.
  • Authorization: The application checks the current user's identity, resource ownership, and action permissions for every call.
  • Approval: High-impact actions show an exact, reviewable payload and bind execution to the approved version.
  • Execution: Timeouts, retries, idempotency, rate limits, step limits, and safe failure states are implemented.
  • Logging: Store tool name, schema version, request identifier, decision, timing, outcome, and redacted arguments for troubleshooting and review.
  • Injection resistance: Treat retrieved or user-supplied content as untrusted data and keep security rules outside the model's discretion.
  • Testing: Include valid, invalid, adversarial, unauthorized, unavailable, and multi-step scenarios in repeatable evaluations.

Start with one read-only tool and a narrow use case. Measure whether it solves the intended task, then add write capabilities only after validation, authorization, logging, and approval are working. This incremental approach makes an AI agent easier to understand and gives you a clear checkpoint each time its permissions expand. For related prompt design patterns, see structured output prompts and AI prompt templates for developers.

Related Topics

#function-calling#ai-agents#tool-use#llm-development#api-integration
D

Digital Insight Editorial Team

AI Development Editors

Senior editor and content strategist. Writing about technology, design, and the future of digital media. Follow along for deep dives into the industry's moving parts.