agent-team/ARCHITECTURE.md
2026-03-06 13:32:23 +08:00

4.1 KiB

Agent Team Collaboration Architecture

System Design

Shared Blackboard Pattern

type SharedBoard struct {
    mu      sync.RWMutex
    entries []BoardEntry
}

type BoardEntry struct {
    Author  string
    Content string
    Type    string // "draft" | "challenge"
}

Thread-safe operations:

  • Add(): Appends entries with write lock
  • ToContext(): Reads all entries with read lock, formats as XML

Execution Flow

HandleUserMessage()
    ↓
Master Planning Loop (iteration 0-4)
    ├─ Master analyzes user request
    ├─ Outputs ASSIGN:member:task lines
    ├─ parseAssignments() extracts tasks
    ├─ Creates new SharedBoard{}
    │
    ├─ runMembersParallel()
    │   ├─ For each assignment, spawn goroutine
    │   ├─ Each member sees current board snapshot
    │   ├─ Member executes task
    │   ├─ Result added to board as "draft"
    │   └─ WaitGroup ensures all complete
    │
    ├─ runChallengeRound()
    │   ├─ Filter members with CanChallenge=true
    │   ├─ For each challenger, spawn goroutine
    │   ├─ Challenger sees full board
    │   ├─ Outputs CHALLENGE:... or AGREE
    │   ├─ CHALLENGE entries added to board
    │   └─ WaitGroup ensures all complete
    │
    ├─ Master Review
    │   ├─ Receives board.ToContext()
    │   ├─ Sees all drafts and challenges
    │   ├─ Decides: DONE or re-ASSIGN
    │   └─ Loop continues if re-ASSIGN
    │
    └─ updateMasterMemory() (async)

Concurrency Model

Parallel Execution Phase:

var wg sync.WaitGroup
for memberName, task := range assignments {
    wg.Add(1)
    go func(name, t string) {
        defer wg.Done()
        // Execute task
        board.Add(name, result, "draft")
    }(memberName, task)
}
wg.Wait()  // Wait for all members

Challenge Round Phase:

var wg sync.WaitGroup
for _, name := range challengers {
    wg.Add(1)
    go func(n string) {
        defer wg.Done()
        // Review board
        if strings.Contains(result, "CHALLENGE:") {
            board.Add(n, result, "challenge")
        }
    }(name)
}
wg.Wait()  // Wait for all challenges

Context Injection

Initial Draft Phase:

Member System Prompt = Soul + Memory + [empty board]

Challenge Round Phase:

Member System Prompt = Soul + Memory + <team_board>
  <entry type="draft" author="member1">...</entry>
  <entry type="draft" author="member2">...</entry>
</team_board>

Master Review Phase:

Master Feedback = Team results + <team_board>
  <entry type="draft" author="member1">...</entry>
  <entry type="draft" author="member2">...</entry>
  <entry type="challenge" author="member1">...</entry>
</team_board>

Event Streaming

Events emitted during execution:

  1. Parallel Phase:

    • EvtAgentMessage with role: "member" (streaming)
    • EvtTaskAssign (task assignment)
    • EvtWorkspaceFile (if document generated)
  2. Challenge Phase:

    • EvtAgentMessage with role: "challenge" (streaming)
  3. Status Updates:

    • EvtRoomStatus with status: "working""thinking""pending"

Configuration

Agent AGENT.md:

---
name: agent_name
role: member
can_challenge: true  # Enable challenge participation
---

Agent SOUL.md:

  • Includes challenge instructions
  • Specifies how to output CHALLENGE:...
  • Defines acceptance of challenges

Benefits

  1. Parallelism: Members work simultaneously, not sequentially
  2. Transparency: All members see each other's work via board
  3. Quality Control: Challenge round catches issues early
  4. Collaboration: Members can question and improve each other's work
  5. Master Awareness: Master sees full context before deciding
  6. Thread-Safe: Concurrent access protected by mutexes
  7. Scalable: Works with any number of members

Backward Compatibility

  • Existing master/member roles unchanged
  • Challenge role is additive (new event type)
  • Members without can_challenge: true skip challenge round
  • No breaking changes to existing APIs