Introducing Colosseum: A Multi-Agent Investment Committee Framework
I’ve been building Colosseum, a multi-agent framework that simulates an investment committee using AI agents. Instead of a single AI making trading decisions, Colosseum orchestrates multiple specialized agents that collaborate like a real investment team.
The Concept
Traditional algorithmic trading systems follow rigid rules or single-model predictions. But real investment committees work differently - they have:
- A technical analyst examining charts and patterns
- A fundamental analyst reviewing financials
- A news analyst monitoring market sentiment
- A risk manager ensuring position limits
Colosseum brings this collaborative approach to AI-driven investing.
Architecture Overview
The framework is built on modern Python infrastructure:
┌─────────────────────────────────────────┐
│ Colosseum Multi-Agent Framework │
├─────────────────────────────────────────┤
│ ┌──────────────┐ ┌─────────────────┐ │
│ │ PostgreSQL │ │ Agent Services │ │
│ │ Database │←─┤ - Supervisor │ │
│ │ (State) │ │ - Plugins │ │
│ └──────────────┘ │ - MCP Clients │ │
│ └─────────────────┘ │
│ Podman Quadlets + systemd │
└─────────────────────────────────────────┘
Core Technologies
- LangChain & LangGraph: Modern agent orchestration using the
create_react_agentpattern - Model Context Protocol (MCP): Secure, standardized communication between agents and external services
- PostgreSQL 16: Production-grade state persistence and conversation history
- Podman Quadlets: Container orchestration via systemd (replacing Kubernetes)
The SupervisorAgent
At the heart of Colosseum is the SupervisorAgent - a coordinator that manages tool registration and MCP server connections:
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
class SupervisorAgent:
def __init__(self, config):
self.llm = ChatOpenAI(
model="gpt-4",
temperature=config.get("temperature", 0.7)
)
self.tools = []
self.mcp_servers = {}
def register_tool(self, tool):
"""Register a tool for agent use"""
self.tools.append(tool)
def create_agent(self):
"""Create the ReAct agent with registered tools"""
return create_react_agent(
self.llm,
self.tools
)
This supervisor pattern allows dynamic tool registration and maintains a registry of all available MCP servers (broker APIs, news feeds, market data).
Model Context Protocol Integration
One of Colosseum’s key innovations is using MCP for broker integration. MCP provides:
- Standardized interfaces - All brokers implement the same base protocol
- Security boundaries - Clear separation between agent logic and broker access
- Auditability - All broker interactions are logged and traceable
Here’s the MCP architecture from colosseum/mcp/base.py:
class MCPServer(ABC):
"""Base class for all MCP servers"""
@abstractmethod
async def connect(self) -> bool:
"""Establish connection to the service"""
pass
@abstractmethod
async def disconnect(self) -> None:
"""Clean disconnect"""
pass
class BrokerMCPServer(MCPServer):
"""MCP server for broker platforms"""
@abstractmethod
async def get_account_info(self) -> dict:
pass
@abstractmethod
async def place_order(self, symbol: str, quantity: int,
order_type: str) -> dict:
pass
@abstractmethod
async def get_positions(self) -> list:
pass
Current broker integrations include:
- Interactive Brokers (
ib.py) - E*TRADE (
etrade.py) - DAS Trader (
dastrader.py)
State Persistence
Multi-agent systems need to remember conversations and maintain state across sessions. Colosseum uses SQLAlchemy 2.0 with three core models:
class AgentState(Base):
"""Stores individual agent state"""
__tablename__ = 'agent_states'
id = Column(Integer, primary_key=True)
agent_id = Column(String, unique=True, nullable=False)
state_data = Column(JSON) # Flexible JSON storage
updated_at = Column(DateTime, default=datetime.utcnow)
class ConversationHistory(Base):
"""Multi-agent conversation tracking"""
__tablename__ = 'conversation_history'
id = Column(Integer, primary_key=True)
session_id = Column(String, nullable=False)
agent_id = Column(String, nullable=False)
message = Column(Text)
timestamp = Column(DateTime, default=datetime.utcnow)
class MCPServerState(Base):
"""Cache MCP server connection state"""
__tablename__ = 'mcp_server_states'
id = Column(Integer, primary_key=True)
server_id = Column(String, unique=True, nullable=False)
connection_state = Column(JSON)
last_connected = Column(DateTime)
The database supports both PostgreSQL (production) and SQLite (development), with automatic schema creation and health checks.
Configuration System
Colosseum follows the XDG Base Directory Specification for Linux-native configuration management:
# Configuration locations (in priority order):
# 1. ~/.config/colosseum/config.yaml (user-specific)
# 2. /var/lib/colosseum/config.yaml (service-specific)
# 3. /etc/colosseum/config.yaml (system-wide)
def load_config():
config_paths = [
Path.home() / '.config' / 'colosseum' / 'config.yaml',
Path('/var/lib/colosseum/config.yaml'),
Path('/etc/colosseum/config.yaml'),
]
for path in config_paths:
if path.exists():
with open(path) as f:
return yaml.safe_load(f)
Example configuration:
agent:
model: "gpt-4"
temperature: 0.7
database:
url: "postgresql://user:pass@localhost:5432/colosseum"
mcp_servers:
- type: "broker"
provider: "interactive_brokers"
config_file: "/etc/colosseum/ib_config.json"
- type: "news"
provider: "etrade"
config_file: "/etc/colosseum/etrade_config.json"
Deployment with Podman Quadlets
Initially, I used Kubernetes (KIND), but ran into localhost networking issues - a notorious problem with KIND. The solution? Podman Quadlets with systemd.
Quadlets provide:
- Native Linux integration via systemd
- Simpler networking (bridge mode with proper DNS)
- No Kubernetes complexity for single-node deployments
- Better developer experience
The deployment system (quadlet_deploy.py) manages:
- Service installation and configuration
- Lifecycle management (start/stop/restart)
- Log viewing via journalctl
- Container shell access
- Database utilities
Services include:
colosseum-network.network: Bridge network for container communicationcolosseum-db.container: PostgreSQL 16 Alpinecolosseum-agent.container: Fedora-based agent runtime- Persistent volumes for data and state
What’s Next
Current development focus:
- Enhanced agent specialization - Creating dedicated technical, fundamental, and sentiment analysis agents
- Backtesting framework - Historical simulation capabilities
- Risk management layer - Position limits, exposure checks, kill switches
- Web UI - Dashboard for monitoring agent decisions and portfolio state
- Paper trading integration - Live testing without real money
Why This Matters
Multi-agent systems represent a shift from monolithic AI to collaborative intelligence. Rather than trying to build one perfect model, we can:
- Specialize agents for specific tasks
- Enable debate and consensus building
- Maintain audit trails of decision-making
- Adapt by swapping or adding agents
Colosseum makes this practical for quantitative trading.
Interested in multi-agent trading systems? Check out the Colosseum repository or reach out on GitHub.