GenAIHub
Back to Labs
Advanced

Confucius Code Agent

Download Lab Files

Build a code agent with scaffolding patterns from the paper "Confucius Code Agent". Implement hierarchical memory, persistent notes, and meta-agent loops.

Why Confucius?

AX (Agent Experience)

Hierarchical memory keeps context clean and stable

UX (User Experience)

Persistent Markdown notes for transparency

DX (Developer Experience)

Modular extensions for easy evolution

Meta-Agent (F4)

Build → Test → Improve configuration loop

Agent Architecture

graph TB META[Meta-Agent] --> ORCH[Orchestrator] ORCH --> THINK[Think] THINK --> ACT[Act] ACT --> OBS[Observe] OBS --> THINK subgraph Components WM[Working Memory] NOTES[Persistent Notes] TOOLS[Extensions/Tools] end ORCH --> WM ORCH --> NOTES ORCH --> TOOLS TOOLS --> S[search_files] TOOLS --> R[read_file] TOOLS --> W[write_file] TOOLS --> T[run_tests]

Step 1: Environment Setup

No API Key Required: Heuristic mode demonstrates scaffolding without LLM calls!

# 1. Navigate to project
cd Handson/Confucius-Agent

# 2. Run WebUI with Docker Compose
docker compose up

# 3. Open in browser
# http://127.0.0.1:7862

# Optional: With OpenAI
export OPENAI_API_KEY='your-key'
docker compose up
# Install Poetry
pip install poetry

# Install dependencies
cd Handson/Confucius-Agent
poetry install

# Run WebUI (Heuristic mode - no API key needed)
poetry run python webui.py

# Or run CLI demo
poetry run python mini_confucius.py

# With LLM providers
poetry install --with llm
export OPENAI_API_KEY='your-key'
poetry run python webui.py
# Install dependencies
pip install -r requirements.txt

# Run WebUI
python webui.py

# Or run CLI demo
python mini_confucius.py

# With OpenAI (optional)
export OPENAI_API_KEY='your-key'
python mini_confucius.py --provider openai

Key Concepts

WorkingMemory

Hierarchical state: goal, plan, key_facts, recent, compressed_history

Orchestrator

Think → Act → Observe loop with trajectory logging

Tools

Modular: search_files, read_file, write_file, run_tests

write_notes()

Generates Markdown notes with hindsight learning

The WorkingMemory is a dataclass that maintains hierarchical context for the agent.

from dataclasses import dataclass, field

@dataclass
class WorkingMemory:
    """Hierarchical context for clean AX (Agent Experience)."""
    
    goal: str                           # What we're trying to achieve
    plan: list[str] = field(default_factory=list)  # High-level steps
    key_facts: list[str] = field(default_factory=list)  # Important discoveries
    recent: list[str] = field(default_factory=list)  # Last N observations
    compressed_history: str = ""        # Summarized older context
    
    def maybe_compress(self, turns: list, max_recent: int = 5):
        """Compress older entries to prevent context overflow."""
        if len(self.recent) > max_recent:
            old = self.recent[:-max_recent]
            self.compressed_history += "\n".join(old)
            self.recent = self.recent[-max_recent:]

Tools are modular functions the agent can invoke to interact with the codebase.

class Tools:
    """Modular tool implementations (DX principle)."""
    
    def __init__(self, repo_root: Path):
        self.repo_root = repo_root
    
    def search_files(self, pattern: str) -> str:
        """Search for pattern in all Python files."""
        matches = []
        for path in self.repo_root.rglob("*.py"):
            content = path.read_text()
            if pattern in content:
                matches.append(str(path.relative_to(self.repo_root)))
        return "\n".join(matches) if matches else "No matches found"
    
    def read_file(self, path: str) -> str:
        """Read file contents."""
        return (self.repo_root / path).read_text()
    
    def write_file(self, path: str, content: str) -> str:
        """Write content to file."""
        (self.repo_root / path).write_text(content)
        return f"Wrote {len(content)} chars to {path}"
    
    def run_tests(self) -> str:
        """Execute tests and return results."""
        result = subprocess.run(
            ["python", "-m", "pytest", "-q"],
            cwd=self.repo_root,
            capture_output=True, text=True
        )
        return result.stdout + result.stderr

The Orchestrator runs the Think → Act → Observe loop and manages working memory.

class Orchestrator:
    """Core loop: Think → Act → Observe."""
    
    def __init__(self, llm, tools: Tools, wm: WorkingMemory):
        self.llm = llm
        self.tools = tools
        self.wm = wm
        self.turns = []
    
    def run(self, task: str, max_steps: int = 8) -> bool:
        """Execute agent loop until success or max steps."""
        last_obs = ""
        
        for step in range(max_steps):
            # Build prompt from working memory
            prompt = self._build_prompt(task) + f"\nLAST_OBS: {last_obs}"
            
            # Think: LLM generates thought + action
            response = self.llm.generate(prompt)
            thought, action = self._parse_action(response)
            
            # Act: Execute tool
            if action:
                tool_name, args = action
                result = self._invoke_tool(tool_name, args)
                last_obs = result.output
                
                # Update memory
                self.wm.recent.append(f"[{step}] {tool_name} → {last_obs[:200]}")
                self.wm.maybe_compress(self.turns)
                
                # Check success
                if "passed" in last_obs.lower():
                    return True
        
        return False

After each run, generate Markdown notes with trajectory and hindsight for user transparency.

def write_notes(self, title: str) -> Path:
    """Generate Markdown notes for UX transparency."""
    notes_dir = self.run_dir / "notes"
    notes_dir.mkdir(parents=True, exist_ok=True)
    
    timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
    path = notes_dir / f"{timestamp}-{title}.md"
    
    content = f"""# {title}
Date: {datetime.now().isoformat()}

## Goal
{self.wm.goal}

## Plan
{chr(10).join('- ' + p for p in self.wm.plan)}

## Key Events (Trajectory)
{chr(10).join('- **' + t.action.tool + '** → ' + ('OK' if t.action.ok else 'ERR') for t in self.turns)}

## Hindsight (Failures / Lessons)
{chr(10).join('- ' + f for f in self.wm.key_facts if 'FAILED' in f.upper())}
"""
    path.write_text(content)
    return path

Expected Output

🧠 Confucius Code Agent Demo
=============================

Setting up demo repository...
✓ Created demo_repo/calc.py (with bug: add subtracts instead)
✓ Created demo_repo/test_calc.py

Starting agent...
  Step 0: run_tests → FAILED test_calc.py: Expected 5 but got -1
  Step 1: search_files {'pattern': 'def add'} → calc.py
  Step 2: read_file {'path': 'calc.py'} → found bug: return a - b
  Step 3: write_file {'path': 'calc.py'} → fixed: return a + b
  Step 4: run_tests → PASSED

✓ Agent complete! Notes: demo_repo/.confucius/notes/20260110-demo.md

Learning Checklist

Quick Quiz

According to the Confucius paper, what is the key differentiator in code agents?

Correct! The paper argues that scaffolding — not just the LLM — is the key differentiator for real-world code agents.
Not quite. The paper emphasizes that scaffolding (orchestration, memory, tools) is the key differentiator.