This document describes the system architecture, component design, and internal structure of FlexiAI Toolsmith.
- Architecture Overview
- Component Architecture
- Event-Oriented Execution Pipeline
- Channel System
- Provider Abstraction
- Tool Infrastructure
- Architecture Diagrams
FlexiAI Toolsmith follows a layered, modular architecture with clear separation of concerns:
┌─────────────────────────────────────────────────────────┐
│ Entry Points │
│ (app.py, chat.py) │
└────────────────────┬────────────────────────────────────┘
│
┌────────────────────▼────────────────────────────────────┐
│ Controllers │
│ (CLIChatController, QuartChatController) │
└────────────────────┬────────────────────────────────────┘
│
┌────────────────────▼────────────────────────────────────┐
│ Core Handlers │
│ (RunThreadManager, EventHandler, ToolExecutor) │
└────────────────────┬────────────────────────────────────┘
│
┌────────────────────▼────────────────────────────────────┐
│ Event System │
│ (EventBus, SSE Manager, Channels) │
└────────────────────┬────────────────────────────────────┘
│
┌────────────────────▼────────────────────────────────────┐
│ Tool Infrastructure │
│ (ToolsRegistry, ToolsManager, Infrastructure) │
└─────────────────────────────────────────────────────────┘
app.py (Web Application)
- Quart web server initialization
- Blueprint registration for chat routes
- User session management
- Form submission handling
chat.py (CLI Application)
- CLI chat loop initialization
- Interactive terminal interface
- Direct user input/output
Controllers orchestrate the interaction between users and the AI assistant:
CLIChatController
- Manages CLI chat sessions
- Handles user input from terminal
- Publishes events to CLI channel
- Formats assistant responses for terminal output
QuartChatController
- Manages web chat sessions via Quart
- Handles HTTP requests and SSE streaming
- Publishes events to Quart channel
- Manages user sessions and thread persistence
RunThreadManager
- Manages OpenAI Assistant API threads and runs
- Handles message creation and retrieval
- Coordinates tool call execution
- Manages streaming responses
Interface Contract:
- get_or_create_thread(assistant_id: str, user_id: Optional[str]) -> str # Returns thread_id
- add_message_to_thread(thread_id: str, message: str, user_id: Optional[str]) -> str # Returns message_id
- start_run(assistant_id: str, thread_id: str) -> Any # Returns async stream of events
- submit_tool_outputs(thread_id: str, run_id: str, tool_outputs: Any) -> Any # Submits tool resultsToolExecutor
- Executes tool calls from assistants
- Routes tool invocations to appropriate infrastructure
- Validates tool parameters
- Returns structured results
- Note: ToolExecutor is invoked by EventHandler when tool calls are required during
_handle_requires_action.
Interface Contract:
- execute(tool_name: str, **arguments: Any) -> Any # Executes tool by name with arguments
- prepare_tool_output(tool_call: Any, result: Any, success: bool) -> Dict[str, Any] # Formats outputNote: Tools are retrieved from ToolsRegistry via agent_actions dict passed to constructor.
EventHandler
- Coordinates event publishing
- Manages event routing to channels
- Handles event transformation
- Provides event filtering capabilities
Interface Contract:
- start_run(assistant_id: str, thread_id: str, user_id: Optional[str]) -> None # Starts assistant run
- _handle_message_delta(event_data: Any, thread_id: str) -> None # Handles message deltas
- _handle_requires_action(run_data: Any, thread_id: str) -> None # Handles tool callsChannels (BaseChannel interface)
- Abstract base for all output channels
- Provides consistent interface for event publishing
Interface Contract:
- publish_event(event: Any) -> None # Publishes event to channel (abstract method)Note: Channel activation is managed by ChannelManager, not individual channels.
flexiai/config/models.py
- Pydantic models for all environment variables
- Provider-specific settings (OpenAI, Azure, DeepSeek, Qwen, GitHub)
- General application settings
- Validation and type checking
flexiai/config/client_settings.py
- Aggregates all configuration models
- Provides unified configuration access
- Validates provider credentials
FlexiAI Toolsmith uses an event-oriented pipeline (not a traditional event-driven architecture) for structured communication between components. This pipeline runs within a single process and does not require an external message broker.
User Input
↓
Controller → Creates MessageEvent
↓
EventHandler → Routes events through internal dispatching (EventDispatcher / MultiChannelPublisher)
↓
RunThreadManager → Processes with Assistant API
↓
ToolExecutor → Executes tool calls (if needed, invoked by EventHandler)
↓
EventHandler → Publishes ResponseEvent to channels
↓
Channel → Streams to User (CLI/Web/Redis)
Note: EventBus exists as an internal utility, but primary event routing is handled by EventHandler and MultiChannelPublisher.
Message Events
- User messages
- Assistant responses
- Tool call requests
- Tool call results
System Events
- Thread creation
- Run status updates
- Error notifications
- Connection events
The EventBus is an internal utility for component communication. Primary event routing is handled by:
- EventHandler - Orchestrates event processing and tool calls
- EventDispatcher - Routes events to appropriate handlers within EventHandler
- MultiChannelPublisher - Publishes events to configured output channels (CLI/Quart/Redis)
Channels are terminal consumers of events and do not participate in execution or routing logic. They serve as output mechanisms for assistant responses:
- Terminal-based output
- Formatted text responses
- Interactive input handling
- Real-time streaming via terminal updates
- Server-Sent Events (SSE) streaming
- WebSocket-like real-time updates
- HTTP request/response handling
- Session management
- Pub/sub messaging
- Distributed communication
- Multi-instance coordination
- Event persistence (optional)
- Dynamic channel activation based on
ACTIVE_CHANNELS - Channel lifecycle management
- Event routing to active channels
- Channel-specific configuration
FlexiAI Toolsmith supports multiple LLM providers through a unified interface.
Provider Support & Code Paths:
- Assistant API features (tool calls, streaming, threads) are gated by provider support
- Code paths branch in
flexiai/credentials/credentials.pybased onCREDENTIAL_TYPE - OpenAI and Azure OpenAI: Full Assistant API support with
OpenAI-Beta: assistants=v2header - DeepSeek, Qwen, GitHub Azure Inference: Chat completions only, no Assistant API endpoints
- See
flexiai/credentials/credentials.pyfor implementation details
flexiai/credentials/credentials.py
- Strategy pattern for provider-specific client creation
- Validates provider credentials
- Creates appropriate client instances
- Handles provider-specific configuration
OpenAI
- Full Assistant API support
- Threads, runs, tool calls, streaming
- Organization and project support
Azure OpenAI
- Full Assistant API support
- Azure-specific endpoint configuration
- API version management
DeepSeek / Qwen / GitHub Azure Inference
- Chat completions only
- OpenAI SDK compatibility
- No Assistant API support
Providers are selected via CREDENTIAL_TYPE environment variable:
openai→ OpenAI clientazure→ Azure OpenAI clientdeepseek→ DeepSeek clientqwen→ Qwen clientgithub_models→ GitHub Azure Inference client
Maps tool names to callable functions:
- Core tools (context storage, agent coordination)
- Infrastructure tools (CSV, spreadsheets)
- Business tools (subscriber management, security audit)
- Custom tools (user-defined)
Implements core system operations:
- Context persistence (RAG)
- Agent coordination
- External API integration (YouTube)
- Tool dispatching
CSV Infrastructure
- File operations
- Data validation
- Transformation utilities
- Query operations
Spreadsheet Infrastructure
- Excel/OpenPyXL operations
- Sheet management
- Formula execution
- Chart generation
- Data analysis
Security Audit Infrastructure
- Network reconnaissance
- Process detection
- Port scanning
- System updates
- Defense actions
See TOOLING.md for detailed tool documentation.
Description: End-to-end message workflow showing how user messages flow through the system from input (CLI or web) through controllers, event handlers, assistant API processing, optional tool execution, and real-time streaming responses back to users.
Key Flow:
- User sends message via CLI or web interface
- Controller (CLIChatController or QuartChatController) receives input
- MessageEvent created and published to event system
- RunThreadManager processes with Assistant API
- EventHandler manages streaming events and tool calls
- ToolExecutor handles tool calls (if required)
- ResponseEvent published to channels (CLI/Quart/Redis)
- Real-time streaming responses delivered to user
Description: Detailed workflow showing how tool calls are routed through the tool registry, executed by infrastructure modules, and returned to the assistant in a structured form.
Key Flow:
- Assistant generates tool call request
- ToolExecutor receives tool call
- ToolsRegistry maps tool name to function
- Infrastructure module executes operation
- Structured result returned to ToolExecutor
- Result formatted and sent to Assistant API
- Assistant processes result and generates response
- Clear separation between orchestration, tools, channels, and providers
- Pluggable tool architecture
- Independent channel implementations
- Easy addition of new tools via registry
- Custom channel implementations
- Provider abstraction for new LLM services
- Single responsibility per component
- Explicit interfaces between layers
- Comprehensive logging and error handling
- Async/await throughout
- Streaming for real-time responses
- Efficient event routing
Assistant API – OpenAI's API for managing assistants, threads, runs, and tool calls. Provides structured interaction with LLM models.
Run – A single execution of an assistant on a thread. Contains messages, tool calls, and status.
Thread – A conversation context in the Assistant API. Contains messages and runs for a specific user.
ToolCall – A request from an assistant to execute a function. Contains tool name and parameters.
MessageDeltaEvent – An incremental update to a message as it's being generated. Used for streaming responses.
SSE (Server-Sent Events) – HTTP protocol for real-time streaming from server to client. Used for web interface.
- WORKFLOW.md – Detailed execution workflows
- TOOLING.md – Tool capabilities and usage
- FILE_MAPPING.md – Internal file reference
- ENV_SETUP.md – Environment configuration
- ../SECURITY.md – Security guidelines

