Webhooks vs. tools: when to give your voice agent a hand.
A practical taxonomy for when an action belongs to your backend, the agent's tool registry, or somewhere in between.
The most common architecture mistake we see new Tone users make is putting everything in the tool registry. The second most common is putting everything in a webhook. Neither is wrong; both are usually wrong for any given action.
Here's the rule we've settled on after several hundred production agents.
The decision tree
For any action your agent might take, ask:
- Does the agent need the result to continue the conversation?
- Is the action user-visible (does it change what the agent says next)?
- Is the action idempotent and safe to retry?
If yes, yes, yes → it's a tool. The agent calls it inline.
If no, no, no → it's a webhook. Fire and forget after the call ends.
If something in the middle → it's a deferred tool: the agent kicks it off, moves on, and the result lands in your CRM whenever.
Tools: the inline path
Use tools when the next sentence the agent says depends on the result. Examples:
- Check appointment availability.
- Look up a customer's last order.
- Validate a confirmation number.
The cost is latency. A tool call adds a network round-trip to your turn budget. Keep tool handlers fast (p95 < 300ms) or the agent feels sluggish.
Webhooks: the after-call path
Use webhooks when nothing the agent is about to say depends on the result. Examples:
- Log the call transcript to your data warehouse.
- Send a follow-up SMS with a calendar link.
- Trigger a Slack notification to a human.
These are unsuited as tools because they don't affect the conversation — making them inline just wastes turn budget.
Deferred tools: the in-between
The trickiest case. The agent needs to promise something will happen, but doesn't need to wait for confirmation. Example: "I'll have a manager call you back within the hour."
Pattern:
agent.registerTool({
name: 'schedule_callback',
description: 'Schedule a human callback. Returns a confirmation token.',
handler: async ({ phone, window }) => {
const token = await callbackQueue.enqueue({ phone, window });
return { token, confirmed_at: new Date().toISOString() };
},
});The handler returns immediately with a token. The actual scheduling happens async. The agent gets the confirmation it needs to keep the conversation moving without paying for the full operation.
The TL;DR
If the agent's next sentence depends on it, it's a tool. If it doesn't, it's a webhook. If it sort-of does, it's a deferred tool.
Most of your integrations are probably webhooks. Most teams over-tool. Resist.