In a multi-agent system, we often use the concept of  orchestration where a smarter or stronger model acts as a coordinator for multiple agents, which decides the plan and sequence of moves, giving instructions to sub-agents to feed them the much needed context. 

Perhaps, one might ask why does this way of design feel extremely intuitive, natural and effective. I think the question lies back to how we always have done things, that is draw parallels to the things you know that works and utilise it. So in this op-ed we will draw parallel to something very fundamental to computer science, parallel programming. 

Parallel programming teaches us about threads and processes. Every time you run an application, like an app on your desktop or phone,  its most likely always a process. A **process** can be defined as **independent executing program** that has its own isolated memory space allocated by the operating system.  This is analogous to a business department. However, what we are more interested are **threads**. A **thread** is the smallest unit of execution that can be managed independently by a scheduler. A process is made up of many threads. Think of them as workers in a business department that power it. They are also what you think about, when you think speed. 

```plantuml
@startuml
skinparam rectangle {
    RoundCorner 10
}
skinparam packageStyle rectangle
package "Operating System / Memory Space" {
    node "Process A (PID: 101)\n[Independent Virtual Address Space]" as ProcA {
        rectangle "Shared Memory Space" as MemA #E8F5E9 {
            rectangle "Code (Text Segment)" as CodeA #C8E6C9
            rectangle "Data / BSS (Globals)" as DataA #C8E6C9
            rectangle "Heap (Dynamic Allocations)" as HeapA #C8E6C9
            rectangle "Files / Sockets / Handles" as ResA #C8E6C9
        }
        package "Thread 1 (TID: 1011)" as T1 #E3F2FD {
            rectangle "Registers / PC" as Reg1 #BBDEFB
            rectangle "Private Stack" as Stack1 #90CAF9
        }
        package "Thread 2 (TID: 1012)" as T2 #E3F2FD {
            rectangle "Registers / PC" as Reg2 #BBDEFB
            rectangle "Private Stack" as Stack2 #90CAF9
        }
        T1 ..> MemA : shares
        T2 ..> MemA : shares
    }
    node "Process B (PID: 202)\n[Independent Virtual Address Space]" as ProcB {
        rectangle "Shared Memory Space" as MemB #FFF3E0 {
            rectangle "Code (Text Segment)" as CodeB #FFE0B2
            rectangle "Data / BSS (Globals)" as DataB #FFE0B2
            rectangle "Heap (Dynamic Allocations)" as HeapB #FFE0B2
            rectangle "Files / Sockets / Handles" as ResB #FFE0B2
        }
        package "Thread 1 (TID: 2021)" as T3 #F3E5F5 {
            rectangle "Registers / PC" as Reg3 #E1BEE7
            rectangle "Private Stack" as Stack3 #CE93D8
        }
        package "Thread 2 (TID: 2022)" as T4 #F3E5F5 {
            rectangle "Registers / PC" as Reg4 #E1BEE7
            rectangle "Private Stack" as Stack4 #CE93D8
        }
        T3 ..> MemB : shares
        T4 ..> MemB : shares
    }
}
' Isolation boundary
ProcA <..> ProcB : **No Direct Memory Access**\n(Requires IPC: Pipes, Sockets, Shared Memory)
@enduml
```

Like workers in a department, they often share the same resources, like files, stationary , computers. However, by sharing, there is a chance that two people might have the same intention to use the exact same item. This is the idea of a shared memory model. However, what happens if two people wants to use the same item. You can't both hold a pen! so you have to do whats natural, take turns.Similarly, for any resource on your computer, only a single thread can access it or else you get undefined behaviour.  This means a single writer. On the other hand, your whole department can see a pen and notice it without using it. However, the moment someone starts writing, its not as clear anymore. Same idea, you can have multiple readers too . But you can never read and write at the same time because it becomes extremely blurry in which which came first, the read or the write.    The whole idea of this analogy is to show that you can only be either a (1) **a single writer** or (2) **multiple readers**  but never a mix of both.

In nature, work in itself draws a heavy similarity. If you have multiple people overwriting one another, there will be no constructive progress. Instead you would organise people into sub-task and get them to handle it entirely on their own. Then you would have a **leader** to organise things around, and often a scribe or individual pens down the idea on a central document. Does this look familiar or sound familiar? **Individuals who collect information and fulfil their own task**  , passes it to a individual who jotts it down, with a leader giving exact instructions. It is **a single writer** - a single document, **multiple readers.** 

And this is how intuitively, we can derive one of the most effective system to an AI system, hidden in plain sight, in both logic and parallel programming , the idea of coordination, between readers and writers.  **The orchestrator** , dispatches task to its **sub-agents**  , acting as the leader. It then collects the task in a central place and writes it into its own context, before sequentially executing the same task.

You can't have two leaders, because then it becomes difficult to know which order they should operate in.  **Dual Consulship** by the romans, show exactly why this was one of the worst ideas . 

You can always increase the number of readers, because the **leader chooses what to do with that** information. 

And now, we have sufficiently approximated an AI problem for a task to a parallel computing task. 

This is the beauty of computer science, where theorems apply across sub-specialty and fields and model closely to the logic we experience in the real world. You will see this design throughout operating systems **(multi-threading)** , databases (**master - slave)** and networks (TCP , UDP ) . And there we have it, AI system design isn't really that new after all. 

Sincerely,

Sean
