A model proposing a tool call is not the same as a model executing one. Push and cancel actions on Amps are real-world side effects: a battery starts charging, a scheduled action terminates, a device’s mode flips. None of those should fire from a free-form text generation. The pattern is straightforward. Destructive tool calls render a confirmation primitive. The user clicks. The tool fires. The agent stays observable; the user stays in control; the audit trail stays clean.Documentation Index
Fetch the complete documentation index at: https://docs.amps.ai/llms.txt
Use this file to discover all available pages before exploring further.
Which calls are destructive
A canonical guideline:| Tool | Destructive? | Why |
|---|---|---|
list_battery, get_battery, list_action, get_action | No | Read-only. No side effect. Render the result, no gate. |
push_battery, push_ev_charger, push_hvac | Yes | Sends a command to a device. Real-world, often irreversible within the session. |
cancel_action | Yes | Terminates a scheduled or in-flight action. |
| Any future write or mutation | Yes by default | Treat new tools as destructive until proven otherwise. |
destructive: true and routes them through the gate.
The interrupt-and-resume pattern
The Vercel AI SDK and similar agent runtimes expose a tool-call interrupt pattern. The flow:- The model emits a tool call.
- The chat shell inspects the call. If the tool is destructive, the shell does not pass the call to the executor. Instead, it renders a confirmation primitive with the proposed inputs.
- The user clicks Confirm or Cancel.
- On confirm, the shell forwards the call to the executor. The tool fires.
- On cancel, the shell injects a synthetic tool result (
{ cancelled: true }or similar) so the agent sees a clean response and can adapt its plan.
<ConfirmCard> with the tool name, the proposed arguments, and two buttons. Or it can be a richer <CapabilityControls> that lets the user adjust the parameters before confirming.
The richer pattern: capability-driven confirmation
Hand-editing a JSON-shaped action is not the user experience to ship. A better confirmation surface is<CapabilityControls> (see Dynamic UI rendering), pre-filled with the model’s proposed values:
The model proposes: pushThe user sees what’s about to happen, can adjust the bounds within the device’s declaredauto.balancedto devicebattery-living-room, scheduled to start at 18:00, end at 22:00. (rendered as a card with the verb selected, the schedule window editable, a Confirm button bottom-right)
min/max, and clicks Confirm. The tool fires with the (possibly adjusted) parameters. The agent gets the response and continues.
This is the load-bearing user experience pattern. Editable confirmation, not a binary gate. The model proposes; the user calibrates; the tool fires.
Why the gate matters
Three failure modes the gate prevents:- Accidental cost. A model that misreads “discharge to 20%” as “discharge to 80%” pushes a real action against a real battery. The gate gives the user a chance to catch it.
- Auditability. Every destructive call has a clear “user clicked Confirm at 14:32 with these args” record, separate from the model’s reasoning. Compliance and debugging both benefit.
- Trust. Users who know the model cannot fire side effects without their click are more willing to give the agent broader latitude on read calls. The gate buys reach.
Cancel-side semantics
The confirmation primitive should always offer a clean cancel path. On cancel, inject a synthetic tool result the model can read and adapt to. Common shapes:What this is not
Confirmation gates do not replace the API’s own safety surface. The API still validates capabilities, still rejects unsupported parameters with structured errors, still resolves conflicts viaonConflict. The gate is a UX layer on top of the API contract, not a substitute for it. A model that proposes a malformed action gets the same 422 from the API as any other client; the gate just gives the user a chance to intervene before the call.
What next
Dynamic UI rendering
The
<CapabilityControls> primitive that backs the richer confirmation surface.Self-describing responses
Why the proposed-args card can show real bounds without device-specific code.
Canonical actions
The action shape the confirmation primitive validates against.
Conflict resolution
What happens after confirm: the API’s own conflict semantics.