Guides
Choosing risk levels
Every write already requires a confirmation. risk decides which ones require a second,
deliberate gesture on top of it — and that budget is small, because people stop reading warnings
they see all day.
The three levels
risk | Confirm call | Acknowledgement |
|---|---|---|
low (default) | required | no |
elevated | required | yes |
high | required | yes |
elevated and high behave identically at the API — both demand acknowledgeHighRisk: true.
The difference is the message your user sees and the weight your UI gives it. Use the
distinction for your own interface, not for a behaviour change that is not there.
A decision procedure
Ask three questions about the write, in order.
Can the person who approved it undo it themselves, in under a minute, from the same screen? If yes, it is
low. Adding an item to a draft, updating a par level, creating a task.Does it leave your system — money, a message, a supplier, a customer? If yes, at least
elevated. You cannot unsend an SMS or unspend money.Would a mistake be expensive, public, or unrecoverable? If yes,
high. Voiding a live ticket, issuing a refund, deleting records, dispatching an order.
Worked examples
| Write | risk | Reasoning |
|---|---|---|
add_items_to_cart | low | A draft. Removing the line undoes it |
update_par_level | low | A setting. Change it back |
create_task | low | Delete it |
mark_item_unavailable | low | Visible immediately, reversible in one tap |
send_purchase_order | elevated | Leaves your system. A supplier now has it |
record_waste | elevated | Moves inventory. Correcting it means a reversing entry, not an undo |
notify_customer | elevated | A person received a message |
void_ticket | high | Money, a live table, and an audit trail |
issue_refund | high | Money leaves. Reversal is a second transaction, not an undo |
delete_menu_item | high | Destructive, and it takes history with it |
approve_purchase_order | high | Commits spend on someone else's authority |
The console's starting point
The onboarding console and the dashboard's import show every operation on one screen with a risk already chosen for each write, labelled Tether suggests. It is a starting point you see and change before you confirm, never a decision: the risk registered is the one on the screen. It reads the verb and the operation's own name and path, never its prose:
| Default | When |
|---|---|
high | A word is refund-, delete- or payment-like (delete, remove, destroy, erase, purge, wipe, void, terminate, refund, reimburse, pay, payment, payout, charge, chargeback, transfer, withdraw, capture, debit), or the verb is DELETE |
elevated | Otherwise, a word is update- or cancel-like (update, change, edit, modify, set, replace, adjust, rename, move, reset, cancel, reschedule, revoke, reject, suspend, disable, deactivate, archive, close, unsubscribe), or the verb is PUT or PATCH |
low | Anything else: create-like |
A word counts in its plural, past and -ing forms (refunds, cancelled). The same words apply
in every domain, which is why the procedure above still decides: send_purchase_order starts at
low and belongs at elevated.
Do not mark everything high
The same logic applies to your interface. If the risk gate is always "click OK", it is not a
gate. Reserve the typed phrase for high and use a plainer confirmation step for elevated.
The value threshold
Independently of risk, an acknowledgement is required when the staged arguments carry a
value, amount or total at or above the configured threshold
(AI:ActionGuardrails:HighValueThreshold).
Two practical consequences for your schemas:
Name the money field value, amount or total if you want the threshold to apply. A
field called cents or grand_total is invisible to this check.
Do not put a value field on a write where it means something else. A value parameter that
holds a par level rather than a currency amount will trip the threshold at 1,000 units and
confuse everyone.
A read cannot be risky
Declaring risk above low on a tool that is not is_write is rejected at registration.
It looks careful and gates nothing: risk is consulted only on the confirm path, and a read never reaches it. Rather than ignoring the field, Tether refuses the catalog. If a read is dangerous enough to want a gate, the honest answer is usually that it is not a read — see Reads and writes.
Where risk is not the answer
Risk levels are blunt: they are per tool, not per argument, and they do not know who is asking.
- "Shift leads may void under $50." That is your permission model. Your endpoint sees every write and can refuse.
- "Only during business hours." Your endpoint.
- "Not more than three times an hour." Your endpoint.
Tether enforces the tenant boundary, because it is the only party that can. Everything specific to your organization belongs where your organization is modelled.
Changing a level later
Risk is read from the current catalog at confirm time, not from the catalog in force when the action was staged. Raising a level takes effect immediately, including for actions already pending — which is the safe direction. Lowering one takes effect immediately too, so lower deliberately.