# Understanding the Role of `buildDirectorPrompt` and `parseDirectorDecision` in OpenMAIC

> Explore how buildDirectorPrompt and parseDirectorDecision in OpenMAIC control the Director agent, an LLM-based system that dynamically routes conversations and manages agent turns for efficient AI interaction.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: deep-dive
- Published: 2026-09-05

---

**The `buildDirectorPrompt` and `parseDirectorDecision` functions in OpenMAIC work together to power the Director agent, a lightweight LLM-based controller that dynamically routes conversation turns between multiple specialized agents and decides when a round should end.**

OpenMAIC is a multi-agent orchestration framework developed by THU-MAIC that coordinates specialized agents (teacher, student, whiteboard, and others) through structured conversations. The Director sits at the heart of this system, replacing hard-coded routing rules with data-driven LLM decisions. These two functions—`buildDirectorPrompt` and `parseDirectorDecision`—form the complete request-response cycle that enables this flexible control mechanism.

## What `buildDirectorPrompt` Does

`buildDirectorPrompt` generates the **system prompt** that instructs the LLM acting as the Director. Located in [`lib/orchestration/director-prompt.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/orchestration/director-prompt.ts) (lines 23-89), this function assembles all runtime context into a structured string using the `DIRECTOR` template.

The function accepts these key parameters:

- `agents` — Array of available `AgentConfig` objects defining who can participate
- `conversationSummary` — Current state of the dialogue
- `agentResponses` — What each agent has already said in this round
- `turnCount` — How many exchanges have occurred
- `discussionContext` — Optional student-initiated discussion mode settings
- `triggerAgentId` — Which agent started the current flow
- `whiteboardLedger` — Whiteboard action history as `WhiteboardActionRecord[]`
- `userProfile` — Optional learner characteristics for personalization
- `whiteboardOpen` — Whether the whiteboard UI is currently active

The prompt construction handles multiple conversation modes. In **discussion mode**, it applies special routing rules that prioritize student-driven exploration. It also calls `buildWhiteboardStateForDirector` to inject a concise whiteboard summary, ensuring the Director understands any collaborative annotations or tool usage.

## What `parseDirectorDecision` Does

`parseDirectorDecision` processes the LLM's response and extracts the routing decision. Found in the same file at lines 110-140, this function serves as the defensive parser that guards against malformed outputs.

The function expects a JSON response from the Director LLM, typically:

```json
{ "next_agent": "teacher" }

```

or

```json
{ "next_agent": "END" }

```

The parser handles three outcomes:

- **Valid agent ID** — Returns `{ nextAgentId: string, shouldEnd: false }` and routing continues
- **Explicit `"END"` value** — Returns `{ nextAgentId: null, shouldEnd: true }` to terminate the round
- **Missing or malformed JSON** — Falls back to `{ nextAgentId: null, shouldEnd: true }` as a safe default

This normalization ensures the orchestration layer never crashes on unexpected LLM outputs.

## How the Functions Work Together

The complete Director control flow follows this sequence:

1. **State gathering** — The workbench collects conversation snapshot, agent configurations, response history, and whiteboard data
2. **Prompt generation** — `buildDirectorPrompt` formats this into the `DIRECTOR` system prompt
3. **LLM inference** — The Director LLM receives the prompt and returns a JSON decision
4. **Decision parsing** — `parseDirectorDecision` safely extracts and validates the `next_agent` field
5. **Action execution** — The orchestrator either dispatches to the named agent or ends the round

This loop repeats until the Director signals termination or a maximum turn limit is reached.

## Implementation Example

Here's how these functions integrate into the orchestration loop:

```typescript
import {
  buildDirectorPrompt,
  parseDirectorDecision,
} from '@/lib/orchestration/director-prompt';

// Assemble current conversation state
const systemPrompt = buildDirectorPrompt(
  agents,                      // AgentConfig[]
  summary,                     // string
  respondedAgents,             // AgentTurnSummary[]
  turnCount,                   // number
  discussionCtx,               // optional discussion info
  triggerAgentId,              // optional initiator
  whiteboardLedger,            // WhiteboardActionRecord[]
  userProfile,                 // optional user profile
  whiteboardOpen,              // boolean
);

// Query the Director LLM
const directorResponse = await llm.chat({ 
  system: systemPrompt, 
  user: '' 
});

// Extract routing decision
const { nextAgentId, shouldEnd } = parseDirectorDecision(
  directorResponse.content
);

// Execute routing or terminate
if (!shouldEnd && nextAgentId) {
  await dispatchToAgent(nextAgentId);
} else {
  endCurrentRound();
}

```

## Key Source Files and Type Definitions

| File | Purpose |
|------|---------|
| [`lib/orchestration/director-prompt.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/orchestration/director-prompt.ts) | Implements both functions plus `buildWhiteboardStateForDirector` helper |
| [`lib/orchestration/registry/types.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/orchestration/registry/types.ts) | Defines `AgentConfig` interface used by the prompt builder |
| [`lib/prompts.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/prompts.ts) | Contains the `DIRECTOR` template string referenced by `buildPrompt` |
| [`lib/orchestration/types.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/orchestration/types.ts) | Declares `WhiteboardActionRecord` and `AgentTurnSummary` structures |

The type system ensures `AgentTurnSummary` captures each agent's contribution timestamp, content, and metadata, while `WhiteboardActionRecord` tracks collaborative edits with operation types and authors.

## Why This Design Matters

The separation of `buildDirectorPrompt` and `parseDirectorDecision` creates a **clean interface boundary** between orchestration logic and LLM interaction. Teams can modify prompt engineering strategies—adding new context fields, adjusting formatting, or switching discussion modes—without changing the parsing contract. Conversely, parser improvements for edge cases (newlines in JSON, markdown code fences, truncated responses) don't affect prompt construction.

This architecture also enables **deterministic reproducibility**. Given the same conversation state, the prompt builder produces identical inputs, making Director behavior testable and debuggable.

## Summary

- **`buildDirectorPrompt`** constructs the complete system prompt that informs the Director LLM about available agents, conversation history, whiteboard state, and routing constraints
- **`parseDirectorDecision`** safely extracts the `next_agent` JSON field and determines whether to continue routing or end the round
- Both functions reside in [`lib/orchestration/director-prompt.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/orchestration/director-prompt.ts) and operate on shared type definitions from [`lib/orchestration/types.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/orchestration/types.ts)
- The prompt builder supports dynamic conversation modes including student-initiated discussion and whiteboard-aware routing
- The parser implements defensive fallback logic that treats malformed responses as end-of-round signals

## Frequently Asked Questions

### What happens if the Director LLM returns invalid JSON?

`parseDirectorDecision` catches parsing errors and returns `shouldEnd: true` with a `null` next agent. This conservative fallback prevents the conversation from entering undefined states when LLM outputs are malformed.

### Can the Director route to the same agent multiple times in one round?

Yes. The `agentResponses` parameter tracks which agents have already spoken, but the prompt does not enforce uniqueness. The Director LLM can theoretically select any available agent based on conversation needs, including revisiting previous speakers.

### How does discussion mode change the Director's behavior?

When `discussionContext` is provided, `buildDirectorPrompt` injects special instructions that prioritize student agency and exploratory dialogue over direct instructional flow. This modifies the routing incentives without changing the underlying parsing logic.