System Architecture
Directory Structure
Why Two Memory Files?
| File | Scope | Purpose |
|---|---|---|
journal.md | Per-session | Short-term memory for the current trading session |
learnings.md | Cross-session | Long-term memory that persists across all sessions |
Core Components
| File | Role |
|---|---|
engine.py | TickEngine — one instance per running agent. Runs tick loop, builds prompts, drives ACP sessions, captures tool calls, persists snapshots. |
strategy.py | Strategy + StrategyStore. Strategies live as agent.md files under trading_agents/{slug}/. |
journal.py | JournalManager — compact, human-readable per-session memory: summary, decisions, ticks, snapshots, executors. |
prompts.py | Builds per-tick prompt: system prompt + strategy + provider summaries + journal context + risk state. |
risk.py | RiskEngine + RiskLimits. Hard guardrails and permission callback that auto-approves tool calls only if they pass risk check. |
providers/ | Deterministic pre-tick data fetchers: executors.py and positions.py, both filtered by controller_id. |
agent.md
The strategy definition uses YAML frontmatter and Markdown body:Tick Loop
Each tick (TickEngine._tick) executes:
- Resolve API client for the configured server
- Run core providers —
executorsandpositions, filtered bycontroller_id == agent_id - Read journal context —
learnings.md, summary, last 3 decisions - Get risk state — exposure, drawdown, open count. If blocked, return without invoking LLM
- Build prompt via
build_tick_prompt(...), appending any user directives - Spawn ACP session with MCP servers (Hummingbot tools, market data, notifications)
- Persist — write
snapshot_N.md, append tick to journal, update summary
Providers
Providers fetch deterministic data before each tick:| Provider | Output |
|---|---|
executors | Active executors filtered by controller_id, with status and P&L |
positions | Held positions from closed executors, with breakeven and unrealized P&L |
data: Structured data for internal trackingsummary: Human-readable string included in the LLM prompt
Routines
Custom Python helpers in theroutines/ directory:
Inspecting Agent Activity
| Location | Content |
|---|---|
sessions/session_N/journal.md | Chronological summary, decisions, tick log |
sessions/session_N/snapshots/snapshot_K.md | Full tick: prompt, response, tool calls, risk state |
learnings.md | Lessons the agent chose to keep across sessions |
dry_runs/experiment_N.md | Dry-run / run-once results |
Injecting Information
You can manually add to the learnings file—the agent doesn’t know whether it wrote the entry or you did. This is useful for:- Pre-seeding knowledge before deployment
- Adding market context the agent can’t observe
- Correcting agent behavior based on your observations
trading_agents/my_strategy/learnings.md directly
Configs
Configs are agent-suggestible parameters that control how the agent operates. The agent can suggest changes based on learnings, but the user must approve. Inagent.md frontmatter:
config.yml:
Risk Limits
Risk Limits are user-only guardrails enforced by the Risk Engine before every action. The agent cannot modify or exceed these.| Limit | Default | Description |
|---|---|---|
max_position_size_quote | 500 | Maximum total position size |
max_single_order_quote | 100 | Maximum size per executor |
max_open_executors | 5 | Maximum simultaneous executors |
max_daily_loss_quote | 50 | Maximum daily loss before blocking |
max_drawdown_pct | 10 | Maximum drawdown percentage |
agent.md frontmatter:

