Field note
Gemini API Function Calling: Approval Controls
Gemini decides which function to call and with what arguments, but your application runs it, so the approval gate belongs in your code and not in the prompt.
Gemini decides which function to call and with what arguments, but your application runs it, so the approval gate belongs in your code and not in the prompt.
What function calling actually does
Google's documentation describes function calling as a way to connect a model to external tools and APIs. You send a prompt together with one or more function declarations: a name, a description and a typed parameter schema. Instead of answering in text, the model can return a function call step containing the function name and the arguments it has chosen. Your application then executes that function. Google's own wording is that execution is "your responsibility": the model does not run anything. You send the result back and the model writes the final reply.
The model can propose several calls in one turn (parallel function calling) or chain them across turns (compositional function calling). Google's examples include scheduling appointments, creating invoices and sending emails. Those are exactly the actions a small business would want reviewed.
The important point for governance is simple. A function call is a proposal. Everything that happens after it is ordinary application code that you control and can test.
Where the risk sits
There are three places where a function-calling integration goes wrong.
Declaring too much. If the tool list for a customer-service turn includes issue_refund and send_email when the task only needs look_up_order, the model can pick the wrong one. Google's best-practice guidance is to keep the active set small (it suggests 10 to 20 tools at most) and to use strong typing and enums rather than free text.
Trusting the arguments. The model fills the parameters from the conversation, and the conversation may include untrusted text: a pasted email, a web page fetched by another tool, a support ticket. An invoice for the wrong customer, an amount the user never stated or a date in the past are all plausible outputs. Google's guidance says to validate function calls before executing them.
Retries. The official SDKs retry transient errors such as 429 and 5xx automatically with exponential backoff. If a write function is not idempotent, a timeout followed by a retry can create two records or send two messages.
The control pattern
- Split functions into read and write. Declare only the functions the current turn needs. Use
tool_choiceto constrain the model:autolets it decide,anyforces a call,noneprohibits calls, and the allowed-tools list restricts which functions it may pick in that turn. - Validate every argument in code against business rules: the customer exists, the amount is within the caller's limit, the date is in the future, the actor is allowed to touch that record. If validation fails, return a function response that says why and let the model ask the user again.
- Put an approval step in front of side effects that are costly or hard to reverse: payments, refunds, external messages, deletions, permission changes. The approval is a record of who approved, what was approved and the exact arguments executed.
- Make write functions idempotent by passing a request key, so a retried call cannot run twice.
- Log the function call, the validated arguments, the approval decision, the model version and the external result. Keep secrets and card data out of the log.
The distinction between a permission the integration holds and an approval a person gives is covered in AI agent approval versus permission. The broader access-matrix approach is in the agentic AI security checklist for SMEs.
What to write into policy
| Question | Rule to record |
|---|---|
| Which functions may run without a person? | Read-only lookups against named systems |
| Which need approval every time? | Payments, refunds above a threshold, external messages, access changes |
| Who approves? | A named role, never "whoever is in the chat" |
| What is logged? | Call, arguments, decision, result, model version |
| How is a function removed? | A configuration change with a named owner, tested at least quarterly |
Keep the policy short enough that a developer will read it before adding a new function.
When to escalate to Google
Escalate when the behaviour is the API's and not yours. Google documents a Malformed_Function_Call failure that can occur when the prompt requires structured text immediately before a tool call; the documented workaround is not to require text before tool calls. A 429 RESOURCE_EXHAUSTED response is a rate or spend limit for the project, and the current limits are shown in AI Studio. Model retirements and API changes are listed on Google's deprecation and release pages, so pin model versions and rerun your function-calling tests after any change. Everything else, including a bad argument that passed validation, is an application bug and stays with you.