Direct answer
Function calling is a protocol for a model to propose a named action and arguments; it is not permission for the model to execute that action. Google’s Gemma guidance explicitly says the host application must parse calls, validate names and arguments, and execute them through a controlled mapping. Build the host as a policy boundary: accept only allowlisted tools, parse against a schema, validate values against current app state, check Android permissions at use time, and require a user confirmation for actions with meaningful consequences. Return a bounded result to the model only after the host operation has completed. The model can produce malformed, ambiguous, stale, or manipulative arguments. Treat output as untrusted input even when it is syntactically valid JSON or uses the expected special tokens. Reject unknown tool names, missing required fields, unexpected extra fields where relevant, values outside allowed ranges, and requests that conflict with authorization or user intent. Do not use reflection, dynamic method lookup, or a global symbol table to call arbitrary functions by model-provided name. Map an exact tool identifier to a known implementation. Tool definitions should be narrow. Prefer a small task such as “draft a note” or “show a translation” over broad actions such as “manage files” or “send anything.” Separate reversible presentation from persistent writes, external communication, purchases, deletion, permission changes, or account operations. A local model may avoid sending its prompt to a remote inference server, but tool execution can still call a network API, modify local data, open another app, or expose clipboard content. The app must document and enforce those boundaries independently. Before execution, bind a proposed call to the active request, verify the user has not cancelled or changed the task, and ask for confirmation where the app’s policy requires it. For operations that can be retried, add an idempotency key or state check to prevent duplicate actions after a timeout or process recreation. Do not treat a repeated model response as a new user authorization. After execution, return a minimal result that the model needs; do not include credentials, private records, or broad tool output. Keep an audit record of tool name, validation decision, user confirmation, outcome, and error category without logging sensitive payloads by default. A safe sequence uses explicit stages: generate proposal, parse, validate schema, authorize, confirm if needed, execute a known handler, verify the resulting state, and summarize. A “no-op” or refusal must be possible. If the parser cannot determine a call boundary, if required fields are missing, or if an application state check fails, the action must not run. If execution returns an error, do not ask the model to improvise a more powerful tool call; report the error or offer a bounded retry. Test the whole boundary with benign and adversarial fixtures: unknown function, wrong type, omitted field, extra field, out-of-range value, stale request, duplicate call, user cancellation, permission denied, process recreation, and a handler failure after partial work. Include an attempt to smuggle instructions inside a string field and verify the host treats it as data. Test the policy for each high-impact tool separately. A model’s ability to format calls does not prove that it chooses the right action, and a successful demo is not a safety certification. For mobile actions, the host still needs Android runtime permission flows. Explain why camera, microphone, contacts, or location is needed when the specific user action requires it; check permission immediately before access; degrade gracefully on denial. Confirm deletion, sending, or purchase according to the app’s explicit policy rather than letting the model infer consent. The model should never grant itself permission. Minimum implementation steps: 1. Define a closed tool registry with typed schemas, precise descriptions, required fields, allowed values, and an explicit “no tool” outcome. Version the schema with the application task. 2. Parse model output with a strict parser and validate every field. Reject malformed structure, unknown names, stale request IDs, unsupported values, or fields that the current UI did not authorize. 3. Apply app policy and Android permission checks. Add user confirmation for persistent or consequential operations and record the decision before invoking the handler. 4. Execute only the predefined handler, then verify local state and return the smallest safe result. Handle cancellation, duplicate requests, partial failure, and process recreation without repeating the action. 5. Run adversarial and regression fixtures and keep the raw proposal, validation result, and outcome in privacy-safe form. The central rule is simple: a local model can suggest; the application remains responsible for permission, validation, authorization, execution, and disclosure.
A voice assistant proposes a calendar or export action
An Android app receives structured output from a local model and wants to use it to create a reminder, copy recognized text, or export a file. The output may be malformed, repeated after a retry, or based on an old screen state.
Decision
Treat the proposal as untrusted data. Route it through a fixed tool registry, current-state validation, Android permission checks, and user confirmation for actions that persist or share information.
Expected outcome
Only an explicitly allowed handler can run, duplicate calls are controlled, and the user can cancel or reject the proposed action.
Evidence to collect
The claim becomes reviewable only when the following evidence is attached to the same artifact and test run:
- Typed schemas
- Risk tiers
- Proposal and execution receipts
Task quality needs a versioned corpus and acceptance rules. Fluent sample output is not an accuracy result.
Implementation workflow
- Define narrow tools and schemas. Create an allowlist of small operations with exact identifiers, required fields, types, bounds, and a no-action result. Do not expose a generic executor, arbitrary reflection, or a function name that can route to unrestricted application code.
- Parse and validate against current state. Reject unknown tools, malformed structures, wrong types, omitted required values, unexpected ranges, stale request identifiers, and proposals that no longer match the visible task. Treat strings as data rather than instructions to the host.
- Apply permission and confirmation policy. Check Android permissions immediately before accessing protected resources. Explain the purpose in context, degrade on denial, and require user confirmation for persistent, destructive, financial, or externally shared actions according to product policy.
- Execute one handler and verify the result. Use a predefined implementation, guard retries with request identity or state checks, verify the resulting local state, and return only a minimal non-sensitive result. Keep partial failures and cancellation visible instead of silently retrying a different action.
Keep each transition observable. A failure should identify the stage, artifact, runtime, and recovery action without logging private user content.
Acceptance criteria
- No model-provided name can invoke a function outside a closed registry of known handlers.
- Schema errors, permission denial, stale state, cancellation, duplicate proposals, and handler failure all stop or safely bound execution.
- Consequential or sharing actions require the app’s explicit confirmation policy; tool results and logs exclude sensitive payloads by default.
Decision table
| Dimension | Choice or evidence | How to interpret it |
|---|---|---|
| Model-generated structured proposal | Untrusted input | Must be parsed, schema-checked, and authorized before any handler runs. |
| Fixed allowlisted handler | Application-controlled capability | Limits available actions but still requires permission, state, and user-policy checks. |
| Dynamic execution by returned function name | Unrestricted dispatch | Unsafe because model output can select code the user and application did not authorize. |
Failure patterns to prevent
- Generic execute function
- Model-controlled confirmation
Also prevent silent fallback, unpinned artifacts, missing cancellation, and conclusions that combine unlike configurations. Store unsuccessful runs alongside successful ones.
Minimum reproducibility record
| Layer | Record |
|---|---|
| Device | Manufacturer, model, chipset, RAM class, operating-system build |
| Software | Application version and git commit |
| Model | Family, variant, revision, format, file length, hash, quantization |
| Runtime | Name, revision, requested backend, observed backend evidence |
| Workload | Fixture revision, input hash, prompt hash, output policy |
| Outcome | Completed, failed, cancelled, fallback, and privacy-safe diagnostics |
Release checklist
- ☐ The primary query is answered without an unsupported number.
- ☐ Every artifact and runtime is pinned.
- ☐ The representative task and failure policy are explicit.
- ☐ Lifecycle, cancellation, cleanup, and fallback are tested.
- ☐ User-content and network boundaries are documented.
- ☐ Result wording applies only to the recorded configuration.
- ☐ The page links to raw method or evidence when results are added.
Sources and related evidence
- FunctionGemma mobile actions
- Google AI for Developers — function calling with Gemma 4
- Google AI for Developers — FunctionGemma model card
- Android Developers — request runtime permissions
- Android Developers — unsafe deserialization risks
Chinese deployment and troubleshooting content is organized in the .奇连 AI 端侧专题.
Frequently asked questions
Can a function-calling model execute the function itself?
No. The model generates a proposal. The host application parses it, validates the tool and arguments, applies authorization, executes a known handler, and returns a result.
If the model runs locally, is the tool call private?
Not automatically. A handler may make network requests, write files, access protected data, or share through another app. Audit each tool’s data flow independently from where inference occurs.
Should every valid schema call run automatically?
No. Schema validity is not user consent. Current app state, permissions, cancellation, and action impact still matter; consequential or sharing actions should follow the explicit confirmation policy.