DEV Community

Cover image for In-depth Analysis of Litho's Multi-Agent Collaborative Architecture and ReAct Reasoning Mechanism
Sopaco
Sopaco

Posted on

In-depth Analysis of Litho's Multi-Agent Collaborative Architecture and ReAct Reasoning Mechanism

Imagine a "technical detective team" composed of experts from various fields, each possessing unique expertise, yet able to collaborate perfectly to uncover the deep secrets of a codebase. This is the charm of Litho's multi-agent system.
Project Open Source Address: https://github.com/sopaco/deepwiki-rs

Litho

Introduction: When AI Learns Team Collaboration

In traditional AI applications, we often see individual models "fighting alone." But Litho adopts a completely different approach - it builds a "virtual technical team" composed of multiple specialized agents, each with clear responsibilities, yet able to complete complex code analysis tasks together through sophisticated collaboration mechanisms.

This multi-agent architecture not only improves the depth and breadth of analysis but, more importantly, it simulates the working methods of human technical teams, giving AI true "team collaboration" capabilities.

Chapter 1: Design Philosophy of Multi-Agent Systems

1.1 Evolution from "Individual Combat" to "Team Operations"

Before Litho appeared, most code analysis tools adopted single-model methods. This approach is like having a generalist engineer analyze the entire system alone - while it might be completed, it's inefficient and prone to missing details.

Litho's multi-agent design philosophy can be understood through a vivid metaphor:

Traditional Single Model: Like having an architect simultaneously responsible for structural design, water and electricity planning, interior decoration, and landscape design.

Litho Multi-Agent System: More like a professional design institute, with structural engineers, water and electricity engineers, interior designers, and landscape designers each performing their duties, completing projects together through coordination meetings.

1.2 The Art of Agent Division of Labor

Litho's agent division of labor embodies the principle of "professionals do professional work":

The Art of Agent Division of Labor

Each agent is like a technical expert with specific expertise:

  • System Context Expert: Responsible for understanding the project's positioning in the larger ecosystem
  • Domain Module Detective: Skilled at identifying business domain and functional module divisions
  • Architecture Analyst: Focused on technical architecture and design pattern analysis
  • Workflow Reconstructor: Good at restoring business processes and execution paths
  • Core Module Insight Expert: Deeply analyzes details of key technical implementations
  • Boundary Interface Analyst: Defines interaction boundaries between the system and the external world

Chapter 2: ReAct Executor - The Agent's "Thinking Engine"

2.1 Thought-Action-Observation Cycle: AI's "Think-Act-Observe" Pattern

ReAct (Reasoning + Acting) is the core reasoning mechanism of Litho agents. This mechanism simulates the thinking process of human experts:

Human Expert Thinking Process:

  1. Thinking: I need to understand the implementation details of this function
  2. Action: Open the corresponding source code file for reading
  3. Observation: Discover that this function handles user authentication logic
  4. Re-thinking: Now I need to understand its call relationships
  5. Re-action: Search for places that call this function
  6. Re-observation: Discover it's called in the login process

Litho Agent's ReAct Cycle:

// Simplified implementation of ReAct cycle
pub struct ReActExecutor {
    max_iterations: usize,      // Maximum iteration count
    verbose: bool,              // Detailed logging
    enable_summary_reasoning: bool, // Enable summary reasoning
}

impl ReActExecutor {
    pub async fn execute_reasoning_loop(&self, agent: &dyn Agent, initial_prompt: &str) -> Result<ReActResponse> {
        let mut chat_history = Vec::new();
        let mut tool_calls_history = Vec::new();

        // Start multi-round reasoning loop
        for iteration in 0..self.max_iterations {
            // Thinking phase: LLM generates reasoning results
            let thought = agent.generate_thought(&chat_history).await?;

            // Determine if action is needed
            if thought.requires_action() {
                // Action phase: Execute tool calls
                let action_result = self.execute_tool_call(&thought.action).await?;
                tool_calls_history.push(action_result.clone());

                // Observation phase: Add results to context
                chat_history.push(Message::observation(&action_result));
            } else {
                // Generate final answer
                return Ok(ReActResponse::success(thought.content, iteration));
            }
        }

        // Handling when maximum iterations reached
        if self.enable_summary_reasoning {
            // Enable summary reasoning fallback mechanism
            self.summarize_and_reason(&chat_history, &tool_calls_history).await
        } else {
            Err(anyhow!("Maximum iterations reached, task not completed"))
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

2.2 Practical Case: How an Agent Analyzes a Login Function

Let's follow a specific example to see how the system context expert analyzes a web application's login function:

Practical Case: How an Agent Analyzes a Login Function

Chapter 3: Collaboration Mechanism of Agent Teams

3.1 ResearchOrchestrator: The Technical Team's "Project Manager"

ResearchOrchestrator plays the role of project manager in the multi-agent system, responsible for coordinating the workflow of various experts:

// Coordination work of research orchestrator
pub struct ResearchOrchestrator {
    agents: HashMap<String, Box<dyn StepForwardAgent>>,
    context: Arc<GeneratorContext>,
}

impl ResearchOrchestrator {
    pub async fn execute_research_pipeline(&self) -> Result<()> {
        info!("๐ŸŽฏ Starting multi-agent collaborative analysis task...");

        // Phase 1: System Context Analysis (Macro Positioning)
        let system_context = self.execute_agent("system_context").await?;
        info!("๐ŸŒ System context analysis completed: identified {} external systems", system_context.external_systems.len());

        // Phase 2: Domain Module Detection (Business Division)
        let domain_modules = self.execute_agent("domain_modules").await?;
        info!("๐Ÿข Domain module detection completed: discovered {} core business domains", domain_modules.domains.len());

        // Phase 3: Architecture Analysis (Technical Design)
        let architecture = self.execute_agent("architecture").await?;
        info!("๐Ÿ—๏ธ Architecture analysis completed: generated {} architecture components", architecture.components.len());

        // Phase 4: Workflow Reconstruction (Business Processes)
        let workflows = self.execute_agent("workflow").await?;
        info!("๐Ÿ”ง Workflow reconstruction completed: restored {} core processes", workflows.flows.len());

        // Phase 5: Core Module Insight (Technical Depth)
        let key_insights = self.execute_agent("key_insights").await?;
        info!("๐Ÿ” Core module insight completed: deeply analyzed {} key modules", key_insights.modules.len());

        // Phase 6: Boundary Analysis (Integration Interfaces)
        let boundaries = self.execute_agent("boundaries").await?;
        info!("๐ŸŒ Boundary analysis completed: identified {} integration interfaces", boundaries.interfaces.len());

        info!("๐ŸŽ‰ Multi-agent collaborative analysis task successfully completed!");
        Ok(())
    }

    async fn execute_agent(&self, agent_name: &str) -> Result<ResearchResult> {
        if let Some(agent) = self.agents.get(agent_name) {
            info!("๐Ÿš€ Starting {} agent...", agent_name);
            agent.execute(&mut self.context.clone()).await
        } else {
            Err(anyhow!("Agent not found: {}", agent_name))
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

3.2 Memory Context: The Team's "Shared Whiteboard"

The key to multi-agent collaboration lies in information sharing. Litho implements a "shared whiteboard" mechanism through GeneratorContext:

Memory Context: The Team's

This "shared whiteboard" mechanism ensures:

  • Information Consistency: All agents analyze based on the same data foundation
  • Avoid Duplicate Work: Subsequent agents can directly use predecessors' analysis results
  • Context Coherence: Analysis process has complete traceability chain

Chapter 4: Tool Calling Mechanism - Agent's "Sensory Extension"

4.1 File Exploration Tool: Agent's "Eyes"

The file_explorer tool gives agents the ability to browse the file system:

// Intelligent application of file exploration tool
pub struct AgentToolFileExplorer {
    project_path: PathBuf,
    ignored_dirs: Vec<String>,
    max_depth: usize,
}

impl AgentToolFileExplorer {
    pub async fn intelligent_exploration(&self, agent_type: &str) -> Result<ExplorationResult> {
        match agent_type {
            "system_context" => {
                // System context expert focuses on top-level structure and entry points
                self.explore_top_level().await
            }
            "domain_modules" => {
                // Domain module detective focuses on business-related directories
                self.explore_business_directories().await
            }
            "architecture" => {
                // Architecture analyst focuses on technical infrastructure
                self.explore_technical_infrastructure().await
            }
            _ => self.general_exploration().await
        }
    }

    async fn explore_top_level(&self) -> Result<ExplorationResult> {
        // Focus on: main files, configuration files, documentation files
        let important_files = vec!["main.rs", "Cargo.toml", "README.md", "src/lib.rs"];
        self.find_and_analyze_files(&important_files).await
    }

    async fn explore_business_directories(&self) -> Result<ExplorationResult> {
        // Focus on: business logic related directories
        let business_dirs = vec!["src/services/", "src/models/", "src/controllers/"];
        self.analyze_directory_structure(&business_dirs).await
    }
}
Enter fullscreen mode Exit fullscreen mode

4.2 File Reading Tool: Agent's "Deep Reading Ability"

The file_reader tool enables agents to deeply understand code content:

// Intelligent file reading strategy
pub struct IntelligentFileReader {
    context: GeneratorContext,
    compression_threshold: usize,
}

impl IntelligentFileReader {
    pub async fn read_for_analysis(&self, file_path: &str, analysis_purpose: &str) -> Result<FileContent> {
        let raw_content = self.read_file(file_path).await?;

        // Intelligently process content based on analysis purpose
        match analysis_purpose {
            "architecture" => self.extract_architecture_info(&raw_content),
            "workflow" => self.extract_workflow_patterns(&raw_content),
            "domain" => self.identify_domain_concepts(&raw_content),
            _ => Ok(raw_content)
        }
    }

    fn extract_architecture_info(&self, content: &str) -> Result<FileContent> {
        // Focus on: module declarations, import statements, public interfaces
        let architecture_patterns = vec![
            r"pub\s+mod\s+(\w+)",
            r"use\s+[\w:]+\s*;",
            r"pub\s+fn\s+(\w+)",
            r"pub\s+struct\s+(\w+)",
        ];
        self.extract_patterns(content, &architecture_patterns)
    }

    fn extract_workflow_patterns(&self, content: &str) -> Result<FileContent> {
        // Focus on: function call chains, control flow, error handling
        let workflow_patterns = vec![
            r"\.await\?",
            r"match\s+.*\{",
            r"if\s+let\s+.*=.*\{",
            r"->\s+Result<.*>",
        ];
        self.extract_patterns(content, &workflow_patterns)
    }
}
Enter fullscreen mode Exit fullscreen mode

5.1 Project Background: E-commerce Microservices Architecture

Let's see through a real case how Litho's multi-agent system collaborates to analyze a complex e-commerce microservices project:

Project Structure:

  • User Service (user-service): Handles user registration, login, personal information
  • Order Service (order-service): Handles order placement, payment, refunds
  • Product Service (product-service): Manages product information, inventory
  • Payment Service (payment-service): Integrates third-party payment platforms

5.2 Multi-Agent Collaboration Process

Multi-Agent Collaboration Process

5.3 Specific Contributions of Each Agent

System Context Expert's Discoveries:

  • Project Type: B2C e-commerce platform
  • Target Users: End consumers and merchants
  • External Systems: Payment gateways, logistics systems, SMS services

Domain Module Detective's Division:

  • User Management Domain: Registration, login, permission control
  • Product Management Domain: Categories, inventory, search
  • Order Processing Domain: Order placement, payment, logistics
  • Payment Service Domain: Third-party payment integration

Architecture Analyst's Insights:

  • Architecture Style: Microservices architecture, inter-service HTTP communication
  • Technology Stack: Rust backend + React frontend + PostgreSQL database
  • Deployment Method: Docker containerized deployment

Chapter 6: Deep Technical Implementation Analysis

6.1 StepForwardAgent Trait: Unified Interface for Agents

Litho defines unified behavior specifications for all agents through the StepForwardAgent trait:

// Unified behavior specification for agents
pub trait StepForwardAgent: Send + Sync {
    /// Execute agent's main task
    async fn execute(&self, context: &mut GeneratorContext) -> Result<()>;

    /// Get prompt template
    fn prompt_template(&self) -> String;

    /// Define data dependency configuration
    fn data_config(&self) -> DataConfig;

    /// Post-processing hook function
    fn post_process(&self, _result: &mut ResearchResult) -> Result<()> {
        Ok(()) // Default empty implementation
    }

    /// Validate execution results
    fn validate_result(&self, result: &ResearchResult) -> Result<()>;
}

// Specific agent implementation
pub struct SystemContextResearcher {
    llm_client: LLMClient,
    config: ResearchConfig,
}

impl StepForwardAgent for SystemContextResearcher {
    async fn execute(&self, context: &mut GeneratorContext) -> Result<()> {
        info!("๐Ÿ” System context expert starting work...");

        // 1. Prepare analysis materials
        let research_materials = self.prepare_materials(context).await?;

        // 2. Build prompts
        let prompt = self.build_prompt(&research_materials);

        // 3. Execute ReAct reasoning
        let result = self.llm_client.react_execute(&prompt, &self.config).await?;

        // 4. Parse and store results
        let system_context = self.parse_result(&result)?;
        context.store_to_memory("research", "system_context", system_context)?;

        info!("โœ… System context analysis completed");
        Ok(())
    }

    fn prompt_template(&self) -> String {
        include_str!("prompts/system_context_sys.tpl").to_string()
    }

    fn data_config(&self) -> DataConfig {
        DataConfig {
            required: vec!["preprocess.project_structure"],
            optional: vec!["preprocess.original_document"],
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

6.2 Error Handling and Fault Tolerance Mechanisms

The stability of the multi-agent system relies on comprehensive error handling mechanisms:

// Intelligent fault-tolerant processing
pub struct FaultTolerantOrchestrator {
    orchestrator: ResearchOrchestrator,
    max_retries: usize,
    fallback_strategies: HashMap<String, Box<dyn FallbackStrategy>>,
}

impl FaultTolerantOrchestrator {
    pub async fn execute_with_fallback(&self) -> Result<ResearchResults> {
        let mut results = ResearchResults::new();
        let mut failed_agents = Vec::new();

        for agent_name in self.orchestrator.agent_names() {
            match self.execute_agent_with_retry(agent_name).await {
                Ok(result) => {
                    results.insert(agent_name, result);
                }
                Err(e) => {
                    warn!("โŒ {} agent execution failed: {}", agent_name, e);
                    failed_agents.push(agent_name);

                    // Try using fallback strategy
                    if let Some(fallback) = self.fallback_strategies.get(agent_name) {
                        if let Ok(fallback_result) = fallback.execute().await {
                            results.insert(agent_name, fallback_result);
                            info!("๐Ÿ”„ Completed {} analysis using fallback strategy", agent_name);
                        }
                    }
                }
            }
        }

        if !failed_agents.is_empty() {
            warn!("โš ๏ธ The following agents failed analysis: {:?}", failed_agents);
        }

        Ok(results)
    }

    async fn execute_agent_with_retry(&self, agent_name: &str) -> Result<ResearchResult> {
        for attempt in 0..self.max_retries {
            match self.orchestrator.execute_agent(agent_name).await {
                Ok(result) => return Ok(result),
                Err(e) if attempt < self.max_retries - 1 => {
                    warn!("๐Ÿ”„ {} retry attempt {}...", agent_name, attempt + 1);
                    tokio::time::sleep(Duration::from_secs(1 << attempt)).await; // Exponential backoff
                }
                Err(e) => return Err(e),
            }
        }
        unreachable!()
    }
}
Enter fullscreen mode Exit fullscreen mode

Chapter 7: Technical Advantages of Multi-Agent Architecture

7.1 Advantages Compared to Single-Model Architecture

Analysis Depth:

  • Single Model: General discussion, lacks professional depth
  • Multi-Agent: Expert-level analysis in each domain

Error Tolerance:

  • Single Model: One error causes entire analysis to fail
  • Multi-Agent: Partial failure doesn't affect overall results

Scalability:

  • Single Model: Extension requires retraining entire model
  • Multi-Agent: Can easily add new expert agents

7.2 Performance Optimization Strategies

Litho's multi-agent system optimizes performance through various strategies:

  1. Parallel Execution: Independent agents can run in parallel
  2. Cache Reuse: Analysis results are cached for subsequent use
  3. Incremental Updates: Only reanalyze changed parts
  4. Resource Scheduling: Intelligently allocate computing resources to agents

Conclusion: New Paradigm of Intelligent Collaboration

Litho's multi-agent collaborative architecture represents a completely new AI application paradigm - no longer making a single model "smarter," but making multiple specialized models "collaborate better."

This architecture's success proves: In complex problem domains, the power of team collaboration far exceeds individual heroism. Just as in human society, a team composed of experts from various fields can often solve complex problems that individual geniuses cannot.

Litho's multi-agent system not only brings revolutionary breakthroughs to the code analysis field but, more importantly, provides an excellent example of how AI can better simulate and enhance human collaboration capabilities.

In upcoming articles, we will continue to explore other technical highlights of Litho, including the unique advantages of Rust language in high-performance AI applications, and the design wisdom of plugin architecture.


This article is the second in the Litho project technical analysis series. Litho's open source address: https://github.com/sopaco/deepwiki-rs

Next Preview: Exploring the Technical Advantages of Rust Language in High-Performance AI Applications - Revealing why Litho chose Rust as the implementation language and Rust's unique value in the AI field.

Top comments (0)