RYO ARENA DOCS
Developer Reference

Architecture

End-to-end system flow — from a user triggering an analysis to database writes and alert delivery.

System Overview

User action (manual or scheduled trigger)


  runAnalysis(token)                    src/server/debate/runAnalysis.ts

        ├─▶  runDebate(token)           src/server/personas/index.ts
        │         │
        │         ├─▶  Bull             parallel  ──┐
        │         ├─▶  Bear             parallel    │  MixRoute gpt-4o-mini
        │         ├─▶  Quant            parallel    │  + Ryo MCP tools
        │         ├─▶  Macro-Regime     parallel    │
        │         ├─▶  Narrative        parallel  ──┘
        │         └─▶  Contrarian       sequential (after all 5)

        ├─▶  generateConsensus()        src/server/consensus/engine.ts
        │         └─▶  agreement level, conviction score, final_call

        ├─▶  detectDivergence()         src/server/divergence/detector.ts
        │         └─▶  DivergenceEvent if flip / agreement drop

        └─▶  scoreVerdicts()            src/server/backtest/scorer.ts
                  └─▶  updateReputation() per resolved position

Background Jobs (Inngest)

alerts/trigger.scheduled


  alertTriggerCheck                     src/server/inngest/functions.ts
        │  step.sleep(gapMinutes)
        │  claim optimistic lock
        │  runAnalysis(token)
        │  evaluateConditions()

        ├─▶  notifyInApp  →  TriggerEvent record
        ├─▶  notifyEmail  →  sendAlertEmail() (1h cooldown)
        └─▶  re-queue next check (infinite loop until disabled)

recheck/schedule.created


  scheduledRecheck                      src/server/inngest/functions.ts
        │  step.sleep(gapMinutes)
        │  claim lock
        │  runAnalysis(token)
        └─▶  advance nextRunAt, re-queue

Key Files

FilePurpose
src/server/debate/runAnalysis.tsMain orchestrator — runs debate, consensus, divergence, scoring
src/server/personas/index.tsrunDebate() — parallel persona execution
src/server/consensus/engine.tsgenerateConsensus() — aggregates verdicts into a Consensus
src/server/divergence/detector.tsdetectDivergence() — compares two consecutive snapshots
src/server/backtest/scorer.tsscoreVerdictsForToken() — resolves positions against price
src/server/backtest/reputation.tsupdateReputation() — upserts Reputation records
src/server/inngest/functions.tsscheduledRecheck + alertTriggerCheck Inngest functions
src/server/triggers/conditions.tsevaluateConditions() — checks alert conditions
src/server/email/mailer.tssendAlertEmail() — Nodemailer SMTP dispatch
src/server/mcp/tools.tsRyo MCP API wrappers with 1 req/s rate limiter
src/lib/llm.tsaskPersona() — MixRoute API call returning parsed Verdict JSON

Data Flow

  1. Persona → Verdict — Each agent calls askPersona(prompt) which hits MixRoute. The LLM uses the injected Ryo MCP tool results and returns a structured Verdict JSON object.
  2. Verdict → ConsensusgenerateConsensus() groups verdicts by stance, computes weighted conviction (1.5× for majority), and determines the final_call.
  3. Consensus → DivergenceEventdetectDivergence() compares the new consensus with the previous one for that token. Stores a DivergenceEvent if a meaningful shift occurred.
  4. Consensus → ReputationscoreVerdictsForToken() resolves any unresolved positions from prior debates using the new consensus's entry refs as a proxy price. Resolved positions update the relevant Reputation record.

On this page