# Project export: agentMail

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 12.0
- Tagline: Multi-agent simulation for email improvement hasn't been done at this scale. Email communication is genuinely hard, especially cross-cultural/hierarchical.
- Devpost: https://devpost.com/software/agentmail
- GitHub: https://github.com/NumerousJLs/agenticCarbonWarehouse
- Video: https://www.youtube.com/embed/qzGxK6Uiu04?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 1 GitHub contributor(s) — Joshua (2 commits)

## Devpost submission (written by the team)

### Inspiration

Email communication is a critical skill in professional environments, yet many people struggle to craft effective messages that achieve their intended goals. We were inspired by the challenge of improving email effectiveness through AI-powered analysis and the potential of multi-agent systems to provide comprehensive, nuanced feedback that goes beyond simple grammar checking. What We Learned Through this project, we gained deep insights into: Multi-Agent System Architecture: Building a distributed system where specialized agents collaborate to solve complex problems Fetch.ai Ecosystem: Leveraging uAgents framework, Agentverse platform, and ASI:One discovery layer for decentralized AI deployment Agent Communication Protocols: Implementing the Chat Protocol for seamless interaction between agents and users Claude API Integration: Utilizing Anthropic's Claude for sophisticated reasoning and analysis capabilities Consensus Mechanisms: Developing systems where multiple AI agents reach agreement on complex communication challenges How We Built It Our system consists of 12 specialized AI agents, each with distinct roles: Context Layer: Context Analyzer, Relationship Mapper, Culture Detector Simulation Layer: Recipient Persona, Sender Advocate, Devil's Advocate, Mediator Evaluation Layer: Tone Validator, Goal Alignment, Risk Assessment Output Layer: Feedback Synthesizer, Email Rewriter The architecture follows a layered approach where agents process emails through multiple perspectives, simulate recipient reactions, evaluate communication effectiveness, and synthesize actionable feedback. All agents are deployed on Fetch.ai's Agentverse platform with Chat Protocol integration for ASI:One discoverability. Challenges We Faced Technical Challenges: Resolving Chat Protocol verification issues with uAgents framework Implementing proper agent-to-agent communication without conflicts Managing 12 concurrent agent processes and ensuring reliable startup Integrating Claude API across all agents while maintaining performance Deployment Challenges: Setting up public endpoints through Cloudflared tunnels for Agentverse registration Ensuring all agents remain discoverable through ASI:One Managing environment variables and API keys across multiple agent instances Creating a seamless user experience despite the complexity of the underlying system System Design Challenges: Designing effective consensus mechanisms between agents with conflicting perspectives Balancing specialized agent roles with overall system coherence Creating meaningful agent personalities that provide diverse insights Ensuring the system scales from simple email analysis to complex communication scenarios The project demonstrates how emergent intelligence can arise from the interaction of specialized AI agents, creating a more sophisticated analysis than any single agent could provide alone.https://www.youtube.com/watch?v=qzGxK6Uiu04&pp=ygUKdGVzdCB2aWRlbw%3D%3D

## README (from the GitHub repository)

# Email Evaluation Agent System

An intelligent email evaluation system built with Fetch.ai's uAgents framework. Test how your emails will be received by different personality types and get expert coaching feedback to improve your communication.

## Overview

This project uses AI agents to simulate email recipients with different personalities and provides professional coaching feedback on how to improve your emails. The system helps you:

- **Test emails** against different personality types (angry CEO, chill coworker, stern professor, etc.)
- **Get realistic responses** showing how each personality would react
- **Receive expert coaching** on improving your email's effectiveness
- **Customize personalities** with moods, contexts, and traits
- **Deploy to Fetch.ai's agent network** for decentralized operation

## Agents
Relationship Mapper Agent
@ agent1qfkjef3wa8cv6l0ceq8edakv5vw7fwmehlswkjayztv9ue6za525vzl6lfe

Culture Detector Agent
@culture-detector-agent

Context Analyzer Agent
@context-analyzer-agent

## Architecture

```
┌─────────────────────────────────────────────────────────────┐
│                    Orchestrator (Local)                      │
│          Coordinates workflow and user interaction           │
└──────────────┬──────────────────────────────┬───────────────┘
               │                              │
               ▼                              ▼
     ┌─────────────────┐            ┌─────────────────┐
     │  Persona Agent  │            │   Coach Agent   │
     │   (Port 8001)   │            │   (Port 8002)   │
     │                 │            │                 │
     │ • Simulates     │            │ • Analyzes      │
     │   personalities │            │   emails        │
     │ • Generates     │            │ • Provides      │
     │   responses     │            │   feedback      │
     │ • Uses OpenAI   │            │ • Uses OpenAI   │
     └─────────────────┘            └─────────────────┘
```

## Features

### Built-in Personality Types

1. **Angry CEO** - Busy executive with no patience for poorly written emails
2. **Chill Coworker** - Laid-back colleague who values work-life balance
3. **Stern Professor** - Academic who expects precision and rigor
4. **Supportive Mentor** - Helpful guide focused on growth
5. **Anxious Client** - Worried about deadlines and outcomes
6. **Skeptical Investor** - Data-driven and scrutinizing

### Key Capabilities

- **Beautiful Web UI**: Modern Streamlit interface with real-time feedback
- **Batch Comparison**: Test emails against multiple personalities simultaneously
- **Dynamic Personality Management**: Create custom personalities on the fly
- **Mood & Context Updates**: Modify personality states without creating new agents
- **Comprehensive Feedback**: Get both persona reactions and expert coaching
- **Interactive CLI**: User-friendly command-line interface
- **Programmatic API**: Use as a library in your own applications
- **Fetch.ai Network Ready**: Deploy agents to the decentralized network

## Installation

### Prerequisites

- Python 3.8 or higher
- pip package manager
- OpenAI API key (optional - can run in demo mode without it)

### Setup

1. **Clone the repository**
   ```bash
   git clone <repository-url>
   cd customOrchestratedAgenticEmailEvals
   ```

2. **Install dependencies**
   ```bash
   pip install -r requirements.txt
   ```

3. **Configure environment**
   ```bash
   cp .env.example .env
   ```

   Edit `.env` and add your OpenAI API key:
   ```
   OPENAI_API_KEY=your_api_key_here
   ```

   **Don't have an API key?** No problem! The system automatically runs in demo mode with sample responses.

## Demo Mode vs Real Mode

The system automatically detects if you have a valid OpenAI API key:

### 🎭 Demo Mode (No API Key Needed)
- Uses pre-generated sample responses
- Perfect for testing the UI and workflow
- No API costs
- No signup required
- Great for understanding how the system works

**To use demo mode:**
- Don't set `OPENAI_API_KEY` in `.env`, OR
- Set `DEMO_MODE=true` in `.env`

### 🤖 Real Mode (Requires OpenAI API Key)
- Uses actual AI analysis via OpenAI
- Personalized responses for your emails
- Requires OpenAI account with credits
- More accurate and contextual feedback

**To use real mode:**
1. Sign up at [OpenAI Platform](https://platform.openai.com/)
2. Add payment method and credits ($5-10 is plenty to start)
3. Create an API key
4. Add to `.env`: `OPENAI_API_KEY=sk-...`

**Note:** If you see a quota error, visit [OpenAI Billing](https://platform.openai.com/account/billing) to add credits.

## Usage

### Running the System

The system works directly with OpenAI - no need to start separate agents!

You have three options to use the system:

**Option A: Web UI (Recommended)**

Start the web interface:

```bash
# macOS/Linux
./start_web.sh

# Windows
start_web.bat

# Or directly with streamlit
streamlit run web/app.py
```

Open your browser to `http://localhost:8501` and enjoy the beautiful interface!

No need to start agents separately - the web UI handles everything!

**Option B: Interactive CLI**

In a separate terminal:

```bash
python src/cli.py
```

Follow the interactive prompts to evaluate emails.

**Option C: Run Examples**

```bash
# Basic usage examples
python examples/basic_usage.py

# Custom personality examples
python examples/custom_personality.py
```

**Option D: Programmatic Usage**

Create your own Python script:

```python
import asyncio
from src.orchestrator import EmailEvaluationOrchestrator

async def main():
    orchestrator = EmailEvaluationOrchestrator()

    result = await orchestrator.evaluate_email(
        draft_email="Your email text here",
        personality_type="angry_ceo",
        sender_name="Your Name"
    )

    orchestrator.print_detailed_feedback(result)

asyncio.run(main())
```

## Example Output

```
==============================================================
EVALUATION RESULTS
==============================================================

📧 PERSONA RESPONSE (angry_ceo)
────────────────────────────────────────────────────────────
Emotional Tone: frustrated

Response:
John - I don't have time to "touch base." What challenges?
What's the new deadline? Give me specifics, not vague updates.

Key Concerns:
  • Lack of specific details
  • No clear action items
  • Vague language about challenges
  • Missing concrete timeline


🎓 COACH FEEDBACK
────────────────────────────────────────────────────────────

Overall Assessment:
The email is too vague and informal for an executive audience...

✅ Strengths:
  • Polite tone
  • Acknowledges there's an issue

⚠️  Areas for Improvement:
  • Lacks specific details about challenges
  • No proposed new deadline
  • No action items or next steps
  • Too casual for executive communication

🎯 Persona Alignment:
This email would frustrate an executive who values efficiency...

💡 Improvement Suggestions:
  1. Lead with the specific issue and proposed solution
  2. Provide concrete data and a new deadline
  3. Include clear action items
  4. Use more direct, professional language

📝 Suggested Revision:
Subject: Project Timeline Adjustment Required

[Improved email text...]
```

## Project Structure

```
customOrchestratedAgenticEmailEvals/
├── src/
│   ├── agents/
│   │   ├── persona_agent.py    # Personality simulation agent
│   │   └── coach_agent.py      # Coaching feedback agent
│   ├── models/
│   │   └── messages.py         # Message models for agent communication
│   ├── utils/
│   │   └── config.py           # Configuration and personality templates
│   ├── orchestrator.py         # Main orchestration logic
│   ├── main.py                 # Agent startup script
│   └── cli.py                  # Interactive command-line interface
├── web/
│   ├── app.py                  # Main Streamlit application
│   └── pages/
│       ├── evaluation.py       # Single email evaluation page
│       └── comparison.py       # Batch comparison page
├── examples/
│   ├── basic_usage

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 49 recognized source files, 265 KB.
- Anthropic (technology) — detected in the code
- FastAPI (technology) — detected in the code
- Flask (technology) — detected in the code
- HTML (language) — detected in the code
- OpenAI (technology) — detected in the code
- Python (language) — detected in the code
- Streamlit (technology) — detected in the code

## Codebase structure (from repository index)

### Files (56 of 56)

```
.env.example
.gitignore
agent1q0ht4y5v35_data.json
agent1qv4z59ueyn_data.json
agent1qwshhv4gf9_data.json
AGENTS_README.md
agents/analyzer.py
agents/evaluator.py
agents/output.py
AGENTVERSE_GUIDE.md
backend/app_12agent.py
backend/app.py
backend/index.html
chat_agent.py
CLEANUP_SUMMARY.md
deploy_to_agentverse.py
examples/basic_usage.py
examples/custom_personality.py
FIXES_SUMMARY.md
get_agent_addresses.py
get_my_agent_address.py
LOCAL_APP_README.md
pitch
proxy_agentverse.py
proxy.py
README.md
REAL_AGENTS_README.md
register_agent.py
REGISTRATION_SUCCESS.md
requirements.txt
src/__init__.py
src/agents/__init__.py
src/agents/coach_agent.py
src/agents/persona_agent.py
src/cli.py
src/main.py
src/models/__init__.py
src/models/messages.py
src/orchestrator_auto.py
src/orchestrator_demo.py
src/orchestrator_simple.py
src/orchestrator.py
src/utils/__init__.py
src/utils/config.py
start_all_agents.py
start_local_app.py
start_webapp.sh
test_agent_simple.py
test_analyzer_simple.py
test_email_analysis.py
test_orchestrator_simple.py
test_query_proxy.py
test_simple_query.py
TUNNEL_SETUP_SUCCESS.md
web_api.py
WEBAPP_README.md
```

### Dependencies

- requirements.txt: anthropic@>=0.18.0, fastapi@>=0.104.0, flask@>=3.0.0, flask-socketio@>=5.3.0, httpx@>=0.25.0, openai@>=1.0.0, pydantic@>=2.0.0, python-dotenv@>=1.0.0, python-socketio@>=5.10.0, streamlit@>=1.28.0, uagents@>=0.12.0, uvicorn@>=0.24.0

### Recent commits (newest first)

- Add link to Pitch presentation
- Update README.md
- Merge pull request #1 from NumerousJLs/baseline
- nice
- Update README.md
- Initial commit

## Key source files (fetched from GitHub, selected and truncated for size)

### REGISTRATION_SUCCESS.md

```markdown
# 🎉 Agent Registration Complete!

**Date:** 2025-10-26
**Status:** ✅ **LIVE AND REGISTERED**

---

## ✅ What's Running:

| Component | Status | Details |
|-----------|--------|---------|
| **Chat Protocol Agent** | ✅ Running | PID 23698 on port 8101 |
| **Cloudflare Tunnel** | ✅ Active | PID 24681 |
| **Public URL** | ✅ Live | https://lung-acid-motorola-buck.trycloudflare.com |
| **Almanac Registration** | ✅ Success | Registered on Fetch.ai network |
| **Agentverse Registration** | ✅ Success | Agent is discoverable |
| **Agent Status** | ✅ Active | Ready to receive messages |

---

## 🎯 Your Agent:

**Name:** Context_Analyzer
**Public Endpoint:** https://lung-acid-motorola-buck.trycloudflare.com
**Seed Phrase:** X283S43BCK+VMylTAUp/Cx4qXnR3/PQOfDQsYxbvuOk=

### Get Your Agent Address:

Go to https://agentverse.ai/ and:
1. Log in
2. Navigate to "Agents" tab
3. Find "Context_Analyzer"
4. Copy the agent address (starts with `agent1q...`)

---

## 🧪 Test Your Agent:

### Test Public Endpoint:
```bash
curl https://lung-acid-motorola-buck.trycloudflare.com/status
```

**Expected:**
```json
{"status":"ok","agent":"context_analyzer","type":"context_extraction","ready":true}
```

### Test Email Analysis:
```bash
curl -X POST https://lung-acid-motorola-buck.trycloudflare.com/chat \
  -H "Content-Type: application/json" \
  -d '{
    "email_text": "Hi team, can we push the deadline back a week?",
    "request_id": "test-001"
  }'
```

### Test via Agentverse:
1. Go to https://agentverse.ai/
2. Find your "Context_Analyzer" agent
3. Use the chat interface to send a test message
4. Your agent should respond with email analysis!

---

## 📊 What Was Registered:

```
Registration Log:
✅ Registering to Almanac... SUCCESS
✅ Registering to Agentverse... SUCCESS
✅ Setting agent as active... SUCCESS
```

Your agent is now:
- 🌐 **Discoverable** on the Fetch.ai network
- 🔄 **Ready** to receive messages
- 📡 **Active** on Agentverse
- 🤖 **Powered** by Claude for email analysis

---

## 🔧 Keep It Running:

### Current Processes:
```bash
# Agent process
PID: 23698
Command: python agents/layer1_context/context_analyzer_chat.py

# Tunnel process
PID: 24681
Command: cloudflared tunnel --url http://localhost:8101
```

### If You Need to Restart:

**Terminal 1 - Agent:**
```bash
source venv/bin/activate
python agents/layer1_context/context_analyzer_chat.py
```

**Terminal 2 - Tunnel:**
```bash
cloudflared tunnel --url http://localhost:8101
# Note: This will generate a NEW URL!
# You'll need to re-register with the new URL
```

### Check Status:
```bash
# Check if agent is responding
curl http://localhost:8101/status

# Check if tunnel is working
curl https://lung-acid-motorola-buck.trycloudflare.com/status

# See running processes
ps aux | grep -E "context_analyzer|cloudflared" | grep -v grep
```

---

## 📋 Next Steps:

### 1. Get Your Agent Address ⭐
Visit https://agentverse.ai/ and find your agent address (agent1q...)

### 2. Test on Agentverse
Use the Agentverse cha
[truncated — 2288 more characters]
```

### LOCAL_APP_README.md

```markdown
# Email Analysis System - Local Web Application

A real-time, multi-agent email analysis system with live agent communication visualization.

## Features

✨ **3-Agent Pipeline Architecture**
- **Analyzer Agent**: Performs 7 comprehensive analyses (context, relationships, culture, recipient simulation, sender advocacy, devil's advocate, mediation)
- **Evaluator Agent**: Evaluates tone, goal alignment, and risk assessment
- **Output Agent**: Generates actionable feedback and 3-tier email rewrites (Conservative, Recommended, Bold)

🔴 **Real-Time Communication**
- WebSocket-based live updates
- Watch agents communicate with each other in real-time
- See status updates, processing steps, and results as they happen

🎨 **Beautiful UI**
- Modern, responsive web interface
- Agent status visualization
- Live message log showing inter-agent communication
- Example emails to get started quickly

## Installation

1. **Install Dependencies**
```bash
pip install flask flask-socketio openai python-socketio
```

Or install from requirements.txt:
```bash
pip install -r requirements.txt
```

2. **Verify API Key**
The app uses ASI-1 API. The API key is already configured in `app.py`, but you can update it if needed:
```python
api_key='YOUR_API_KEY_HERE'
```

## Running the Application

### Option 1: Direct Python
```bash
python app.py
```

### Option 2: Using the start script
```bash
python start_local_app.py
```

The application will start on:
```
http://localhost:5000
```

## Usage

1. **Open your browser** to `http://localhost:5000`

2. **Enter email details**:
   - From (Sender): e.g., "John Smith (Manager)"
   - To (Recipient): e.g., "Jane Doe (Team Member)"
   - Email Content: The actual email text

3. **Click "Analyze Email"** or use one of the example emails

4. **Watch the magic happen**:
   - The **Analyzer** agent lights up and performs 7 analyses
   - Results are sent to the **Evaluator** agent
   - The **Evaluator** performs 3 evaluations and calculates a risk score
   - Results are sent to the **Output** agent
   - The **Output** agent generates feedback and rewrites
   - Final results appear with score, feedback, and 3 rewritten versions

5. **View Results**:
   - Overall score (0-10)
   - Detailed feedback with strengths, issues, and action items
   - Three rewritten versions: Conservative, Recommended, and Bold

## Agent Communication Pipeline

```
User Input
    ↓
┌─────────────┐
│  Analyzer   │  → Performs 7 analyses
└─────────────┘
    ↓ AnalysisResult
┌─────────────┐
│  Evaluator  │  → Evaluates tone, goals, risks
└─────────────┘
    ↓ EvaluationResult
┌─────────────┐
│   Output    │  → Generates feedback & rewrites
└─────────────┘
    ↓ FinalOutput
User sees results
```

## Features in Detail

### Analyzer Agent
- **Context Analysis**: Intent, tone, urgency, action items
- **Relationship Mapping**: Power dynamics, formality, trust
- **Culture Detection**: Communication styles, cultural sensitivities
- **Recipient Simulation**: How recipient w
[truncated — 2195 more characters]
```

### requirements.txt

```
# Fetch.ai uAgents Framework (Required for hackathon)
uagents>=0.12.0

# AI/LLM Integration (Required for hackathon)
anthropic>=0.18.0

# Legacy OpenAI support (optional for demo mode)
openai>=1.0.0

# Additional utilities
python-dotenv>=1.0.0
pydantic>=2.0.0
httpx>=0.25.0

# Web Backend
fastapi>=0.104.0
uvicorn>=0.24.0
flask>=3.0.0
flask-socketio>=5.3.0
python-socketio>=5.10.0

# Web UI
streamlit>=1.28.0

```

### src/main.py

```python
"""
Main entry point - Starts all agents using Bureau.
"""
from uagents import Bureau
import asyncio
import sys
import os

# Add parent directory to path so we can import from src
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

from src.agents.persona_agent import PersonaAgent
from src.agents.coach_agent import CoachAgent


def main():
    """Start all agents in a Bureau."""
    # Create agents
    persona_agent_instance = PersonaAgent(seed="persona_agent_seed_123")
    coach_agent_instance = CoachAgent(seed="coach_agent_seed_456")

    # Create bureau to run agents together
    bureau = Bureau(
        port=8000,
        endpoint=["http://localhost:8000/submit"]
    )

    # Add agents to bureau
    bureau.add(persona_agent_instance.agent)
    bureau.add(coach_agent_instance.agent)

    print("="*60)
    print("Starting Email Evaluation Agent System")
    print("="*60)
    print(f"\nPersona Agent: http://localhost:{persona_agent_instance.agent._port}")
    print(f"Coach Agent: http://localhost:{coach_agent_instance.agent._port}")
    print(f"\nAgents are ready to receive requests...")
    print("="*60 + "\n")

    # Run the bureau
    bureau.run()


if __name__ == "__main__":
    main()

```

### src/cli.py

```python
"""
Interactive CLI for email evaluation system.
"""
import asyncio
import sys
import os
from typing import Optional

# Add parent directory to path so we can import from src
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

from src.orchestrator_auto import EmailEvaluationOrchestrator
from src.utils.config import PERSONALITY_TEMPLATES


class EmailEvaluationCLI:
    """Interactive command-line interface for email evaluation."""

    def __init__(self):
        """Initialize the CLI."""
        self.orchestrator = EmailEvaluationOrchestrator()

    def print_header(self):
        """Print welcome header."""
        print("\n" + "="*60)
        print("📧 EMAIL EVALUATION SYSTEM")
        print("="*60)
        print("\nThis system helps you test how your emails will land")
        print("with different personality types and get coaching feedback.\n")

    def list_personalities(self):
        """List available personality types."""
        print("\n📋 Available Personality Types:")
        print("─"*60)
        for i, (key, description) in enumerate(PERSONALITY_TEMPLATES.items(), 1):
            # Get first line of description
            first_line = description.split('\n')[0]
            print(f"{i}. {key.replace('_', ' ').title()}")
            print(f"   {first_line[:70]}...")
        print()

    def get_multiline_input(self, prompt: str) -> str:
        """Get multiline input from user."""
        print(prompt)
        print("(Enter your email below. Type 'END' on a new line when done)")
        print("─"*60)

        lines = []
        while True:
            try:
                line = input()
                if line.strip().upper() == 'END':
                    break
                lines.append(line)
            except EOFError:
                break

        return '\n'.join(lines)

    async def evaluate_email_interactive(self):
        """Interactive email evaluation flow."""
        print("\n" + "─"*60)

        # Get email draft
        draft_email = self.get_multiline_input("\n📝 Enter your email draft:")

        if not draft_email.strip():
            print("\n❌ No email entered. Returning to menu.")
            return

        # Show personality options
        self.list_personalities()

        # Get personality choice
        personality_input = input("Enter personality type (name or number) or 'custom': ").strip()

        personality_type = None
        custom_description = None

        # Handle custom personality
        if personality_input.lower() == 'custom':
            personality_type = input("Enter personality name: ").strip()
            custom_description = self.get_multiline_input(
                "\n📝 Describe the personality:"
            )
        else:
            # Try to match by number or name
            try:
                idx = int(personality_input) - 1
                personality_type = list(PERSONALITY_TEMPLATES.keys())[idx]
            except (ValueError, IndexError):
                # Try to match by name
                normalized_input = personality_input.lower().replace(' ', '_')
                if normalized_input in PERSONALITY_TEMPLATES:
                    personality_type = normalized_input
                else:
                    print(f"\n❌ Unknown personality type: {personality_input}")
                    return

        # Get sender name
        sender_name = input("\nYour name (optional, press Enter to skip): ").strip() or "User"

        # Perform evaluation
        print("\n⏳ Evaluating your email...")
        print("This may take a moment as we consult with the agents...\n")

        result = await self.orchestrator.evaluate_email(
            draft_email=draft_email,
            personality_type=personality_type,
            personality_description=custom_description,
            sender_name=sender_name
        )

        # Display results
        self.orchestrator.print_detailed_feedback(result)

    async def update_personality_interactive(self):
        """Interactive personality update flow."""
        print("\n" + "─"*60)

        self.list_personalities()

        personality_type = input("Enter personality type to update: ").strip()
        mood = input("Current mood (optional): ").strip() or None
        context = input("Additional context (optional): ").strip() or None
        traits = input("Additional traits (optional): ").strip() or None

        await self.orchestrator.update_personality(
            personality_type=personality_type,
            mood=mood,
            context=context,
            additional_traits=traits
        )

        print("\n✅ Personality updated!")

    async def run(self):
        """Run the interactive CLI."""
        self.print_header()

        while True:
            print("\n" + "─"*60)
            print("MENU:")
            print("1. Evaluate an email")
            print("2. List personality types")
            print("3. Update personality mood/context")
            print("4. Exit")
            print("─"*60)

            choice = input("\nEnter your choice (1-4): ").strip()

            if choice == '1':
                await self.evaluate_email_interactive()
            elif choice == '2':
                self.list_personalities()
            elif choice == '3':
                await self.update_personality_interactive()
            elif choice == '4':
                print("\n👋 Goodbye!\n")
                break
            else:
                print("\n❌ Invalid choice. Please enter 1-4.")


async def main():
    """Main entry point for CLI."""
    cli = EmailEvaluationCLI()
    try:
        await cli.run()
    except KeyboardInterrupt:
        print("\n\n👋 Goodbye!\n")
        sys.exit(0)


if __name__ == "__main__":
    asyncio.run(main())

```

### backend/app.py

```python
"""
12-Agent Email Analysis System
4 Layers with 2 rounds of dialogue between each agent
"""
from flask import Flask, request, jsonify, send_from_directory
from flask_cors import CORS
from anthropic import Anthropic
import time
import threading
from typing import List, Dict
import os

# Initialize Anthropic
client = Anthropic(
    api_key='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',
)

# Initialize Flask
app = Flask(__name__, static_folder='.')
CORS(app)

# In-memory storage for messages
messages_store: List[Dict] = []
analysis_in_progress = False

def add_message(agent: str, msg_type: str, content: str):
    """Add a message to the store"""
    message = {
        "timestamp": time.time(),
        "agent": agent,
        "type": msg_type,
        "content": content
    }
    messages_store.append(message)
    print(f"[{agent}] [{msg_type}] {content[:100]}")
    return message

def agent_response(agent_name: str, system_prompt: str, user_prompt: str, context: str = "") -> str:
    """Get a single response from an agent"""
    full_prompt = f"{context}\n\n{user_prompt}" if context else user_prompt

    response = client.messages.create(
        model="claude-3-5-haiku-20241022",
        max_tokens=300,
        system=system_prompt,
        messages=[
            {"role": "user", "content": full_prompt}
        ]
    )
    content = str(response.content[0].text)
    add_message(agent_name, "message", content)
    time.sleep(0.3)
    return content

def two_agent_dialogue(agent1_name: str, agent1_prompt: str, agent2_name: str, agent2_prompt: str, topic: str, context: str = "") -> tuple:
    """Have 2 rounds of dialogue between two agents about the email"""

    # Round 1: Agent 1 speaks about the email
    response1 = agent_response(agent1_name, agent1_prompt, topic, context)
    time.sleep(0.3)

    # Round 1: Agent 2 responds - keeping email in context
    response2 = agent_response(
        agent2_name,
        agent2_prompt,
        f"{topic}\n\n{agent1_name} said: {response1}\n\nRespond to their point while analyzing the email:",
        context
    )
    time.sleep(0.3)

    # Round 2: Agent 1 responds back - keeping email in context
    response3 = agent_response(
        agent1_name,
        agent1_prompt,
        f"{topic}\n\n{agent2_name} said: {response2}\n\nRespond to their point while continuing to analyze the email:",
        context
    )
    time.sleep(0.3)

    # Round 2: Agent 2 final response - keeping email in context
    response4 = agent_response(
        agent2_name,
        agent2_prompt,
        f"{topic}\n\n{agent1_name} said: {response3}\n\nProvide your final analysis of the email, building on this dialogue:",
        context
    )
    time.sleep(0.3)

    return response1, response2, response3, response4

def run_analysis(email_text: str, sender_info: str, recipient_info: str):
    """Run the 12-agent analysis pipeline"""
    global analysis_in_progress
    analysis_in_progress = True

    try:
        messages_store.clear()

        # ========================================
        # LAYER 1: CONTEXT EXTRACTION (3 agents)
        # ========================================
        add_message("System", "status", "🔍 CONTEXT EXTRACTION LAYER")

        # Dialogue 1: Context Analyzer <-> Relationship Mapper
        add_message("System", "status", "Context Analyzer discussing with Relationship Mapper...")
        ctx1, ctx2, ctx3, ctx4 = two_agent_dialogue(
            "Context Analyzer",
            "You are a context extraction expert. Analyze the goal, tone, and urgency of emails. Engage in dialogue with the Relationship Mapper.",
            "Relationship Mapper",
            "You are a relationship dynamics expert. Infer power structures, rapport, and communication history. Engage in dialogue with the Context Analyzer.",
            f"Discuss this email:\n\nFrom: {sender_info}\nTo: {recipient_info}\n\nEmail:\n{email_text}"
        )
        context_analysis = ctx4
        relationship_analysis = ctx2
        time.sleep(0.5)

        # Dialogue 2: Relationship Mapper <-> Culture Detector
        add_message("System", "status", "Relationship Mapper discussing with Culture Detector...")
        rel1, cul1, rel2, cul2 = two_agent_dialogue(
            "Relationship Mapper",
            "You are a relationship dynamics expert. Discuss how relationship dynamics affect communication.",
            "Culture Detector",
            "You are a cultural communication expert. Identify cultural, regional, or professional norms that matter.",
            f"Building on previous context, discuss cultural aspects:\n\nEmail:\n{email_text}\n\nFrom: {sender_info}\nTo: {recipient_info}",
            f"Previous context: {context_analysis}"
        )
        culture_analysis = cul2
        time.sleep(0.5)

        # ========================================
        # LAYER 2: SIMULATION LAYER (4 agents)
        # ========================================
        add_message("System", "status", "🎭 SIMULATION LAYER")

        layer1_context = f"Context: {context_analysis}\nRelationship: {relationship_analysis}\nCulture: {culture_analysis}"

        # Dialogue 3: Recipient Persona <-> Sender Advocate
        add_message("System", "status", "Recipient Persona discussing with Sender Advocate...")
        rec1, sen1, rec2, sen2 = two_agent_dialogue(
            "Recipient Persona",
            "You are role-playing as the email recipient. React authentically and discuss your perspective.",
            "Sender Advocate",
            "You represent the sender's goals and interests. Advocate for what they're trying to achieve.",
            f"Discuss this email:\n{email_text}",
            layer1_context
        )
        recipient_response = rec2
        sender_advocacy = sen2
        time.sleep(0.5)

        # Dialogue 4: Devil's Advocate <-> Mediator
        add_message("System", "status", "Devil's Advocate discussing with M
[truncated — 4950 more characters]
```

### get_my_agent_address.py

```python
"""
Get the agent address from the seed phrase
"""
import os
from dotenv import load_dotenv

load_dotenv()

try:
    from uagents import Identity

    seed = os.getenv("AGENT_SEED_PHRASE")

    if seed:
        identity = Identity.from_seed(seed, 0)
        print("\n" + "="*70)
        print("🎯 YOUR AGENT ADDRESS")
        print("="*70)
        print(f"\nAgent Address: {identity.address}")
        print(f"\nThis is your agent's unique identifier on the Fetch.ai network!")
        print("\n📋 Use this address in your orchestrator:")
        print(f'   "context_analyzer": "{identity.address}"')
        print("\n" + "="*70 + "\n")
    else:
        print("❌ AGENT_SEED_PHRASE not found in .env")

except ImportError:
    print("❌ uagents not installed")
    print("   Try: pip install uagents")

```

### test_simple_query.py

```python
"""
Test script for simple query agent
"""
import asyncio
from uagents import Model
from uagents.query import query


class TestRequest(Model):
    message: str


class Response(Model):
    text: str


async def main():
    # Address of the simple test agent (will be printed when agent starts)
    # Replace this with the actual address printed by test_agent_simple.py
    test_agent_address = "agent1q..."  # UPDATE THIS

    print(f"Querying test agent at {test_agent_address}...")

    try:
        response = await query(
            destination=test_agent_address,
            message=TestRequest(message="Hello, test agent!"),
            timeout=15.0
        )

        print(f"✓ Got response from test agent, type: {type(response)}")

        if isinstance(response, Response):
            print(f"Response text: {response.text}")
        else:
            print(f"Unexpected response type: {response}")

    except Exception as e:
        print(f"✗ Error querying test agent: {e}")


if __name__ == "__main__":
    asyncio.run(main())

```

### test_agent_simple.py

```python
"""
Simple Test Agent - Basic Query Endpoint
"""
from uagents import Agent, Context, Model


class TestRequest(Model):
    message: str


class Response(Model):
    text: str


agent = Agent(
    name="test_agent_simple",
    seed="test_agent_simple_seed_2024",
    port=8005,
    endpoint=["http://localhost:8005/submit"],
)


@agent.on_event("startup")
async def startup(ctx: Context):
    ctx.logger.info(f"Starting up {agent.name}")
    ctx.logger.info(f"With address: {agent.address}")
    ctx.logger.info(f"And wallet address: {agent.wallet.address()}")

    print(f"\n{'='*60}")
    print(f"🧪 SIMPLE TEST AGENT")
    print(f"Name: {agent.name}")
    print(f"Address: {agent.address}")
    print(f"Port: 8005")
    print(f"{'='*60}\n")


@agent.on_query(model=TestRequest, replies={Response})
async def query_handler(ctx: Context, sender: str, _query: TestRequest):
    ctx.logger.info(f"Query received from {sender}")
    ctx.logger.info(f"Message: {_query.message}")
    try:
        # Simple echo response
        await ctx.send(sender, Response(text=f"success - received: {_query.message}"))
    except Exception as e:
        ctx.logger.error(f"Error: {e}")
        await ctx.send(sender, Response(text="fail"))


if __name__ == "__main__":
    print("Starting Simple Test Agent...")
    agent.run()

```

### get_agent_addresses.py

```python
"""
Get all agent addresses for the orchestrator
"""
from uagents import Agent

# Agent configurations (name, seed, port)
agents_config = [
    # Layer 1: Context Extraction
    ("context_analyzer", "context_analyzer_seed_123", 8101),
    ("relationship_mapper", "relationship_mapper_seed_456", 8102),
    ("culture_detector", "culture_detector_seed_789", 8103),

    # Layer 2: Simulation
    ("recipient_persona", "recipient_persona_seed_201", 8201),
    ("sender_advocate", "sender_advocate_seed_202", 8202),
    ("devils_advocate", "devils_advocate_seed_203", 8203),
    ("mediator", "mediator_seed_204", 8204),

    # Layer 3: Evaluation
    ("tone_validator", "tone_validator_seed_301", 8301),
    ("goal_alignment", "goal_alignment_seed_302", 8302),
    ("risk_assessor", "risk_assessor_seed_303", 8303),

    # Layer 4: Output
    ("feedback_synthesizer", "feedback_synthesizer_seed_401", 8401),
    ("email_rewriter", "email_rewriter_seed_402", 8402),
]

print("Agent Addresses:")
print("="*80)

agent_addresses = {}

for name, seed, port in agents_config:
    agent = Agent(name=name, seed=seed, port=port)
    address = agent.address
    agent_addresses[name] = address
    print(f"{name:25} -> {address}")

print("\n" + "="*80)
print("\nPython dict for orchestrator:")
print("="*80)
print("self.agents = {")
for name, address in agent_addresses.items():
    print(f'    "{name}": "{address}",')
print("}")

```

[39 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]