Architecture Overview
Agent Air is a modular TUI framework for building terminal-based agents powered by large language models. The architecture follows a layered design with clear separation of concerns, using message-driven communication between components.
Layered Architecture
The system is organized into four distinct layers, each with specific responsibilities:
┌─────────────────────────────────────────────────────────────────┐
│ TUI Application Layer │
│ App, Widgets, Commands, Key Handlers, Themes, Layouts │
└────────────────────────────┬────────────────────────────────────┘
│ Channels (UiMessage)
┌────────────────────────────▼────────────────────────────────────┐
│ Agent Infrastructure Layer │
│ AgentAir, InputRouter, Logger, Configuration │
└────────────────────────────┬────────────────────────────────────┘
│ Channels (ControllerInputPayload)
┌────────────────────────────▼────────────────────────────────────┐
│ Controller Layer │
│ LLMController, SessionManager, ToolExecutor, Registries │
└────────────────────────────┬────────────────────────────────────┘
│
┌────────────────────────────▼────────────────────────────────────┐
│ Client Layer │
│ LLMClient, Anthropic Provider, OpenAI Provider │
└─────────────────────────────────────────────────────────────────┘
TUI Application Layer
The topmost layer handles all user-facing concerns:
- App: The main application struct that runs the terminal event loop
- Widgets: Reusable UI components (ChatView, TextInput, StatusBar, panels)
- Commands: Slash command system for user actions
- Key Handlers: Keyboard input processing with customizable bindings
- Themes: Visual styling with 45+ built-in themes
- Layouts: Flexible widget arrangement templates
Agent Infrastructure Layer
This layer provides the orchestration and lifecycle management:
- AgentAir: Central struct that initializes and coordinates all components
- InputRouter: Routes messages from TUI to the controller
- Logger: Tracing-based logging infrastructure
- Configuration: YAML config loading and environment variable handling
Controller Layer
The controller layer manages LLM interactions and tool execution:
- LLMController: Main event loop processing six channels concurrently
- LLMSessionManager: Manages multiple concurrent LLM sessions
- ToolExecutor: Executes tools in parallel with result aggregation
- Registries: Tool, permission, and user interaction registries
Client Layer
The bottom layer handles HTTP communication with LLM providers:
- LLMClient: Provider-agnostic client interface
- Anthropic Provider: Claude API implementation with streaming
- OpenAI Provider: GPT API implementation with streaming
Component Interaction
The layers communicate through typed channels using Tokio’s MPSC primitives:
┌─────────────┐ ┌──────────────────┐
│ App │──── ToControllerTx ─────────▶│ InputRouter │
│ (TUI) │ │ │
│ │◀─── FromControllerRx ────────│ │
└─────────────┘ └────────┬─────────┘
│
▼
┌──────────────────┐
│ LLMController │
│ │
│ - from_llm_rx │
│ - input_rx │
│ - batch_rx │
│ - tool_rx │
│ - interact_rx │
│ - perm_rx │
└────────┬─────────┘
│
┌─────────────────────────────────┼─────────────────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ LLMSession │ │ ToolExecutor │ │ Registries │
│ │ │ │ │ │
│ - streaming │ │ - parallel │ │ - tools │
│ - compaction │ │ execution │ │ - perms │
└──────────────┘ └──────────────┘ │ - interact │
│ └──────────────┘
▼
┌──────────────┐
│ LLMClient │
│ │
│ - Anthropic │
│ - OpenAI │
└──────────────┘
Design Principles
Message-Driven Architecture
All inter-component communication uses typed message channels. This provides:
- Decoupling: Components only know about message types, not implementations
- Non-blocking: Async channels prevent one component from blocking another
- Backpressure: Bounded channel buffers (default 100) prevent memory exhaustion
Async-First Design
The entire system runs on Tokio’s async runtime:
- Single runtime instance created by AgentAir
- Background tasks spawned for controller, router, and event forwarding
CancellationTokenenables coordinated graceful shutdownblock_onbridges sync entry points to async internals
Trait-Based Extensibility
Core behaviors are defined as traits, allowing customization without modifying framework code:
| Trait | Purpose |
|---|---|
AgentConfig | Agent configuration (paths, prompts, name) |
Executable | Tool implementation |
Widget | TUI component |
SlashCommand | User command |
KeyHandler | Keyboard input processing |
LlmProvider | Custom LLM backend |
Compactor | Context window compaction strategy |
Shared State with Arc
Components that need shared access use Arc<T> for thread-safe reference counting:
controller: Arc<LLMController>
user_interaction_registry: Arc<UserInteractionRegistry>
permission_registry: Arc<PermissionRegistry>
tool_registry: Arc<ToolRegistry>
Interior mutability is handled with RwLock for read-heavy data (conversation history) and Mutex for exclusive access (channel receivers in select loops).
Data Flow Summary
- User Input: User types in TextInput widget
- Message Creation: App creates
ControllerInputPayloadwith content and turn ID - Routing: InputRouter forwards payload to LLMController
- Session Handling: Controller routes to appropriate LLMSession
- API Call: Session uses LLMClient to call provider API with streaming
- Response Processing: Streamed chunks emit
ControllerEventvia callback - Event Conversion: Events convert to
UiMessagefor TUI consumption - Display: App receives messages and updates ChatView
Tool execution follows a similar pattern but with additional steps for parallel execution and result aggregation before sending results back to the LLM.
Key Structs at Each Layer
| Layer | Key Structs |
|---|---|
| TUI | App, ChatView, TextInput, Theme, LayoutTemplate |
| Agent | AgentAir, InputRouter, Logger, LLMRegistry |
| Controller | LLMController, LLMSession, ToolExecutor, ToolRegistry |
| Client | LLMClient, AnthropicProvider, OpenAIProvider |
Next Steps
- Module Structure - Detailed breakdown of each module
- Message Flow - Step-by-step message routing
- Async Runtime - Tokio patterns and task management
