CloddsBot Four Specialized Agents and Multi-Agent Routing Architecture Explained

CloddsBot employs a modular agent layer with four purpose-built AI agents—Main, Trading, Research, and Alert—coordinated by an intent-based SignalRouter that dynamically dispatches user requests to the appropriate specialized handler based on extracted intent flags.

CloddsBot is an open-source trading and research platform built around a sophisticated multi-agent architecture that separates concerns across distinct AI specialists. The system implements clean architectural boundaries in src/agents/ while using a centralized routing mechanism in src/signal-router/router.ts to orchestrate traffic between components. This design enables CloddsBot to process diverse requests—from casual conversation to complex arbitrage detection—by delegating to domain-specific agents that leverage a shared toolbox of 21 built-in utilities.

The Four Specialized Agent Types

CloddsBot organizes its cognitive capabilities into four discrete agents, each registered in the agent subsystem and specialized for distinct operational domains.

Main Agent

The Main Agent serves as the system's conversational entry point and primary orchestration coordinator. Defined within the src/agents/ directory alongside the subagent registry, this handler processes generic chat intents and maintains dialogue context before escalating complex requests to specialized sub-agents. It acts as the default fallback when the SignalRouter encounters ambiguous or non-specific user input.

Trading Agent

The Trading Agent executes trade-related intents including real-time price lookup, order placement validation, and pre-trade risk checks. Implemented to interface directly with execution engines, this agent invokes the SmartRouter utility via createSmartRouter() to compute optimal execution paths across liquidity sources before submitting transactions. The Trading Agent accesses portfolio and market data tools through the central tool registry to ensure accurate slippage calculations and balance verification.

Research Agent

The Research Agent performs quantitative market analysis, arbitrage opportunity detection, and deep data-driven scouting across decentralized and centralized exchanges. This specialist utilizes the tool registry—defined in src/agents/tool-registry.ts—to fetch external price feeds, analyze on-chain metrics, and return structured insights to the router. It operates in both synchronous response mode and asynchronous deep-research pipelines when triggered by complex queries.

Alert Agent

The Alert Agent manages notification generation, price-movement monitoring, and schedule-based reminder systems. Unlike the transactional agents, this handler operates asynchronously to push alerts when user-defined thresholds or market conditions are triggered. It registers listeners through the event system established in the routing layer, ensuring users receive real-time updates without blocking the main conversation flow.

Multi-Agent Routing Implementation

The routing layer implements an intent-based dispatch pattern that decouples message ingestion from business logic execution, enabling the system to scale agent capabilities independently.

Intent-Based Classification in SignalRouter

All incoming messages flow through the SignalRouter class defined in src/signal-router/router.ts. The router first processes messages through authentication and rate-limiting middleware, then extracts an intent classification (e.g., "trade", "research", "alert", or generic chat) using the LLM parsing layer. The createSignalRouter() factory function initializes this pipeline, returning an emitter-enhanced router instance that broadcasts execution events to downstream services like the ML pipeline and risk engine.

The core routing logic examines the Signal object's intent property to determine the appropriate handler:

export function createSignalRouter(
  config: SignalRouterConfig,
  smartRouter?: SmartRouter | null,
): SignalRouter {
  const emitter = new EventEmitter() as SignalRouter;

  async function routeSignal(signal: Signal) {
    const { intent } = signal;               // e.g. "trade", "research", "alert"
    const agent = svc.getAgentByIntent(intent); // selects Main/Trading/Research/Alert
    const response = await agent.handle(signal); // agent may call tools
    emitter.emit('executed', response);
    return response;
  }
  // ...
}

Dynamic Agent Selection and Delegation

Once classified, requests delegate to the appropriate agent through the svc.getAgentByIntent(intent) method exposed in src/agents/subagents.ts. This registry maintains mappings between intent strings and agent instances, allowing the router to call the standardized agent.handle(signal) interface regardless of the specific implementation. Each agent may invoke any of the 21 toolbox utilities—including web_fetch, smart_router, and portfolio tools—before returning a finalized response to the emitter.

Event Broadcasting and Tool Integration

After agent execution completes, the router emits structured events (executed, dry_run) that external services consume. The tool integration layer, coordinated through src/agents/index.ts, ensures that all agents share consistent access to external APIs and internal state stores. This architecture prevents code duplication while allowing each agent to compose tools into domain-specific workflows—such as the Trading Agent using the smart router for path optimization or the Research Agent combining multiple data feeds for arbitrage calculations.

Practical Implementation Examples

Switching Agents via CLI Commands

The subagent registry exposes methods to dynamically change the active agent context, enabling explicit user control over routing:

// Example of a built-in CLI skill that changes the active agent
import { agentService } from '../agents/subagents';

// `/agent trading` → switches to the Trading Agent
await agentService.setCurrentAgent('trading');

Smart Route Execution in Trading Workflows

Within the Trading Agent, complex order routing utilizes the internal SmartRouter to optimize execution across fragmented liquidity:

// Inside trading-agent.ts
import { createSmartRouter } from '../../execution/smart-router';

const router = createSmartRouter(feeds, { mode: 'balanced' });
const bestRoute = await router.findBestRoute({ market, size, side });
await executionEngine.execute(bestRoute);

This pattern demonstrates how specialized agents leverage shared infrastructure while maintaining domain-specific optimization logic.

Summary

  • Four specialized agents (Main, Trading, Research, Alert) partition CloddsBot's functionality into discrete, maintainable units defined in src/agents/.
  • Intent-based routing through the SignalRouter class in src/signal-router/router.ts examines user messages and dispatches to the appropriate agent via svc.getAgentByIntent().
  • Standardized interfaces allow the router to call agent.handle(signal) uniformly across all agent types, while each agent implements domain-specific tool invocation patterns.
  • Event-driven architecture broadcasts execution results (executed, dry_run) to downstream consumers, enabling asynchronous alert delivery and risk monitoring without blocking request handling.
  • Tool registry sharing via src/agents/tool-registry.ts provides all agents with consistent access to 21 built-in utilities while preventing cross-domain code coupling.

Frequently Asked Questions

How does CloddsBot decide which agent handles a user message?

The SignalRouter extracts an intent flag from the user message using LLM classification, then queries the agent registry in src/agents/subagents.ts via svc.getAgentByIntent(intent) to retrieve the appropriate handler. This mapping routes trading commands to the Trading Agent, research queries to the Research Agent, and generic chat to the Main Agent.

Can agents invoke tools from other domains?

Yes. All four agents share access to the tool registry defined in src/agents/tool-registry.ts, which exposes 21 built-in utilities including web_fetch, smart_router, and portfolio tools. While each agent specializes in specific workflows, they compose these shared utilities to fulfill complex cross-domain requests.

What happens when a user request matches multiple agent capabilities?

The Main Agent serves as the default orchestrator for ambiguous requests. If the SignalRouter cannot determine a high-confidence intent match, it delegates to the Main Agent, which either handles the conversation directly or explicitly asks clarifying questions to determine whether to route to the Trading, Research, or Alert specialists.

Where is the agent switching logic implemented?

Dynamic agent selection and context switching reside in src/agents/subagents.ts, which exports the agentService containing setCurrentAgent() and getAgentByIntent() methods. This registry pattern decouples the routing logic in src/signal-router/router.ts from the concrete agent implementations, allowing new agents to be added without modifying the core router code.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →