Architecture¶
High-Level Overview¶
graph TB
subgraph CLI["CLI / TUI"]
cli["retrai run"]
tui["retrai tui"]
end
subgraph Server["Web Server"]
api["FastAPI"]
ws["WebSocket"]
vue["Vue 3 Frontend"]
end
subgraph Core["Agent Core"]
graph["LangGraph StateGraph"]
plan["Plan Node"]
act["Act Node"]
eval["Evaluate Node"]
hitl["Human Check"]
end
subgraph Infra["Infrastructure"]
bus["AsyncEventBus"]
llm["LiteLLM"]
tools["Tool Registry"]
goals["Goal Registry"]
mem["Agent Memory"]
end
cli --> graph
tui --> graph
api --> graph
graph --> plan
plan --> act
act --> eval
eval --> hitl
plan --> llm
act --> tools
eval --> goals
graph --> bus
bus --> ws
bus --> tui
bus --> cli
graph --> mem
style graph fill:#7c3aed,color:#fff
style bus fill:#2563eb,color:#fff
style llm fill:#059669,color:#fff
Package Structure¶
retrai/
├── agent/ # LangGraph agent
│ ├── graph.py # StateGraph definition
│ ├── state.py # AgentState TypedDict
│ ├── routers.py # Edge routing logic
│ └── nodes/ # Graph nodes
│ ├── plan.py # LLM reasoning
│ ├── act.py # Tool execution
│ ├── evaluate.py # Goal checking
│ ├── reflect.py # Strategy extraction
│ └── human_check.py
├── cli/ # Typer CLI
│ ├── app.py # Commands
│ ├── commands.py # Subcommands
│ └── runners.py # Run orchestration
├── events/ # Event system
│ ├── bus.py # AsyncEventBus
│ └── types.py # AgentEvent dataclass
├── goals/ # Goal definitions
│ ├── base.py # GoalBase ABC
│ ├── registry.py # Goal registry
│ ├── detector.py # Auto-detection
│ ├── pytest_goal.py
│ ├── pyright_goal.py
│ ├── bun_goal.py
│ ├── sql_goal.py
│ ├── perf_goal.py
│ ├── ml_goal.py
│ ├── ai_eval.py
│ └── ...
├── llm/ # LLM integration
│ └── factory.py # get_llm() → ChatLiteLLM
├── memory/ # Persistent memory
│ ├── store.py # JSON-based store
│ └── extractor.py # Strategy extraction
├── tools/ # Agent tools
│ ├── base.py # BaseTool ABC
│ ├── builtins.py # Tool registry
│ ├── bash_exec.py
│ ├── file_read.py
│ ├── file_write.py
│ ├── grep_search.py
│ └── ...
├── server/ # FastAPI server
│ ├── app.py # ASGI app
│ ├── run_manager.py # Run lifecycle
│ └── routes/
│ ├── runs.py # REST endpoints
│ └── ws.py # WebSocket
├── tui/ # Textual TUI
│ ├── app.py # Main app
│ ├── widgets.py # Custom widgets
│ ├── screens.py # Modal screens
│ ├── wizard.py # Setup wizard
│ └── styles.tcss # Stylesheet
├── swarm/ # Multi-agent orchestration
│ ├── orchestrator.py
│ ├── worker.py
│ ├── roles.py
│ └── decomposer.py
├── benchmark.py # Model comparison
├── watcher.py # File watcher
├── pipeline/ # Pipeline mode
├── review.py # Code review
├── history.py # Run history
├── config.py # RunConfig
└── safety/ # Guardrails
└── guardrails.py
Key Design Decisions¶
LangGraph StateGraph¶
The agent is a cyclic graph with conditional edges, not a linear pipeline. This means:
- The agent can loop as many times as needed
- Routing is determined at runtime by the state
- HITL interrupts are first-class via
interrupt() - State is checkpointed automatically via
MemorySaver
LiteLLM for Multi-Model¶
Instead of binding to one provider, retrAI uses LiteLLM which provides a unified interface to 100+ LLM providers. Switching models is a single CLI flag.
Event-Driven Architecture¶
All agent activity flows through the AsyncEventBus — a pub/sub system using asyncio.Queue per subscriber. This decouples the agent from its consumers (CLI, TUI, WebSocket) and allows multiple frontends to observe the same run simultaneously.
Tool Registry¶
Tools are registered via a decorator pattern:
from retrai.tools.base import BaseTool
class MyTool(BaseTool):
name = "my_tool"
description = "Does something useful"
async def execute(self, **kwargs) -> str:
return "result"
The registry is extensible via Python entry points for plugin discovery.