# Synqed Workspace Guide 🚀

A comprehensive guide to multi-agent collaboration with **Workspace** and **OrchestratedWorkspace**.

---

## Table of Contents
- [Overview](#overview)
- [Quick Start](#quick-start)
- [Workspace vs OrchestratedWorkspace](#workspace-vs-orchestratedworkspace)
- [Basic Workspace](#basic-workspace)
- [Orchestrated Workspace](#orchestrated-workspace)
- [Collaboration Modes](#collaboration-modes)
- [Real-World Examples](#real-world-examples)
- [API Reference](#api-reference)
- [Best Practices](#best-practices)

---

## Overview

Synqed provides two powerful tools for multi-agent collaboration:

| Feature | **Workspace** | **OrchestratedWorkspace** |
|---------|--------------|---------------------------|
| **Purpose** | Basic collaborative environment | Intelligent task orchestration |
| **Setup** | Manual agent coordination | Automatic task decomposition |
| **Agent Selection** | You choose which agents to use | LLM selects best agents per subtask |
| **Task Planning** | You define the workflow | LLM breaks tasks into subtasks |
| **Collaboration** | Agents work in parallel | Multi-turn turn-taking dialogue |
| **Best For** | Simple coordination, direct control | Complex tasks, intelligent routing |

---

## Quick Start

### Installation

```bash
pip install synqed anthropic python-dotenv
```

### Environment Setup

Create a `.env` file:

```bash
ANTHROPIC_API_KEY='your-api-key-here'
```

### 30-Second Example

```python
import synqed
import asyncio
from synqed import CollaborationMode

async def main():
    # Create agents
    writer = synqed.Agent(name="Writer", description="Creative writer", 
                         skills=["writing"], executor=your_logic_func)
    editor = synqed.Agent(name="Editor", description="Content editor",
                         skills=["editing"], executor=your_logic_func)
    
    # Start servers
    writer_server = synqed.AgentServer(writer, port=8001)
    editor_server = synqed.AgentServer(editor, port=8002)
    await writer_server.start_background()
    await editor_server.start_background()
    
    # Create orchestrator
    orchestrator = synqed.Orchestrator(
        provider=synqed.LLMProvider.ANTHROPIC,
        api_key="your-key",
        model="claude-sonnet-4-5"
    )
    
    # Create orchestrated workspace with turn-taking dialogue
    workspace = synqed.OrchestratedWorkspace(
        orchestrator=orchestrator,
        enable_agent_discussion=True,          # Enable turn-taking
        collaboration_mode=CollaborationMode.ADVERSARIAL,  # Force conflict
        display_messages=True
    )
    
    # Register agents
    workspace.register_agent(writer)
    workspace.register_agent(editor)
    
    # Execute task - watch agents iterate back and forth!
    result = await workspace.execute_task(
        "Write a short story about AI, then edit it for clarity"
    )
    
    print(f"Final Result: {result.final_result}")

asyncio.run(main())
```

---

## Workspace vs OrchestratedWorkspace

### When to Use **Workspace**

✅ You want **direct control** over agent interactions  
✅ Simple tasks with clear delegation  
✅ You know which agents should do what  
✅ Need a basic collaboration sandbox  

**Example Use Case:** Three agents collaborating on a shared document where you explicitly assign roles.

### When to Use **OrchestratedWorkspace**

✅ Complex tasks that need **automatic decomposition**  
✅ You want the **LLM to plan** the workflow  
✅ Need **turn-taking adversarial dialogue**  
✅ Want agents to **iterate and challenge** each other  
✅ Tasks with dependencies and subtasks  

**Example Use Case:** "Research microservices, write implementation code, and create documentation" - let the orchestrator break this down and coordinate turn-taking dialogue.

---

## Basic Workspace

### Core Concept

`Workspace` is a **collaborative sandbox** where agents can:
- Share files and artifacts
- Send messages to each other
- Track progress together
- Maintain shared state

### Basic Example

```python
import synqed
import asyncio

async def main():
    # Create workspace
    workspace = synqed.Workspace(
        name="Recipe Planning",
        description="Plan meals and create shopping lists",
        display_messages=True  # Real-time colored output
    )
    
    # Add agents
    workspace.add_agent(recipe_agent)
    workspace.add_agent(shopping_agent)
    workspace.add_agent(nutrition_agent)
    
    # Start workspace
    await workspace.start()
    
    # Collaborate - all agents work in parallel
    result = await workspace.collaborate(
        "Plan a week of healthy dinners and create a shopping list"
    )
    
    # Get artifacts created during collaboration
    artifacts = workspace.get_artifacts()
    for artifact in artifacts:
        print(f"Artifact: {artifact.name}")
        print(f"Content: {artifact.content}")
    
    # Get conversation history
    messages = workspace.get_messages()
    
    # Clean up
    await workspace.close()

asyncio.run(main())
```

### Workspace Features

#### 1. Direct Messaging

```python
# Send message to specific agent
response = await workspace.send_message_to_agent(
    participant_id="agent-123",
    message="Can you review this recipe?"
)

# Broadcast to all agents
responses = await workspace.broadcast_message(
    "Team meeting at 3pm!"
)
```

#### 2. Artifact Management

```python
# Add artifact
artifact_id = workspace.add_artifact(
    name="shopping_list.txt",
    artifact_type="file",
    content="Eggs, Milk, Bread",
    created_by="shopping_agent"
)

# Get artifacts
all_artifacts = workspace.get_artifacts()
file_artifacts = workspace.get_artifacts(artifact_type="file")
```

#### 3. Shared State

```python
# Set shared data
workspace.set_shared_state("budget", 100)
workspace.set_shared_state("dietary_restrictions", ["vegetarian"])

# Get shared data
budget = workspace.get_shared_state("budget")
all_state = workspace.get_all_shared_state()
```

#### 4. Message Callbacks

```python
async def on_new_message(message):
    print(f"{message.sender_name}: {message.content}")

# Register callback
workspace.on_message(on_new_message)
```

---

## Orchestrated Workspace

### Core Concept

`OrchestratedWorkspace` is an **intelligent project manager** that:
1. **Analyzes** your complex task
2. **Breaks it down** into subtasks
3. **Selects** the best agents for each subtask
4. **Coordinates** turn-taking adversarial dialogue
5. **Synthesizes** the final result

### Complete Example

```python
import synqed
import asyncio
from synqed import CollaborationMode

async def main():
    # Step 1: Create orchestrator
    orchestrator = synqed.Orchestrator(
        provider=synqed.LLMProvider.ANTHROPIC,
        api_key="your-api-key",
        model="claude-sonnet-4-5",
        temperature=0.7
    )
    
    # Step 2: Create orchestrated workspace
    orchestrated = synqed.OrchestratedWorkspace(
        orchestrator=orchestrator,
        enable_agent_discussion=True,      # Enable turn-taking dialogue
        collaboration_mode=CollaborationMode.ADVERSARIAL,  # Force conflict
        display_messages=True,             # Watch in real-time
        workspace_persistence=True,        # Save workspace state
        max_parallel_subtasks=3            # Max parallel execution
    )
    
    # Step 3: Register specialized agents
    orchestrated.register_agent(research_agent)  # Good at research
    orchestrated.register_agent(coding_agent)    # Good at writing code
    orchestrated.register_agent(writing_agent)   # Good at documentation
    orchestrated.register_agent(review_agent)    # Good at quality checks
    
    # Step 4: Execute complex task - watch turn-taking dialogue!
    result = await orchestrated.execute_task(
        """Research best practices for microservices architecture,
        write implementation code in Python, create comprehensive
        documentation, and provide a security review."""
    )
    
    # Step 5: Check results
    if result.success:
        print(f"✅ Success!")
        print(f"\nFinal Result:\n{result.final_result}")
        
        # See how task was broken down
        print(f"\nSubtasks executed: {len(result.plan.subtasks)}")
        for subtask in result.plan.subtasks:
            print(f"  - {subtask.description} → {subtask.assigned_agent_name}")
        
        # Individual subtask results
        for subtask_id, subtask_result in result.subtask_results.items():
            print(f"\n{subtask_id}: {subtask_result[:200]}...")
        
        # Full conversation history
        print(f"\nTotal messages: {len(result.workspace_messages)}")
    else:
        print(f"❌ Failed: {result.error}")

asyncio.run(main())
```

### How It Works (NEW Turn-Taking Mode)

The `OrchestratedWorkspace` follows a **turn-taking dialogue workflow**:

```
1. PLANNING PHASE
   └─ LLM analyzes task
   └─ Breaks into subtasks
   └─ Assigns to best agents
   └─ Determines dependencies

2. WORKSPACE SETUP
   └─ Creates temporary workspace
   └─ Adds required agents
   └─ Sets up shared context

3. TURN-TAKING DIALOGUE (if enable_agent_discussion=True)
   
   └─ Orchestrator announces TURN ORDER
   └─ Designates who goes FIRST
   
   Turn 1: First agent presents thinking
   Turn 2: Second agent RESPONDS to first agent
   Turn 3: First agent RESPONDS to second agent
   Turn 4: Second agent RESPONDS to first agent
   ... (up to 6 turns or until satisfied)
   
   Each turn:
   • Agent sees full conversation history
   • Responds directly to previous agent
   • Challenges assumptions, identifies flaws
   • NOT eager to please - maximizes quality
   • Iterates until both satisfied
   
   Final: Each agent produces deliverable

4. SYNTHESIS
   └─ LLM combines all results
   └─ Creates cohesive final answer

5. CLEANUP
   └─ Stores artifacts
   └─ Exports workspace (if enabled)
   └─ Returns result
```

---

## Collaboration Modes

### 🤝 COLLABORATIVE (Supportive)

**Best for:** Teams building on each other's ideas

**How it works:**
- Agents take turns sharing ideas
- Give **supportive, constructive** feedback
- Build synergy and find common ground
- Refine work collaboratively

**Example:**
```python
workspace = synqed.OrchestratedWorkspace(
    orchestrator=orchestrator,
    collaboration_mode=CollaborationMode.COLLABORATIVE
)
```

**Use when:** You want harmonious teamwork, consensus-building, and agents that complement each other.

---

### ⚔️ ADVERSARIAL (Turn-Taking Dialogue - NEW!)

**Best for:** Critical decisions, robust solutions, avoiding groupthink

**How it works (NEW Turn-Taking Mode):**
1. **Orchestrator designates who goes FIRST**
2. First agent presents their thinking to the workspace
3. Second agent **directly responds** to first agent's output (not a parallel proposal!)
4. Agents **iterate back and forth**, taking turns (up to 6 turns default)
5. Each agent challenges assumptions and pushes for quality
6. Agents are **NOT eager to please** - they maximize quality through conflict
7. Continue until both satisfied or max turns reached
8. Each agent produces final deliverable incorporating insights from dialogue

**Key Difference from Old Mode:**
- **OLD**: Agents proposed → reviewed in parallel → refined once (led to duplicate outputs)
- **NEW**: Sequential turn-taking dialogue where each response builds on the previous

**Example:**
```python
workspace = synqed.OrchestratedWorkspace(
    orchestrator=orchestrator,
    enable_agent_discussion=True,  # Must be True for dialogue
    collaboration_mode=CollaborationMode.ADVERSARIAL  # Turn-taking dialogue
)
```

**Key Features:**
- ✅ **Sequential, not parallel**: Agents respond to each other in real-time
- ✅ **No duplicate outputs**: Each agent builds on previous messages
- ✅ **True iteration**: Multiple rounds of challenge and response (up to 6 turns)
- ✅ **Quality focus**: Agents push back on weak thinking, don't compromise prematurely
- ✅ **Context awareness**: Each turn includes full conversation history

**Adversarial Prompts Push Agents To:**
- "CHALLENGE weak points in the previous response"
- "Identify flaws, gaps, or unstated assumptions"
- "Do NOT be polite at the expense of quality"
- "You are NOT trying to agree - you're trying to maximize quality"
- "Surface problems NOW through conflict, not later through failure"

**Use when:** You need robust solutions, want to surface hidden problems early, or are making critical architecture decisions.

**Why it works:** Forces diversity of thought through iterative dialogue, prevents premature consensus, identifies edge cases through adversarial pressure. Each turn builds on the previous one, creating emergent solutions better than any single viewpoint.

---

### 🔷 INDEPENDENT (No Interaction)

**Best for:** Parallel tasks that don't need coordination

**How it works:**
- Agents execute subtasks in parallel
- No discussion or feedback
- Fast, independent execution

**Example:**
```python
workspace = synqed.OrchestratedWorkspace(
    orchestrator=orchestrator,
    enable_agent_discussion=False  # Independent mode
)
```

**Use when:** Subtasks are truly independent, speed is critical, or agents don't need to coordinate.

---

## Real-World Examples

### Example 1: Basic Workspace - Recipe Team

```python
async def recipe_collaboration():
    workspace = synqed.Workspace(
        name="Recipe Team",
        display_messages=True
    )
    
    workspace.add_agent(chef_agent)
    workspace.add_agent(nutritionist_agent)
    workspace.add_agent(shopper_agent)
    
    await workspace.start()
    
    # All agents work together
    result = await workspace.collaborate(
        "Create a healthy, budget-friendly dinner for 4"
    )
    
    # Get the shopping list artifact
    shopping_lists = workspace.get_artifacts(artifact_type="shopping_list")
    
    await workspace.close()
    return result
```

### Example 2: Orchestrated - Turn-Taking Story Writing

```python
async def collaborative_writing():
    orchestrated = synqed.OrchestratedWorkspace(
        orchestrator=orchestrator,
        collaboration_mode=CollaborationMode.ADVERSARIAL,
        enable_agent_discussion=True  # Turn-taking dialogue
    )
    
    orchestrated.register_agent(writer_agent)
    orchestrated.register_agent(editor_agent)
    
    result = await orchestrated.execute_task(
        "Write an opening scene about a robot learning to paint"
    )
    
    # Agents will:
    # Turn 1: Writer presents story concept
    # Turn 2: Editor responds with critique
    # Turn 3: Writer refines based on feedback
    # Turn 4: Editor pushes for improvements
    # ... iterate until satisfied ...
    # Final: Both produce polished deliverable
    
    return result
```

### Example 3: Orchestrated - Software Development

```python
async def software_project():
    orchestrated = synqed.OrchestratedWorkspace(
        orchestrator=orchestrator,
        collaboration_mode=CollaborationMode.ADVERSARIAL
    )
    
    orchestrated.register_agent(architect_agent)
    orchestrated.register_agent(backend_dev_agent)
    orchestrated.register_agent(frontend_dev_agent)
    orchestrated.register_agent(qa_agent)
    orchestrated.register_agent(security_agent)
    
    result = await orchestrated.execute_task(
        """Design and implement a REST API for user authentication.
        Include security best practices, comprehensive tests, and documentation."""
    )
    
    # The orchestrator automatically:
    # 1. Has architect design the API
    # 2. Has backend dev implement it (turn-taking with architect)
    # 3. Has security agent review (adversarial dialogue)
    # 4. Has QA write tests
    # 5. Has frontend dev create usage docs
    # 6. Synthesizes everything into final deliverable
    
    return result
```

---

## API Reference

### Workspace

#### Constructor

```python
workspace = synqed.Workspace(
    name: str,                          # Workspace name
    description: str,                   # Description of purpose
    workspace_id: str = None,          # Optional custom ID
    workspace_dir: Path = None,        # Optional custom directory
    auto_cleanup: bool = True,         # Clean up on close
    enable_persistence: bool = False,  # Save state to disk
    max_messages: int = 1000,          # Max messages to retain
    message_retention_hours: int = 24, # Message retention time
    display_messages: bool = True      # Real-time display
)
```

#### Methods

```python
# Agent management
workspace.add_agent(agent, agent_url=None, role="agent", metadata=None)
workspace.remove_agent(participant_id)
workspace.list_participants()

# Lifecycle
await workspace.start()
await workspace.pause()
await workspace.resume()
await workspace.complete()
await workspace.close()

# Collaboration
await workspace.collaborate(task, orchestrator=None, timeout=300.0)
await workspace.send_message_to_agent(participant_id, message)
await workspace.broadcast_message(message, sender_id="system", sender_name="System")

# Artifacts
workspace.add_artifact(name, artifact_type, content, created_by, metadata=None)
workspace.get_artifact(artifact_id)
workspace.get_artifacts(artifact_type=None, created_by=None)

# State
workspace.set_shared_state(key, value)
workspace.get_shared_state(key, default=None)
workspace.get_all_shared_state()

# Messages
workspace.get_messages(message_type=None, sender_id=None, limit=None)
workspace.on_message(callback)

# Export
await workspace.export_workspace(export_path=None)
```

### OrchestratedWorkspace

#### Constructor

```python
orchestrated = synqed.OrchestratedWorkspace(
    orchestrator: Orchestrator,                      # Required: orchestrator instance
    enable_agent_discussion: bool = True,           # Enable turn-taking dialogue
    collaboration_mode: CollaborationMode = ADVERSARIAL,  # Collaboration style
    workspace_persistence: bool = False,            # Save workspace state
    max_parallel_subtasks: int = 3,                # Parallel execution limit
    message_callback: Callable = None,              # Custom message handler
    display_messages: bool = False,                 # Built-in display
    display_verbose: bool = False                   # Verbose output
)
```

#### Methods

```python
# Agent registration
orchestrated.register_agent(agent)

# Execution
result = await orchestrated.execute_task(
    task: str,
    context: dict = None,
    workspace_name: str = None
)
```

#### ExecutionResult

```python
result.success          # bool: Whether execution succeeded
result.final_result     # str: Synthesized final answer
result.plan             # ExecutionPlan: Task breakdown
result.subtask_results  # dict: Individual subtask results
result.workspace_messages  # list: Full message history (dialogue turns)
result.workspace_id     # str: Workspace ID
result.error           # str: Error message if failed
result.metadata        # dict: Additional metadata (dialogue_turns, etc.)
```

---

## Best Practices

### ✅ DO

1. **Use OrchestratedWorkspace with ADVERSARIAL mode for critical tasks**
   - Turn-taking dialogue prevents groupthink
   - Iterative challenge-response produces better results

2. **Enable display_messages during development**
   - Watch agents iterate back and forth in real-time
   - See how dialogue evolves over multiple turns

3. **Choose the right collaboration mode**
   - ADVERSARIAL for critical decisions (default for quality)
   - COLLABORATIVE for creative teamwork
   - INDEPENDENT for parallel tasks

4. **Register agents with clear, distinct skills**
   - Helps orchestrator make smart assignments
   - Creates productive tension in adversarial dialogue

5. **Review the dialogue history**
   - Check `result.workspace_messages` to see turn-by-turn conversation
   - Learn how agents challenged each other

### ❌ DON'T

1. **Don't use OrchestratedWorkspace for simple tasks**
   - Overhead of planning + dialogue isn't worth it
   - Use basic Workspace or direct Agent calls

2. **Don't disable discussion for complex tasks**
   - `enable_agent_discussion=False` skips turn-taking
   - You lose the iterative refinement benefit

3. **Don't expect agents to agree immediately**
   - Adversarial mode is designed for conflict
   - Quality emerges through iteration, not instant consensus

4. **Don't forget to close workspaces**
   - Always `await workspace.close()`
   - Or use async context manager

---

## Understanding Turn-Taking Dialogue

### What Makes It Different?

**OLD parallel approach:**
```
Agent 1: Here's my proposal [generated independently]
Agent 2: Here's my proposal [generated independently]
Result: Often similar or identical outputs
```

**NEW turn-taking approach:**
```
Orchestrator: "Agent 1 goes FIRST"
Turn 1 - Agent 1: "Here's my approach: X, Y, Z"
Turn 2 - Agent 2: "I see problems with X. Here's why..."
Turn 3 - Agent 1: "Valid point on X, but Y addresses that because..."
Turn 4 - Agent 2: "Fair, but what about edge case W?"
Turn 5 - Agent 1: "Good catch. Let me refine..."
Turn 6 - Agent 2: "Now this is solid. Final thoughts..."
Final: Both produce deliverables incorporating dialogue insights
```

### Dialogue Flow

```
┌─────────────────────────────────────────┐
│   Orchestrator: Turn Order Announced   │
│   "Agent 1 goes FIRST"                  │
└─────────────────────────────────────────┘
                   ↓
┌─────────────────────────────────────────┐
│ Turn 1: Agent 1 presents thinking       │
│ "Here's my approach..."                 │
└─────────────────────────────────────────┘
                   ↓
┌─────────────────────────────────────────┐
│ Turn 2: Agent 2 responds to Agent 1     │
│ "I challenge X because..."              │
└─────────────────────────────────────────┘
                   ↓
┌─────────────────────────────────────────┐
│ Turn 3: Agent 1 responds to Agent 2     │
│ "Valid, but consider..."                │
└─────────────────────────────────────────┘
                   ↓
        ... iterate up to 6 turns ...
                   ↓
┌─────────────────────────────────────────┐
│   Final: Each produces deliverable      │
│   incorporating dialogue insights       │
└─────────────────────────────────────────┘
```

---

## Troubleshooting

### Agents not taking turns

**Problem:** Agents still seem to work in parallel

**Solution:** 
```python
# Ensure BOTH settings are correct
workspace = synqed.OrchestratedWorkspace(
    orchestrator=orchestrator,
    enable_agent_discussion=True,  # ← Must be True
    collaboration_mode=CollaborationMode.ADVERSARIAL  # ← Or COLLABORATIVE
)
```

### Dialogue too short

**Problem:** Agents converge too quickly (< 3 turns)

**Solution:**
- Modify max_turns in `_execute_turn_taking_dialogue` (default: 6)
- Adjust completion markers in `_check_dialogue_completion`
- Use more adversarial prompting

### Agents being too polite

**Problem:** Agents agree too easily, don't challenge enough

**Solution:**
- Use `CollaborationMode.ADVERSARIAL` (not COLLABORATIVE)
- Review system prompts in agent executors
- Ensure agents have distinct, potentially conflicting expertise

### Task decomposition is poor

**Problem:** LLM creates bad subtasks

**Solution:**
- Make sure agents have clear, descriptive skills
- Provide better task descriptions
- Add context to `execute_task(task, context={...})`

### Messages not displaying

**Problem:** Not seeing real-time output

**Solution:**
```python
workspace = synqed.OrchestratedWorkspace(
    orchestrator=orchestrator,
    display_messages=True  # ← Enable this
)
```

---

## Advanced: Customizing Dialogue

### Custom Turn Limits

Modify the turn-taking behavior by adjusting internal parameters:

```python
# In your code, after creating workspace
# The turn limit is currently hardcoded to 6
# You can modify it by adjusting the max_turns parameter
# in _execute_turn_taking_dialogue method
```

### Custom Completion Detection

The system detects when agents are satisfied by looking for markers like:
- "I agree"
- "This works"
- "We're aligned"
- "Ready to proceed"

You can customize this in `_check_dialogue_completion` method.

---

## Next Steps

1. **Try the examples:** Start with `workspace.py` in the examples folder
2. **Experiment with ADVERSARIAL mode:** Watch agents iterate back and forth
3. **Build your agents:** Create specialized agents with distinct expertise
4. **Monitor dialogue:** Use `display_messages=True` to watch turn-taking
5. **Scale up:** Add more agents for complex workflows

---

## Additional Resources

- 📚 [Full API Documentation](../docs/)
- 💡 [More Examples](../examples/)
- 🐛 [Report Issues](https://github.com/your-repo/issues)
- 💬 [Community Discord](https://discord.gg/your-invite)

---

**Happy Collaborating! 🎉**

