Tutorial: Building a Market Analyst System
Relevant source files
The following files were used as context for generating this wiki page:The Market Analyst system is a real-time, multi-agent application designed to demonstrate the capabilities of the Loom runtime. It showcases an event-driven architecture where specialized agents collaborate to analyze market data, generate trading plans using an LLM, and execute trades. This system exemplifies key Loom features such as asynchronous fan-out/fan-in patterns, parallel processing, and intelligent aggregation.
The primary goal of the Market Analyst app is to unlock long-lifecycle, proactive agents with tiered memory, representing a significant step in the project's progression. It builds upon the foundational concepts of Loom's "Brain/Hand Separation," where Python agents handle fast-iterating cognitive tasks and the Rust core manages stable, secure execution.
Sources: apps/market-analyst/README.md:3-15, ROADMAP.md:12, 106-107, README.md:58-82
System Architecture
The system is composed of several specialized agents that communicate via the Loom Event Bus. The data flows from a real-time data source, through parallel analysis agents, to a central planner, and finally to an execution agent.
This diagram illustrates the event-driven flow between the agents in the Market Analyst system.
Agent Components
Each agent has a specific responsibility within the system, demonstrating a separation of concerns.
| Agent | Responsibility | Source File |
|---|---|---|
data.py | Connects to OKX WebSocket for live market prices (e.g., BTC, ETH) and emits market.price.* events. | apps/market-analyst/README.md:65-67 |
trend.py | Performs technical analysis on price data. | apps/market-analyst/README.md:68-69 |
risk.py | Calculates risk metrics based on market data. | apps/market-analyst/README.md:70-71 |
sentiment.py | Analyzes market sentiment from news and social data. | apps/market-analyst/README.md:72-73 |
planner.py | Aggregates results from analysis agents, uses an LLM for reasoning, and generates a trading plan. | apps/market-analyst/README.md:74-75 |
executor.py | Executes the trading plan by placing orders via the OKX WebSocket API. | apps/market-analyst/README.md:76-77 |
Sources: apps/market-analyst/README.md:63-78
Configuration (loom.toml)
The system's behavior is configured in the loom.toml file, allowing for easy adjustments to LLM providers, data sources, and agent parameters.
| Section | Key | Description |
|---|---|---|
[llm.deepseek] | api_key, model, etc. | Configures the LLM provider used by the Planner Agent. Supports environment variables like ${DEEPSEEK_API_KEY}. |
[agents.data-agent] | data_source, symbols | Defines the market data source (e.g., "okx") and the symbols to track (e.g., ["BTC-USDT", "ETH-USDT"]). |
[agents.planner-agent] | llm_provider, timeout_ms | Specifies which LLM to use and the timeout for waiting on analysis results (e.g., 3000ms). |
[agents.executor-agent] | enable_trading, min_order_size, max_order_size | Contains safety switches and parameters for trade execution. enable_trading is false by default. |
Sources: apps/market-analyst/README.md:86-118, apps/market-analyst/agents/planner.py:309-312
Planner Agent: Aggregation and Decision Making
The Planner Agent is the "brain" of the operation. It aggregates asynchronous analysis reports and uses an LLM to formulate a coherent trading plan.
Sources: apps/market-analyst/agents/planner.py
Analysis Aggregation
The PlannerBuffer class is responsible for collecting partial analyses from the trend, risk, and sentiment agents.
- It stores incoming analysis payloads, keyed by symbol.
- A plan can be generated if at least two analyses are received (e.g., trend and risk).
- If all analyses are not received within a configurable timeout (
timeout_sec), it proceeds with the data it has. This ensures the system remains responsive.
The planner_timeout_loop periodically checks for expired buffers and triggers planning to prevent indefinite waiting.
Sources: apps/market-analyst/agents/planner.py:25-63, 287-306
Planning Logic
The make_plan function orchestrates the decision-making process. It first attempts to use an LLM for intelligent reasoning and falls back to a simpler rule-based system if the LLM fails.
This flowchart shows the decision path within the make_plan function.
Memory-Aware Planning
A key feature of the Planner is its integration with Loom's core memory. Before making a decision, it queries recent plans to avoid issuing redundant or contradictory orders in a short time frame.
- Query History: It calls
ctx.get_recent_plans()to fetch the last few trading decisions. - Duplicate Check: It uses
ctx.check_duplicate_plan()to see if an identical plan was made recently. If a duplicate is found, the action is overridden toHOLD. - Save Plan: After generating a plan, it calls
ctx.save_plan()to record the new decision in memory, making it available for future checks.
This sequence diagram shows the Planner's interaction with the agent context (ctx) to manage memory.
Executor Agent: Trade Execution
The Executor Agent is the "hands" of the system. It subscribes to plan.ready events and executes the specified trades via the OKX WebSocket API.
Sources: apps/market-analyst/EXECUTOR.md
Trading Flow
The agent's logic is straightforward: listen for a plan, validate it, calculate the order size, and execute.
Safety and Configuration
The Executor Agent is designed with safety as a priority. Trading is disabled by default and must be explicitly enabled.
| Feature | Configuration | Default | Description |
|---|---|---|---|
| Safety Switch | enable_trading in loom.toml | false | Must be set to true to enable live trading. |
| Demo Mode | OKX_USE_DEMO in .env | 'true' | Uses the OKX demo/simulation account for safe testing. |
| Order Size Limits | min_order_size, max_order_size in loom.toml | 0.001, 0.01 | Defines the absolute minimum and maximum size for any single order. |
Sources: apps/market-analyst/EXECUTOR.md:19-27, 58-70
Confidence-Based Order Sizing
The size of a trade is not fixed; it scales with the confidence level provided by the Planner Agent. This strategy reduces risk by committing less capital to lower-confidence plans. The order size is calculated only for confidence levels between 50% and 100%.
The formula is: size = min_size + (max_size - min_size) * ((confidence - 0.5) * 2)
| Confidence | Sizing Factor | Example (0.001-0.01 BTC) |
|---|---|---|
| 50% | 0% (Min Size) | 0.001 BTC |
| 75% | 50% | 0.0055 BTC |
| 100% | 100% (Max Size) | 0.01 BTC |
Sources: apps/market-analyst/EXECUTOR.md:29-41
Data Payloads
The agent consumes a structured plan and produces a structured execution result.
Input Plan (plan.ready event):
{
"symbol": "BTC",
"action": "BUY",
"confidence": 0.85,
"reasoning": "Strong uptrend with bullish sentiment",
"sources": {
"trend": {},
"risk": {},
"sentiment": {}
}
}
Sources: apps/market-analyst/EXECUTOR.md:52-65
Output Result (execution.{symbol} event):
{
"symbol": "BTC",
"plan_action": "BUY",
"plan_confidence": 0.85,
"executed": true,
"status": "success",
"order_id": "123456789",
"order_size": 0.0082,
"message": "Order placed: BUY 0.0082 BTC-USDT",
"execution_time_ms": 1700000000000
}
Sources: apps/market-analyst/EXECUTOR.md:67-82
Conclusion
The Market Analyst system is a powerful demonstration of Loom's multi-agent capabilities. It effectively integrates real-time data streams, parallel analysis, LLM-based cognitive planning, and secure execution into a single, cohesive application. The clear separation of concerns among agents, the event-driven communication, and the built-in safety mechanisms make it a robust template for building sophisticated, long-running AI systems.
Sources: apps/market-analyst/README.md:3-15, README.md:58-82