Confirmations
Risky tools — spend, mass-message, destructive, or live-deploy actions — never fire unconfirmed, whether you talk to Octo through the dashboard, email, or the API. Over HTTP, this is the same “YES machine” used everywhere else, exposed as a two-call exchange.
The flow
Section titled “The flow”- You ask for something consequential in a stateful conversation (i.e.
using
previous_response_idon/v1/responses, orconversationon/v1/chat/completions— see Statefulness). - Octo replies with assistant text asking you to confirm, quoting a short
action code — e.g. “This will send 412 SMS. Reply YES 4821 to
proceed.” On
/v1/responsesthe code is also machine-readable atmetadata.octo_pending_action. - You reply “YES 4821” in the next call of the same conversation. Octo executes the parked action and returns the result.
a = client.responses.create( model="claude-sonnet-4-6", input="Send the appointment reminder to all of list B.",)# a.output_text -> "This will text 412 people. Reply YES 4821 to send."# a.metadata -> { "octo_pending_action": "4821" }
b = client.responses.create( model="claude-sonnet-4-6", input="YES 4821", previous_response_id=a.id,)# b.output_text -> "Sent to 412 contacts."Spend actions work the same way
Section titled “Spend actions work the same way”Anything that spends money parks identically. Buying a phone number is a good example — Octo searches availability (a safe read), presents options priced in credits, then parks the purchase until you confirm:
a = client.responses.create( model="claude-sonnet-4-6", input="Buy us a Seattle (206) number for our voice agent.",)# a.output_text -> "Found (206) 555-1234 — 192 credits/month, voice + SMS.# Buying charges a recurring monthly fee. Reply YES 2214 to confirm."# a.metadata -> { "octo_pending_action": "2214" }
b = client.responses.create( model="claude-sonnet-4-6", input="YES 2214", previous_response_id=a.id,)# b.output_text -> "Purchased +1 (206) 555-1234 — voice + SMS are ready."Prices are quoted in credits (your workspace balance), never dollars. Only US and CA numbers can be bought this way; other countries require a one-time regulatory bundle, and Octo will link you to the in-app approval flow instead of attempting a charge.
Bulk operations confirm once
Section titled “Bulk operations confirm once”When you ask Octo to delete or change many matching resources at once
(“delete all closed conversations”, “clean up my Slack channels”, “cancel every
running campaign”), it calls a single bulk tool — delete_conversations,
delete_channels, delete_contacts, delete_campaigns, undeploy_agents, or
cancel_campaigns — rather than looping a per-item tool. You get one
confirmation that states the blast radius, not one per item:
a = client.responses.create( model="claude-sonnet-4-6", input="Delete all my closed conversations.",)# a.output_text -> "This will delete 232 conversations (e.g. \"Acme\", \"Globex\"…)# and their messages. Reply YES 4821 to proceed."b = client.responses.create(model="claude-sonnet-4-6", input="YES 4821", previous_response_id=a.id)# b.output_text -> "Deleted 232 conversations."Each bulk tool takes either a filter (e.g. status, channel, tag, older
than a date) or an explicit list of ids. A few behaviors worth knowing:
- Full-workspace wipes need a count handshake. A
filterof{ all: true }won’t run until you echo the live count back asconfirm_count— a guard against accidentally clearing an entire resource type. - A confirmation can be drift-aborted. The count you were quoted is a
snapshot. If the matching set has grown more than ~10% by the time you reply
YES, Octo refuses and re-asks with the new number rather than deleting more than you saw. - Running campaigns are protected.
delete_campaignsskips campaigns that are still running unless you explicitly include them; cancel them first.
Stateless calls cannot confirm
Section titled “Stateless calls cannot confirm”A /v1/chat/completions call made without a conversation param has no
thread to park a “YES” on — there’s nowhere for the confirmation to live
between calls. So stateless calls run safe tools only: anything
consequential is simply not offered. If you need Octo to be able to take
risky actions, use a stateful conversation (conversation or
previous_response_id).
No separate step-up factor
Section titled “No separate step-up factor”There is no second factor over the API distinct from the key itself — the same API key that asks for a risky action is the key that confirms it. This is the same security model described in Authentication: treat the key like a password, and rely on rate limits and spend thresholds as the backstop.