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:
- Send the user request, system instructions, conversation context, and available tool definitions to the model.
- Inspect the model response for a tool call.
- Validate the tool name and every argument against a schema and application rules.
- Check authentication, authorization, rate limits, and approval requirements.
- Execute the tool in a controlled application layer.
- Return a bounded tool result to the model.
- 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
| Approach | Best suited to | Control and trade-offs |
|---|---|---|
| Function calling | Connecting a model to a defined set of application functions | Direct and flexible, but your team must implement validation, permissions, execution, and error handling |
| Plugins or provider-managed extensions | Using an integration exposed through a model platform | Can reduce integration work, but available controls, portability, and lifecycle depend on the platform |
| Workflow tools | Sequencing known steps such as approvals, notifications, and data transfers | Good for visible, repeatable processes; less suited to open-ended reasoning unless paired with a model |
| Agent frameworks | Managing tool selection, memory, routing, and multi-step loops | Useful 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 change | Likely questions to investigate | Possible response |
|---|---|---|
| More invalid arguments | Is the schema ambiguous? Did an API contract change? Are examples inconsistent? | Clarify descriptions, tighten enums and validation, and add targeted test cases |
| More repeated calls | Is 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 declines | Are users seeing unexpected targets, excessive permissions, or unclear previews? | Improve the confirmation summary and reduce the action's scope |
| Higher latency or cost | Are 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 answers | Is 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.