DEV Community

Cover image for Give the Risk Agent a Veto, Not a Vote
Basavaraj SH
Basavaraj SH

Posted on

Give the Risk Agent a Veto, Not a Vote

Multi-agent LLM trading frameworks keep surfacing on Hacker News, and the discussion usually fixates on the roster: a news analyst, a fundamentals analyst, a technician, a debate round. The design choice that matters most is how you combine what those agents say.

Averaging Hides the One Agent Who Was Right

There are two ways to turn several agent opinions into one action: weighted voting, where every agent returns a direction and a confidence score and you average them into a signal, or a gate, where analysts vote on direction but a separate risk agent holds binary authority to block the trade outright.

Voting feels fairer and it's easier to tune. It also quietly buries asymmetric information. If three agents are mildly bullish and one has read a footnote about a restated quarter, averaging reduces that objection into a small discount on position size. In domains where the loss distribution is fat-tailed - a handful of outcomes that dwarf all the others - you don't want the rare correct objection smoothed into the mean.

The trade-off is real. A veto costs you trades that would have worked, and it hands one model the ability to freeze the system on a hallucination. So you constrain it: the risk agent can only fire on enumerated conditions, and every block must name the rule it triggered and cite the document it relied on. An unexplained block is logged as a system failure, not as a block.

The way to choose is by examining the shape of the error, not average accuracy. Symmetric, small, noisy errors favor voting, because averaging genuinely cancels noise. Rare and large errors favor a gate.

Real Example

# analysts vote on direction; risk holds a separate switch
signal = weighted_vote(news.call, fundamentals.call, technicals.call)

veto = risk_agent.check(
 ticker, signal,
 rules=["position_limit", "earnings_blackout", "liquidity_floor"],
)

if veto.blocked:
 log(veto.rule, veto.evidence) # must name a rule AND cite a source doc
 order = None
else:
 order = size(signal, cap=veto.max_notional)
Enter fullscreen mode Exit fullscreen mode

Two details do the work. The rules list is closed, so the risk agent can't invent a reason to sit out. And veto.evidence is required - if the agent blocks without pointing at a filing, a price feed, or a position record, the pipeline treats that as a broken component and escalates instead of silently doing nothing.

This pattern generalizes well beyond trading. Any workflow where one agent handles irreversible or expensive actions - refunds, outbound messages, contract terms, publishing - has the same choice to make.

Key Takeaways

  • Choose your aggregation rule based on the shape of your losses, not average accuracy: averaging suits small symmetric errors, a gate suits rare large ones.
  • A veto only stays trustworthy if it's limited to a closed list of conditions and must cite evidence for each block.
  • Treat an unexplained block as a failure to investigate, not as a safe default - otherwise you've built an invisible kill switch.

If you gave one component in your pipeline the power to stop everything, which specific conditions would you put on its list - and how would you notice it was blocking too often?


Sources referenced: Hacker News discussion on a multi-agent LLM financial trading framework

Top comments (0)