Chat interface for actions that should be buttons
User wants to toggle a setting or trigger a known action, but chat is the only interface. They type "turn on dark mode" and wait for a round-trip instead of flipping a switch. Chat is the ONLY path to deterministic actions.
What goes wrong
User types "enable dark mode" in chat; agent responds after 2 seconds. A toggle would take 50ms. Multiply across every simple action and chat becomes a bottleneck.
Detection
Surfaces: agent-chat
Auditability: observational
Static signals:
- Find chat input surfaces.
- Identify deterministic actions achievable through chat (toggles, selections, CRUD).
- Flag cases where chat is the only path to a simple action.
Concrete commands:
rg -l 'ChatInput|MessageInput|PromptInput' --type=ts src/
rg -l 'Toggle|Switch|Select|Dropdown' --type=ts src/components/Judgment signals:
- The anti-pattern is chat-only for deterministic actions. Some conversational interface is expected.
- Controls rendered inside the chat stream count: an MCP Apps
ui://resource or an AI SDKdata-*part that renders a real toggle, table, or picker is direct manipulation. The fail is a text box as the only path.
False-positive guards:
- Skip
// ax-audit-ignore:control-over-conversational, test, and Storybook files.
Fix
Add direct-manipulation controls alongside chat: quick-action buttons, command palette, context menus. Keep chat for ambiguous or multi-step requests.
Examples
Anti-pattern (fails):
<div>
<DataTable data={data} />
<AgentChat onSend={handleAgentCommand} /> {/* no sort, filter, or action controls */}
</div>Applied (passes):
<div>
<DataTable data={data} onSort={handleSort} sortable />
<QuickActions actions={[{ label: "Export CSV", handler: exportCsv }]} />
<AgentChat onSend={handleAgentCommand} />
</div>Default tier and overrides
Defaults to: fix-this-sprint
| Surface | Tier |
|---|---|
| Agent tool execution | backlog |
| Agent chat | fix-this-sprint |
| Agent config | fix-this-sprint |
| Agent dashboard | fix-this-sprint |
Suppression
{/* ax-audit-ignore:control-over-conversational, chat-first product by design */}
<AgentChat onSend={onSend} />