---
title: "Multi-Agent in Practice: Why I Chose the Supervisor Pattern to Coordinate AI Agents"
description: "An in-depth comparison of the two dominant Multi-Agent architectures (Network vs Supervisor), illustrated with a LangGraph-powered podcast auto-generation pipeline. Covers Supervisor design thinking, feedback loops, and fault-tolerance strategies."
canonical_url: "https://blog.markkulab.net/en/post/multi-agent-supervisor-architecture"
author: "Mark Ku"
author_url: "https://blog.markkulab.net/en/author/mark-ku"
site: "Mark Ku's Tech Notes"
date_published: "2026-03-23 10:00:00 +0800"
category: "AI"
tags: ["Multi-Agent", "LangGraph", "Supervisor", "AI Agent", "LangChain"]
language: "en"
license: "CC BY 4.0"
license_url: "https://creativecommons.org/licenses/by/4.0/"
attribution: "when reusing or quoting, credit the author and link back to the original"
---

# Multi-Agent in Practice: Why I Chose the Supervisor Pattern to Coordinate AI Agents

> **TL;DR** — 歡迎收聽 Mark 的 Tech Insights，我是主持人璦廷。當單一的人工智慧無法滿足複雜任務時，多個人工智慧代理協作的 Multi-Agent 架構就成了關鍵。 今天讓我們來看看，為什麼在眾多架構中，我們特別推薦 Supervisor 主管模式。相較於讓代理自由對話、容易失控的點對點網路，Supervisor 模式由中央主管負責流程編排，各個 Worker 代理只需專注於專業執行。 這個重點值得注意，在實作 Podcast 自動生成管線時，代理間不直接溝通，而是透過共享的 State 物件傳遞資訊。搭配 LangGraph 的 Reducer 機制，能確保代理平行運作時的錯誤紀錄不被覆蓋。這不僅讓系統完全解耦，更能輕鬆建立品質把關的回饋迴路與容錯策略。 總結來說，Supervisor 模式讓複雜的人工智慧工作流變得清晰可控。思考一下，您手邊有哪些任務，也適合拆解並交給專屬的數位員工來代勞呢？

## Background

By 2025, AI Agents are nothing new. The real competition has shifted to **Multi-Agent** systems — letting multiple agents coordinate, divide work, and collaborate autonomously.

No matter how capable a single agent is, it hits a wall on complex tasks: the context window overflows, and trying to pack search + writing + editing + image generation + speech synthesis into one prompt makes quality unpredictable. Breaking the task into multiple specialized agents, each doing one thing, actually gives you more control.

But that raises the question: **how do multiple agents coordinate?** This post compares the two dominant architectural patterns and explains why I ended up choosing the Supervisor model for my podcast auto-generation pipeline.

## Two Dominant Architectural Patterns

When designing a Multi-Agent system, you typically encounter two design patterns:

### 1. Network / Peer-to-Peer

Agents communicate directly with each other — no central controller. Each agent can decide on its own who to talk to and what to pass along.

```
┌─────────┐     ┌─────────┐
│ Agent A │◄───►│ Agent B │
└────┬────┘     └────┬────┘
     │               │
     ▼               ▼
┌─────────┐     ┌─────────┐
│ Agent C │◄───►│ Agent D │
└─────────┘     └─────────┘
    （每個 Agent 都可以跟任意 Agent 溝通）
```

**Best for**: open-ended discussions, brainstorming, multi-perspective debates. **Risks**: unpredictable flow, easy to fall into infinite loops, difficult to debug.

### 2. Supervisor

A central Supervisor Agent evaluates the current state and decides which agent to dispatch next. Worker agents execute their task and report back; the Supervisor decides what happens next.

```
                ┌────────────┐
                │ Supervisor │
                │  (協調者)   │
                └─────┬──────┘
           ┌──────────┼──────────┐
           ▼          ▼          ▼
      ┌─────────┐ ┌─────────┐ ┌─────────┐
      │Worker A │ │Worker B │ │Worker C │
      │(搜尋)   │ │(撰寫)   │ │(校稿)   │
      └─────────┘ └─────────┘ └─────────┘
    （Worker 只跟 Supervisor 溝通，彼此不直接對話）
```

**Best for**: task pipelines with clear steps, quality gates, and trackable progress. **Advantages**: predictable flow, clear separation of concerns, straightforward fault tolerance.

### Comparison

<table style="min-width: 75px;"><colgroup><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"></colgroup><tbody><tr><th colspan="1" rowspan="1"><p>Dimension</p></th><th colspan="1" rowspan="1"><p>Network (P2P)</p></th><th colspan="1" rowspan="1"><p>Supervisor</p></th></tr><tr><td colspan="1" rowspan="1"><p>Control</p></td><td colspan="1" rowspan="1"><p>Decentralized, agents negotiate</p></td><td colspan="1" rowspan="1"><p>Centralized, Supervisor dispatches</p></td></tr><tr><td colspan="1" rowspan="1"><p>Predictability</p></td><td colspan="1" rowspan="1"><p>❌ Low, paths are dynamic</p></td><td colspan="1" rowspan="1"><p>✅ High, explicit state machine</p></td></tr><tr><td colspan="1" rowspan="1"><p>Debug difficulty</p></td><td colspan="1" rowspan="1"><p>😰 High, complex message flows</p></td><td colspan="1" rowspan="1"><p>😌 Low, every step is logged</p></td></tr><tr><td colspan="1" rowspan="1"><p>Best task type</p></td><td colspan="1" rowspan="1"><p>Open-ended discussion, creative work</p></td><td colspan="1" rowspan="1"><p>Production pipelines with defined steps</p></td></tr><tr><td colspan="1" rowspan="1"><p>Extensibility</p></td><td colspan="1" rowspan="1"><p>Adding agents requires rethinking topology</p></td><td colspan="1" rowspan="1"><p>Just register a new Worker with the Supervisor</p></td></tr><tr><td colspan="1" rowspan="1"><p>Fault tolerance</p></td><td colspan="1" rowspan="1"><p>Each agent handles its own errors</p></td><td colspan="1" rowspan="1"><p>Supervisor owns the degradation strategy</p></td></tr></tbody></table>

## Why I Chose the Supervisor Pattern

The core reason: **the Supervisor only needs to know "who can do what," and Workers only need to know "how to do this one thing well."**

That separation is clean:

- **Supervisor** handles "orchestration" — who goes first, who goes next, what happens on failure.
- **Workers** handle "specialized execution" — search is search, writing is writing, editing is editing.

This mirrors the **Single Responsibility Principle (SRP)** in software engineering — each agent does exactly one thing and reports back when done.

In practice, most AI automation tasks have clear sequential dependencies (you need the search results before you can write, and the draft before you can edit). The Supervisor pattern is a natural fit for this kind of pipeline workflow.

## How Agents Coordinate: Shared State Is the Only Communication Channel

In the Supervisor pattern, **agents never communicate directly with each other**. All coordination flows through a shared State object:

```
┌─────────────────────────────────────────────┐
│           共享狀態（Shared State）             │
│                                             │
│  rawSources ← Research 寫入                  │
│  podcastMarkdown ← Writer 寫入               │
│  editorFeedback ← Editor 寫入                │
│  coverImagePath ← CoverArt 寫入              │
│  audioPath ← TTS 寫入                        │
│  errors ← 所有 Agent 可寫入（append 模式）     │
│                                             │
│  Supervisor 讀取 State → 決定下一步           │
└─────────────────────────────────────────────┘
```

Each agent's interaction pattern is simple:

- **Read**: pull its required input from State (e.g., Writer reads `rawSources`)
- **Write**: push its output back to State (e.g., Writer writes `podcastMarkdown`)
- **Doesn't need to know**: who ran before it, or who runs next

This means **agents are fully decoupled**. You can swap any agent's implementation at any time (e.g., replace a Gemini Writer with a Claude Writer) — as long as the State field contracts remain the same, no other agent is affected.

## LangGraph State Management: Annotations and Reducers

LangGraph uses `Annotation` to define shared state — this is the foundation of all Multi-Agent coordination.

### Core concept: each field can have its own reducer

Ordinary state management is "last write wins," but that breaks down in Multi-Agent scenarios. For example, if Agent A records an error and Agent B records an error, without a reducer B's error would overwrite A's.

LangGraph's solution is to let each field define its own **reducer (merge strategy)**:

```typescript
export const PodcastAnnotation = Annotation.Root({
  // 普通欄位：後寫覆蓋（預設行為）
  date: Annotation<string>,
  podcastMarkdown: Annotation<string>,

  // append reducer：新值追加到陣列，不覆蓋舊值
  errors: Annotation<AgentError[], AgentError[]>({
    reducer: (existing, update) => [...existing, ...update],
    default: () => [],
  }),

  // merge reducer：合併物件的 key-value
  retryCount: Annotation<Record<string, number>>({
    reducer: (existing, update) => ({ ...existing, ...update }),
    default: () => ({}),
  }),
})
```

### How reducers work

<table style="min-width: 75px;"><colgroup><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"></colgroup><tbody><tr><th colspan="1" rowspan="1"><p>Reducer type</p></th><th colspan="1" rowspan="1"><p>Behavior</p></th><th colspan="1" rowspan="1"><p>Use case</p></th></tr><tr><td colspan="1" rowspan="1"><p>None (default)</p></td><td colspan="1" rowspan="1"><p>Last write wins</p></td><td colspan="1" rowspan="1"><p>Fields written by a single agent (<code>podcastMarkdown</code>)</p></td></tr><tr><td colspan="1" rowspan="1"><p>append</p></td><td colspan="1" rowspan="1"><p>New value appended to array</p></td><td colspan="1" rowspan="1"><p>Fields multiple agents may write (<code>errors</code>)</p></td></tr><tr><td colspan="1" rowspan="1"><p>merge</p></td><td colspan="1" rowspan="1"><p>Merge object keys</p></td><td colspan="1" rowspan="1"><p>Counters, state tracking (<code>retryCount</code>)</p></td></tr><tr><td colspan="1" rowspan="1"><p>custom</p></td><td colspan="1" rowspan="1"><p>Any custom logic</p></td><td colspan="1" rowspan="1"><p>Special requirements</p></td></tr></tbody></table>

### Why does this matter?

The most common bug in Multi-Agent systems without reducers is **state being silently overwritten**. Consider this scenario:

1. CoverArt Agent and TTS Agent **run in parallel**.
2. CoverArt hits an error and writes `errors: [{ agent: 'coverArt', message: '...' }]`.
3. TTS also hits an error and writes `errors: [{ agent: 'tts', message: '...' }]`.
4. Without an append reducer, TTS's error overwrites CoverArt's — **you'll never know the cover generation failed**.

With an append reducer, both errors are preserved. This is table-stakes for Multi-Agent state management.

## Design Concept: Implementing Supervisor with LangGraph StateGraph

I use [LangGraph](https://langchain-ai.github.io/langgraphjs/)'s `StateGraph` to implement the Supervisor. The core ideas are:

1. **Shared State**: all agents read from and write to the same State object (using `Annotation` as described above).
2. **Nodes**: each agent is a node.
3. **Edges**: define execution order between nodes.
4. **Conditional Edges**: the Supervisor reads State to decide which path to take next.

```
START → Research → Writer → Editor ─┬─→ Publisher → [CoverArt + TTS] → END
                     ▲               │
                     │    (score < 60, retry ≤ 2)
                     └───────────────┘
                      回饋迴路：帶著問題清單重寫
```

## Implementation: Podcast Auto-Generation Pipeline

I built a "Tech News Podcast Auto-Generator" using this architecture. Six agents, each with a dedicated role:

<table style="min-width: 75px;"><colgroup><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"></colgroup><tbody><tr><th colspan="1" rowspan="1"><p>Agent</p></th><th colspan="1" rowspan="1"><p>Responsibility</p></th><th colspan="1" rowspan="1"><p>Technology</p></th></tr><tr><td colspan="1" rowspan="1"><p>🔍 ResearchAgent</p></td><td colspan="1" rowspan="1"><p>Search for the latest AI news (8-12 items)</p></td><td colspan="1" rowspan="1"><p>Claude CLI + web_search</p></td></tr><tr><td colspan="1" rowspan="1"><p>✍️ WriterAgent</p></td><td colspan="1" rowspan="1"><p>Turn news sources into a podcast article</p></td><td colspan="1" rowspan="1"><p>Gemini 3.1 Pro</p></td></tr><tr><td colspan="1" rowspan="1"><p>📝 EditorAgent</p></td><td colspan="1" rowspan="1"><p>Quality scoring + removing AI artifacts</p></td><td colspan="1" rowspan="1"><p>Gemini 3.1 Pro + regex</p></td></tr><tr><td colspan="1" rowspan="1"><p>📦 PublisherAgent</p></td><td colspan="1" rowspan="1"><p>Assemble frontmatter and write MDX file</p></td><td colspan="1" rowspan="1"><p>Filesystem</p></td></tr><tr><td colspan="1" rowspan="1"><p>🎨 CoverArtAgent</p></td><td colspan="1" rowspan="1"><p>Generate cover image</p></td><td colspan="1" rowspan="1"><p>Gemini Image + sharp</p></td></tr><tr><td colspan="1" rowspan="1"><p>🎙️ TTSAgent</p></td><td colspan="1" rowspan="1"><p>Generate multi-voice dialogue audio</p></td><td colspan="1" rowspan="1"><p>Gemini + VoAI TTS</p></td></tr></tbody></table>

### Full Architecture Diagram

```
┌─────────────────────────────────────────────────────────────────────┐
│                        LangGraph StateGraph                         │
│                        (Supervisor 協調者)                           │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────────┐  │
│  │ Research  │───▶│  Writer  │───▶│  Editor  │───▶│  Publisher   │  │
│  │  Agent   │    │  Agent   │◀───│  Agent   │    │    Agent     │  │
│  │          │    │          │回饋 │          │    │              │  │
│  │ Claude   │    │ Gemini   │迴路 │ Gemini   │    │  Filesystem  │  │
│  │ CLI +    │    │ 3.1 Pro  │(≤2) │ 3.1 Pro  │    │  MDX 寫入    │  │
│  │web_search│    │          │    │          │    │              │  │
│  └──────────┘    └──────────┘    └──────────┘    └──────┬───────┘  │
│                                                         │          │
│                                              ┌──────────┴────┐     │
│                                              │   平行執行     │     │
│                                         ┌────▼────┐  ┌──────▼──┐  │
│                                         │CoverArt │  │  TTS    │  │
│                                         │ Agent   │  │  Agent  │  │
│                                         │ Gemini  │  │ Gemini  │  │
│                                         │ Image + │  │ + VoAI  │  │
│                                         │ sharp   │  │         │  │
│                                         └────┬────┘  └────┬────┘  │
│                                              ▼            ▼       │
│                                             END          END      │
└─────────────────────────────────────────────────────────────────────┘
```

## Key Code Walkthrough

### 1. Shared State Definition (LangGraph Annotation)

All agents read and write the same State. `Annotation` defines the data structure and reducers:

```typescript
import { Annotation } from '@langchain/langgraph'

export const PodcastAnnotation = Annotation.Root({
  // ─── 輸入 ───
  date: Annotation<string>,
  config: Annotation<PodcastConfig>,

  // ─── 各階段產出 ───
  rawSources: Annotation<NewsSource[]>,        // Research 寫入
  podcastMarkdown: Annotation<string>,          // Writer 寫入
  editorFeedback: Annotation<EditorFeedback>,   // Editor 寫入
  cleanedContent: Annotation<string>,           // Editor 寫入
  coverImagePath: Annotation<string | null>,    // CoverArt 寫入
  audioPath: Annotation<string | null>,         // TTS 寫入

  // ─── 控制欄位 ───
  errors: Annotation<AgentError[]>({
    reducer: (existing, update) => [...existing, ...update],
    default: () => [],
  }),
  retryCount: Annotation<Record<string, number>>({
    reducer: (existing, update) => ({ ...existing, ...update }),
    default: () => ({}),
  }),
})
```

**Key point**: `errors` uses an append reducer so later agents can't overwrite earlier error records.

### 2. StateGraph Assembly: Nodes + Edges + Conditional Routing

```typescript
import { StateGraph, END } from '@langchain/langgraph'

export function buildGraph() {
  const graph = new StateGraph(PodcastAnnotation)
    // 註冊節點（每個 Agent 都是一個 function）
    .addNode('research', researchAgent)
    .addNode('writer', writerAgent)
    .addNode('editor', editorAgent)
    .addNode('publisher', publisherAgent)
    .addNode('coverArt', coverArtAgent)
    .addNode('tts', ttsAgent)

    // 順序執行
    .addEdge('__start__', 'research')
    .addEdge('research', 'writer')
    .addEdge('writer', 'editor')

    // 條件路由：Editor 決定要重寫還是放行
    .addConditionalEdges('editor', routeAfterEditor, {
      publisher: 'publisher',
      writerRetry: 'writerRetry',
    })

    // Publisher 後：平行執行 CoverArt + TTS
    .addConditionalEdges('publisher', routeAfterPublisher, {
      coverArt: 'coverArt',
      tts: 'tts',
      end: 'end',
    })

    .addEdge('coverArt', END)
    .addEdge('tts', END)

  return graph.compile()
}
```

**Key point**: `addConditionalEdges` is the Supervisor's core mechanism — it reads the current State and decides which path to take next.

### 3. Worker Agent Implementation (WriterAgent as an Example)

Each Worker does exactly one thing: receive State, execute the task, write back the result:

```typescript
export async function writerAgent(
  state: PodcastState
): Promise<Partial<PodcastState>> {
  const model = await createVertexModel({
    model: state.config.writerModel,
    temperature: 0.8,
  })

  // 如果是 retry，帶入 Editor 的回饋
  let feedbackContext = ''
  if (state.editorFeedback && !state.editorFeedback.passed) {
    feedbackContext = state.editorFeedback.issues
      .map(i => `- ${i}`)
      .join('\n')
  }

  const prompt = buildWriterPrompt(state.date, newsContext) + feedbackContext
  const response = await model.invoke([{ role: 'user', content: prompt }])

  return {
    podcastMarkdown: response.content.trim(),
    currentStep: 'writing_done',
  }
}
```

The Worker doesn't need to know which iteration it's on, who ran before it, or who runs next. It just focuses on producing a good draft.

## Feedback Loop: The Quality Gatekeeper Pattern

This is the most powerful aspect of the Supervisor pattern — **you can design feedback loops**.

```
Writer ──draft──▶ Editor ──score──┬──▶ ✅ Pass → Publisher
                                  │
                            ❌ Fail (score < 60)
                                  │
                    Rewrite with feedback (max 2 retries)
                                  │
                                  └──▶ Writer
```

```typescript
function routeAfterEditor(state: PodcastState): string {
  // 通過 → 下一步
  if (state.editorFeedback?.passed) return 'publisher'

  // 沒通過但還有重試次數 → 帶回饋重寫
  const retries = state.retryCount?.['writer'] ?? 0
  if (retries < MAX_WRITER_RETRIES) return 'writerRetry'

  // 超過重試次數 → 帶警告繼續
  return 'publisher'
}
```

### Analogy: Coding Agent Scenario

The same pattern applies to code review:

```
Coding Agent ──submit code──▶ Supervisor Agent ──review──┬──▶ ✅ Pass → Merge
                                                          │
                                                    ❌ Security issue / violation
                                                          │
                                          Fix with feedback (max N retries)
                                                          │
                                                          └──▶ Coding Agent
```

The Supervisor only evaluates "does this code have problems," and the Coding Agent only "fixes based on feedback." Responsibilities are clear and don't bleed into each other.

## Fault Tolerance and Degradation Strategies

In a Multi-Agent system, not every agent is equally critical. A well-designed Supervisor needs **tiered fault tolerance**:

<table style="min-width: 75px;"><colgroup><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"></colgroup><tbody><tr><th colspan="1" rowspan="1"><p>Failure scenario</p></th><th colspan="1" rowspan="1"><p>Handling</p></th><th colspan="1" rowspan="1"><p>Severity</p></th></tr><tr><td colspan="1" rowspan="1"><p>Research search fails</p></td><td colspan="1" rowspan="1"><p>Writer generates from LLM's own knowledge</p></td><td colspan="1" rowspan="1"><p>⚠️ Degrade</p></td></tr><tr><td colspan="1" rowspan="1"><p>Editor fails repeatedly</p></td><td colspan="1" rowspan="1"><p>Publish with warning</p></td><td colspan="1" rowspan="1"><p>⚠️ Degrade</p></td></tr><tr><td colspan="1" rowspan="1"><p>CoverArt generation fails</p></td><td colspan="1" rowspan="1"><p>Article publishes without cover</p></td><td colspan="1" rowspan="1"><p>💡 Acceptable</p></td></tr><tr><td colspan="1" rowspan="1"><p>TTS synthesis fails</p></td><td colspan="1" rowspan="1"><p>Article publishes without audio</p></td><td colspan="1" rowspan="1"><p>💡 Acceptable</p></td></tr><tr><td colspan="1" rowspan="1"><p>Publisher write fails</p></td><td colspan="1" rowspan="1"><p><strong>Abort the pipeline</strong></p></td><td colspan="1" rowspan="1"><p>🔴 Hard failure</p></td></tr></tbody></table>

**Design principle**: failures in the core pipeline (Research → Write → Edit → Publish) need graceful degradation; failures in supplementary features (Cover, TTS) should not impact the main flow.

## Notes and Gotchas

### Practical pitfalls

- **Use reducers for shared state**: if multiple agents write to `errors` simultaneously without an append reducer, they'll overwrite each other. LangGraph's `Annotation` reducer is a lifesaver.
- **Parallel agents must be truly independent**: CoverArt and TTS can run in parallel because they have no data dependency on each other. If there is a dependency, sequential execution is required.
- **Always cap feedback loops**: a feedback loop without `MAX_RETRIES` is an infinite loop. I set mine to 2; after that, the pipeline continues with a warning.
- **Different agents can use different models**: Research uses Claude (strong search reasoning), Writer/Editor use Gemini (cheap + long context), TTS uses a dedicated voice API. Mixing models often yields better results than using one model for everything.

### Performance reference

<table style="min-width: 75px;"><colgroup><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"></colgroup><tbody><tr><th colspan="1" rowspan="1"><p>Mode</p></th><th colspan="1" rowspan="1"><p>Time</p></th><th colspan="1" rowspan="1"><p>Description</p></th></tr><tr><td colspan="1" rowspan="1"><p>Text only (skip-tts + skip-cover)</p></td><td colspan="1" rowspan="1"><p>~2 min</p></td><td colspan="1" rowspan="1"><p>Research → Writer → Editor → Publisher</p></td></tr><tr><td colspan="1" rowspan="1"><p>With cover</p></td><td colspan="1" rowspan="1"><p>~3 min</p></td><td colspan="1" rowspan="1"><p>Adds CoverArt generation</p></td></tr><tr><td colspan="1" rowspan="1"><p>Full pipeline</p></td><td colspan="1" rowspan="1"><p>~4 min</p></td><td colspan="1" rowspan="1"><p>CoverArt + TTS running in parallel</p></td></tr></tbody></table>

### When not to use Supervisor

- If the task is inherently open-ended (multi-agent debates, creative brainstorming), Supervisor actually limits agent autonomy.
- If you only have 2 agents and the flow is linear, just chain them directly — no need to bring in the full Supervisor architecture.

## Conclusion

The core of Multi-Agent isn't "more agents = better." It's **clear division of labor + predictable flow**.

Three design principles for the Supervisor pattern:

1. **Supervisor owns orchestration, Workers own execution** — single responsibility, each does its job.
2. **Feedback loops ensure quality** — the Editor/Reviewer acts as gatekeeper, sending work back when it doesn't pass.
3. **Tiered fault tolerance** — core pipeline degrades gracefully; supplementary features fail gracefully.

If you're planning a Multi-Agent system, I'd suggest first asking yourself: "does this task have a clear sequential order?" If yes, the Supervisor pattern is the most stable starting point.

![Dark mode admin panel displaying an AI agent workflow with multiple steps](https://blog.markkulab.net/content/markku/posts/multi-agent-supervisor-architecture/images/2.jpg)![Dark UI showing AI content generation form and multi-agent workflow](https://blog.markkulab.net/content/markku/posts/multi-agent-supervisor-architecture/images/667429162_26583505644577677_1599853590001067562_n.jpg)

---

## About this article and its author

Originally published on [Mark Ku's Tech Notes](https://blog.markkulab.net/en/post/multi-agent-supervisor-architecture)

License: [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) — when reusing or quoting, credit the author and link back to the original

### About the author

**[Mark Ku](https://blog.markkulab.net/en/author/mark-ku)** — Software Solution Provider

- 10+ years senior software engineer, now an AI Builder
- Focused on large-platform architecture — North-American e-commerce, AI SaaS subscription billing
- Combining AI Agents and automation to build evolvable product foundations

### Free tools built by the author

All of these are free to use:

- [Free PDF Sign Tool](https://blog.markkulab.net/en/tools/pdf-sign): Online PDF sign tool — draw, type, or upload a signature, then drag, resize, and download. Everything runs in your browser; nothing is uploaded.
- [VS Code Refactory](https://blog.markkulab.net/en/tools/refactory): Refactory is a VS Code refactoring extension: 34 actions plus a 37-rule code-smell inspection layer with a Code Health dashboard, across 18 languages, backed by 534 tests. It learns your repo's conventions: where interfaces live, where DI is registered, whether 'use client' belongs. It ranks files by git churn × complexity so you know what to fix first, and hands any smell to the Claude Code already on your machine. Free to use, and your source never leaves your computer.
- [DB-Kit Database Manager](https://blog.markkulab.net/en/tools/db-kit): DB-Kit is a lightweight, cross-platform database manager built with Tauri + Rust + React. Manage MySQL, MariaDB, PostgreSQL, SQL Server, Oracle, SQLite, MongoDB, Redis, Kafka, Elasticsearch and RabbitMQ from one consistent interface: passwords encrypted in the OS keychain, SSH tunnels, full CRUD, a visual query builder, stacked multi-statement result sets, cross-connection data transfer and compare/sync, Excel / CSV import & export, visualized execution plans, ER diagrams, scheduled backups, SQL stress testing with p50–p99 latency percentiles, a 15-rule SQL review engine, Kafka message browsing with monitoring & alerts, a bilingual UI (Traditional Chinese / English), a built-in AI assistant (natural-language SQL, AI review and tuning advice) and the dbk CLI. Free and open source (MIT), with installers for Windows, macOS and Linux.
- [VS Code Super Mermaid](https://blog.markkulab.net/en/tools/super-mermaid): Super Mermaid is a VS Code extension for beautiful Mermaid diagrams out of the box: auto-colored live preview, mouse pan & zoom, high-res PNG / SVG export, 21 templates and multiple themes. Free and open source (MIT).
- [React Super Mermaid](https://blog.markkulab.net/en/tools/react-super-mermaid): react-super-mermaid is an open-source React component library: render beautiful Mermaid diagrams with a single <MermaidViewer>, with built-in colorful / sketch themes, pan & zoom, in-diagram search, and high-res SVG / PNG export. Lightweight, SSR-safe, fully typed. Free and open source (MIT).
- [Jira / Confluence Super Mermaid](https://blog.markkulab.net/en/tools/jira-super-mermaid): An Atlassian Forge app: write Mermaid syntax directly inside a Jira issue or a Confluence page and get flowcharts, sequence diagrams, state machines and Gantt charts. 11 diagram types, SVG / PNG export, light and dark themes, full CJK support. Runs on Atlassian: your diagrams live in your own site and the app calls no third-party service. Free, coming soon to the Atlassian Marketplace.
- [Mermaid Live Preview](https://blog.markkulab.net/en/tools/mermaid-preview): Write Mermaid in your browser, see it render instantly, and share the whole diagram as a single link. No sign-up, nothing uploaded to a server, and mermaid.live share links work as-is.
- [React Intl Phone Number](https://blog.markkulab.net/en/tools/react-intl-phone-number): react-intl-phone-number is an open-source React component: framework-agnostic and antd-free, with E.164 in/out, a searchable flag / country-code dropdown, configurable validation levels (strict / mobile-strict / loose), themeable CSS, and i18n — phone logic powered by google-libphonenumber. Lightweight and fully typed. Free and open source (MIT).
- [Uptime Kuma Cluster](https://blog.markkulab.net/en/tools/uptime-kuma-cluster): Turn single-node Uptime Kuma into a highly available cluster: OpenResty + Lua smart load balancing, shared MariaDB state, health checks and automatic failover, plus cluster-management REST APIs. One Docker Compose command to start. Free and open source (MIT).
- [Special Education](https://blog.markkulab.net/en/education): Learning materials crafted for special education students

### Daily podcasts

- [Mark's Tech Insights — Daily AI News](https://blog.markkulab.net/en/category/tech-news): Daily curated AI and tech trends. Catch the latest developments via audio summaries — covering AI applications, software architecture, DevOps, and engineering practice. — RSS: https://blog.markkulab.net/feed.xml
- [AI股市蝦聊](https://blog.markkulab.net/en/category/ai-stock-chat): Every trading day, an AI-analyzed take on the Taiwan stock market, delivered as a two-host conversation covering the session and the next-day outlook. — RSS: https://blog.markkulab.net/ai-stock-chat/feed.xml
- [開源好物週報](https://blog.markkulab.net/en/category/open-source-weekly): A weekly two-host pick of free open-source tools surfaced from real Hacker News, GitHub, and Reddit buzz — what pain they solve and the fastest way to get started. — RSS: https://blog.markkulab.net/open-source-weekly/feed.xml

### Newsletter

[Subscribe to the newsletter](https://blog.markkulab.net/en/subscribe) — Be the first to know about new posts. No spam, unsubscribe anytime.
