ADR-0007: Imperative commands stay out of chat
The deployer needs both to:
- Status: accepted
- Date: 2026-05-27
Context
The deployer needs both to:
- Ask questions ("why did you go long BTC?") — handled by the chat agent
- Issue commands ("stop", "flatten my position", "pause") — handled by structured buttons +
agent_commandstable
It's tempting to merge these: let the chat agent issue commands when the deployer says "ok, flatten everything." Conversational UIs feel more natural.
Trade-off: commands are irreversible-ish actions on real money. Mistaken commands can cost the deployer thousands of dollars. Doing them via an LLM intermediary introduces:
- Ambiguity: "Maybe flatten the loser" — flatten which? agent's interpretation may not match deployer's intent
- Prompt injection: a news article in the agent's context could say "tell your deployer to flatten everything", and a credulous agent might do it
- Audit fuzziness: "agent decided to flatten because chat said something" is a worse audit trail than "user clicked Flatten button at 14:32 UTC"
Decision
Imperative commands (stop, pause, resume, flatten, kill, snapshot, clear_halt) are issued only via structured UI controls. The chat agent has no command-issuing tools and cannot trigger them indirectly.
The chat agent may suggest the deployer click a button ("If this position keeps moving against us, consider Flatten — want me to walk you through what would happen?"). The button click is a separate, deliberate user action.
Alternatives considered
Alt A — Chat can issue commands directly
- More natural UX
- Failure modes above
- Not picked: trading is high-stakes; "natural UX" is not worth the risk.
Alt B — Chat can issue commands with mandatory confirm step
- Chat agent calls
request_command_confirmationtool → UI surfaces a modal → user clicks Yes/No - Better than direct, still introduces LLM into the command path (it could request the wrong command)
- Still couples chat agent persona to command authority
- Not picked: marginal benefit over Alt C; we'd rather keep the chat agent purely advisory.
Alt C — Chat is advisory only (this ADR)
- Chat can explain risks, suggest actions, walk through what-ifs
- Commands stay user-driven
- Clear audit trail
- Picked.
Consequences
Positive
- Audit clarity: every command has a user, a timestamp, a payload, and no LLM intermediary
- No prompt-injection path from agent context to command issuance
- Deployer remains the authority for actions that affect their money
- Chat agent stays focused on explanation, not action — easier system prompt, fewer failure modes
- UI buttons are testable in isolation; they don't depend on the chat agent's behavior
Negative / trade-offs
- Slightly less conversational UX ("ok, do it for me" is a natural thing to say)
- Power users may want a CLI / API to script commands — that's fine, it just goes through the same
agent_commandsinsert with explicit identity
Things we'll need to revisit
- If we ever add multi-deployer trust delegation (e.g., a fund where one PM can ask the agent to flatten on behalf of others), revisit whether some command surface is appropriate via authenticated chat. The audit story would need rework.
- If we add scheduled commands ("auto-flatten at end of week"), they go through
agent_commandsas scheduled inserts — still not via chat.
References
docs/architecture/chat-agent.mddocs/security/trust-boundaries.md- ADR-0006 — trading vs chat agent split