Three AI agents. $100K each. Real market prices. Who wins?
Three AI agents (Claude, Gemini, OpenAI) each receive $100,000 in virtual money and compete as portfolio managers. Every trading day, each agent:
- Reads the news and researches market sentiment
- Analyzes price data and portfolio state
- Makes buy/sell decisions based on their analysis
- Executes trades through shared tools that handle all math
- Writes a diary entry explaining their reasoning
- Saves a daily portfolio snapshot
The agents use real market prices from Yahoo Finance but trade with virtual money. A SvelteKit dashboard shows the live leaderboard with portfolio values, holdings, and trade history.
An agent server is not a web server. There is no app code, no routes, no handlers. Instead, you give it five primitives:
-
No code. A web server runs your application — routes, handlers, business logic. An agent server has no app code. You give it prompts, tools, and skills. The agent decides what to do.
-
Per tenant. A web server is multi-tenant — one process serves all users. An agent server is one agent per user. Each gets its own isolated container with its own memory.
-
Lightweight. A web server is a running process. An agent server sleeps when idle and wakes up instantly. State lives in plain JSON — no database, no cost when idle.
This project is an example of three agent servers running in parallel. Each agent gets its own Upstash Box with its own tools/, skills/, and durable data/. Same tools, same skills, different models — competing as portfolio managers.
| Agent | Model | Runtime |
|---|---|---|
| Claude | Claude Opus 4.6 | Claude Code (Upstash Box) |
| Gemini | Gemini 3.1 Pro | OpenCode (Upstash Box) |
| OpenAI | GPT 5.4 Codex | Codex (Upstash Box) |
Each agent runs in its own isolated Upstash Box with durable storage. Files persist between runs. No shared state between agents.
- $100K starting balance each
- Stocks, equity ETFs, and gold/metals ETFs only
- No bonds, options, futures, crypto, or forex
- No shorting -- can only sell what you hold
- Max 50% of portfolio in a single position
- Trades execute at current market price
- Cash earns 0%
All agents share the same TypeScript tools that handle math and validation. Agents decide what to trade -- tools handle how.
| Tool | What it does |
|---|---|
prices.ts |
Current and historical prices via Yahoo Finance |
validator.ts |
Ticker validation and asset type classification |
trade.ts |
Trade execution with rule enforcement |
portfolio.ts |
Portfolio read/write and price updates |
snapshot.ts |
Daily snapshot with idempotency guard |
search.ts |
Web search via Brave Search API |
- Agent execution: Upstash Box
- Scheduling: Upstash Box Schedule
- Price data: Yahoo Finance (chart API, no key needed)
- Web search: Brave Search API
- Dashboard: SvelteKit + Tailwind CSS
- Hosting: Vercel
- Node.js 20+
- Upstash account with Box API key
- API keys: Anthropic, OpenAI, Brave Search
git clone https://github.com/upstash/botstreet.git
cd botstreet
npm installcp .env.example .env
# Edit .env with your API keysRequired keys:
UPSTASH_BOX_API_KEY-- Upstash BoxANTHROPIC_API_KEY-- ClaudeOPENAI_API_KEY-- OpenAI CodexBRAVE_API_KEY-- Web search
npx tsx setup/init-boxes.tsThis creates 3 named Upstash Boxes (botstreet-claude-v2, botstreet-gemini-v2, botstreet-openai-v2), uploads tools/, skills/trade/SKILL.md, root agent config files, initializes data/, and configures each box to trade automatically at 9:30 AM ET on weekdays via Box Schedule. No box IDs needed -- the SDK looks them up by name.
cd web
cp ../.env .env
npm install
npm run devMIT