In an async, event-driven architecture like Agent Air, errors originate in different tasks and contexts. “Bubbling up” isn’t just about returning Result; it involves crossing channel boundaries and thread contexts.
The Propagation Path
- Origin: An error occurs (e.g.,
reqwestfails in theLLMClient). - Mapping: It is converted to a domain error (
LlmError::Network). - Controller: The
LLMControllercatches this error.- If it’s a tool error, it might be fed back to the LLM as a “Tool Result”.
- If it’s a fatal system error, it’s converted to a
ControllerEvent::Error.
- Event Loop: The main event loop receives the
ControllerEvent::Error. - TUI: The TUI converts this event into a
UiMessage::Error. - Display: The error is rendered in the
ChatView(often in red) or as a popup/status bar message.
Cross-Task Propagation
When a background task (like a tool execution) fails critically (panics or unrecoverable error), we use tokio::sync::oneshot or mpsc channels to signal the failure back to the main controller task, ensuring the agent doesn’t just silently hang.
