Agent acts on non-trivial request without confirming intent
User says "reorganize my files." The agent immediately moves files, but the user meant "suggest a new folder structure," not "execute a restructure right now." Intent Handshake requires agents to play back their interpretation before executing. The intent/interpretation gap stays invisible until the damage is done.
What goes wrong
User asks "clean up my project." The agent deletes unused files, renames directories, and updates imports in one shot. The user wanted a report. No playback, no scoping choices, no "here's what I'll do" first. Destructive, ambiguous requests get instant-execute treatment.
Detection
Surfaces: agent-chat, agent-tool-execution
Auditability: hybrid
Static signals:
- Find agent action triggers for non-trivial operations (multi-step, destructive, ambiguous).
- Check for a confirmation/playback step between request and execution.
- Flag direct execution of complex requests with no preview.
Concrete commands:
rg '(executeTool|runAction|performAction|handleToolCall)' --type=ts -l src/
rg '(delete|remove|move|rename|reorganize|migrate|deploy|publish)' --type=ts src/tools/ src/actions/
rg '(confirm|approval|preview|playback|requireApproval)' --type=ts src/
rg '(autoExecute|skipConfirm|auto_approve)' --type=ts src/
rg '(AskUserQuestion|elicitation/create|permissionMode.*plan)' --type=ts src/Judgment signals:
- Trivial, unambiguous requests ("what time is it?") don't need a handshake.
- Targets multi-step, destructive, ambiguous, or high-stakes requests.
- Framework primitives count when the agent can actually reach them: Claude Agent SDK
AskUserQuestionorplanmode, MCPelicitation/create, an AI SDK approval carrying areason. A system prompt that says "confirm before destructive actions" with no such primitive wired is a hope, not a handshake.
False-positive guards:
- Skip files with
// ax-audit-ignore:comm-no-intent-handshake. - Skip test and Storybook fixtures.
- Skip read-only operations (queries, lookups, status checks).
Fix
Before executing non-trivial actions, play back understanding: "I'll reorganize your files by moving X to Y. Proceed?" Options: text playback, structured plan preview, or scoping choices.
Default tier and overrides
Defaults to: fix-this-sprint
| Surface | Tier |
|---|---|
| Agent tool execution | release-blocker |
| Agent chat | fix-this-sprint |
Examples
Anti-pattern (fails):
async function onToolCall(tool: string, args: Record<string, unknown>) {
const result = await tools[tool].execute(args); // no confirmation, even for destructive ops
return { role: "tool", content: result };
}Applied (passes):
async function onToolCall(tool: string, args: Record<string, unknown>) {
const meta = tools[tool].metadata;
if (meta.destructive || meta.multiStep)
return { type: "pending_approval", message: `I'll ${meta.describe(args)}. Proceed?`,
onApprove: () => tools[tool].execute(args) };
return tools[tool].execute(args);
}Suppression
{/* ax-audit-ignore:comm-no-intent-handshake, read-only lookup, no side effects */}
<QuickSearchAgent />