# How the Director Node Makes Routing Decisions in OpenMAIC

> Discover how the OpenMAIC Director Node makes routing decisions using nine explicit rules and runtime limits to manage multi-agent conversations, prevent loops, and avoid redundancy.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: internals
- Published: 2026-09-03

---

**The Director Node combines nine explicit routing rules embedded in its system prompt with hard runtime limits to orchestrate multi-agent classroom conversations, determining which agent speaks next while preventing infinite loops and redundant calls.**

OpenMAIC (Multi-Agent Intelligent Classroom) is an open-source framework for orchestrating AI-powered educational dialogues. The **Director Node** serves as the central orchestrator that makes routing decisions to determine which classroom agent should speak next and when conversations should terminate. According to the THU-MAIC/OpenMAIC source code, this routing logic relies on a dual-layer architecture: policy-driven prompts that guide the LLM's reasoning, and deterministic runtime guards that enforce execution boundaries.

## The Nine Routing Rules in the System Prompt

The core routing policy is encoded in the `buildDirectorPrompt` function located in [`lib/chat/pi/prompts.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/chat/pi/prompts.ts) (lines 21‑33). This function generates a system prompt that enumerates nine explicit rules governing agent selection and conversation flow. These rules are the *only* source of routing decisions for the Director LLM.

### Priority and Sequencing Constraints

Rules 1‑3 establish the speaking order and prevent redundant invocations:

- **Teacher first priority**: In standard Q&A sessions, the teacher (role = `teacher`) must speak first to address user questions. In discussion mode, the initiator speaks first, followed by teacher guidance.
- **No redundant repeats**: The Director should not call an agent that has already spoken in the current loop unless absolutely necessary.
- **Avoid consecutive same‑role calls**: When another useful role is available, the system skips dispatching two agents of the same role back‑to‑back.

### Content and Role-Based Constraints

Rules 4‑7 govern the pedagogical quality and role integrity of responses:

- **Read prior results**: The Director must not ask another agent to re‑explain the same point; instead, it requests questions, challenges, examples, or concise summaries.
- **Clear user questions default to teacher**: If the latest user message is a clear question and no agent has answered it, the teacher gets priority. Assistants serve as fallback only when the teacher is unavailable.
- **First substantive answer rule**: For concept, mechanism, or process questions, the first substantive answer must come from the teacher (or teaching assistant if the teacher is unavailable). Students may only react after the teacher or assistant delivers the core point.
- **Separate perspectives**: The Director must never let one child agent impersonate another. If another perspective is needed, it calls that specific agent separately.

### Termination and Brevity Requirements

Rules 8‑9 control session lifecycle and response scope:

- **Terminal tool termination**: Once useful classroom agent turns are complete, the Director must call exactly one terminal tool—either `cue_user` or `close_session`—and stop further agent calls.
- **Brief instructions**: Each `call_agent` directive must remain concise. The Director should not request full lectures, multiple examples, or complex multi-student interactions from a single agent.

## Runtime Enforcement in the Director Loop

While the prompt-based rules guide the LLM's reasoning, the `runPiDirectorLoop` function in [`lib/chat/pi/director-loop.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/chat/pi/director-loop.ts) enforces hard constraints that override any model drift.

### Tool Call Budgeting

The runtime caps the number of tool invocations to prevent runaway execution. Lines 66‑68 define `maxDirectorToolCalls` as:

```typescript
const maxDirectorToolCalls = Math.max(opts.maxAgentTurns * 3, opts.maxAgentTurns + 3);

```

This budget ensures that regardless of the LLM's planning horizon, the Director cannot exceed a calculated maximum based on the configured `maxAgentTurns` parameter.

### Termination Conditions

The `afterToolCall` handler (lines 38‑45) tracks each invocation and determines when to inject a termination flag. The loop terminates when any of the following conditions are met:

- The session is closed (`sessionClosed`)
- The user is cued (`userCued`)
- The tool call limit is reached (`directorToolCalls >= maxDirectorToolCalls`)

When termination is triggered, the handler returns `{ terminate: true }`, forcing the Director LLM to stop issuing further `call_agent` calls. This runtime mechanism guarantees compliance with Rule 8 (exactly one terminal tool per loop).

```typescript
const terminate =
  sessionClosed || userCued || directorToolCalls >= maxDirectorToolCalls;
if (!terminate && !evidenceError) return undefined;
return {
  ...(terminate ? { terminate: true } : {}),
  ...(evidenceError ? { isError: true } : {}),
};

```

## Key Source Files for Routing Logic

| File | Role |
|------|------|
| [`lib/chat/pi/prompts.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/chat/pi/prompts.ts) | Contains `buildDirectorPrompt` which embeds the nine routing rules into the Director's system prompt (lines 21‑33). |
| [`lib/chat/pi/director-loop.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/chat/pi/director-loop.ts) | Implements `runPiDirectorLoop` with tool call budgeting and termination logic (lines 38‑45, 66‑68). |
| [`lib/chat/pi/tools/call-agent.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/chat/pi/tools/call-agent.ts) | Defines the `call_agent` tool that the Director invokes to delegate tasks to child agents. |
| [`lib/chat/pi/tools/read-scene.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/chat/pi/tools/read-scene.ts) | Provides the `read_scene` tool for fetching scene evidence before making routing decisions. |
| [`lib/chat/pi/director-compaction.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/chat/pi/director-compaction.ts) | Handles context compaction to maintain token limits, indirectly influencing routing efficiency. |

## Summary

- The **Director Node** in OpenMAIC determines routing through a hybrid policy-runtime architecture.
- Nine explicit **routing rules** embedded in `buildDirectorPrompt` govern agent priority, prevent redundancy, and enforce pedagogical sequencing.
- **Runtime enforcement** via `maxDirectorToolCalls` and the `afterToolCall` handler prevents infinite loops and guarantees session termination.
- The system distinguishes between **normal Q&A mode** (teacher speaks first) and **discussion mode** (initiator speaks first).
- All routing logic is contained within the `lib/chat/pi/` directory, specifically in [`prompts.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/prompts.ts) and [`director-loop.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/director-loop.ts).

## Frequently Asked Questions

### What are the nine routing rules in OpenMAIC's Director Node?

The nine rules are embedded in the system prompt generated by `buildDirectorPrompt` in [`lib/chat/pi/prompts.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/chat/pi/prompts.ts). They cover: (1) Teacher/initiator speaks first, (2) No redundant agent repeats, (3) Avoid consecutive same-role calls, (4) Read prior results before delegating, (5) Route clear questions to teachers first, (6) Require teacher/assistant for first substantive answers, (7) Prevent agent impersonation, (8) Call exactly one terminal tool when complete, and (9) Keep agent instructions brief.

### How does the Director Node prevent infinite agent loops?

The Director Node implements a **tool call budget** calculated as `Math.max(maxAgentTurns * 3, maxAgentTurns + 3)` in [`lib/chat/pi/director-loop.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/chat/pi/director-loop.ts) (lines 66‑68). The `afterToolCall` handler tracks invocations and automatically terminates the loop when this limit is reached, regardless of the LLM's intent. Additionally, Rule 8 in the system prompt explicitly forbids calling agents after the answer is sufficient.

### What triggers the Director Node to terminate a session?

Termination occurs when the `afterToolCall` handler detects any of three conditions in [`lib/chat/pi/director-loop.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/chat/pi/director-loop.ts) (line 45): the session is closed (`sessionClosed`), the user is cued (`userCued`), or the tool call limit is exceeded. When triggered, the handler injects `{ terminate: true }` into the context, forcing the Director to invoke exactly one terminal tool—either `cue_user` or `close_session`—and cease further agent calls.

### Where is the Director Node routing logic implemented in the codebase?

The routing logic is split between two primary locations in the THU-MAIC/OpenMAIC repository. **Policy logic** resides in [`lib/chat/pi/prompts.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/chat/pi/prompts.ts) within the `buildDirectorPrompt` function (lines 21‑33), which encodes the nine routing rules into the LLM's system prompt. **Runtime enforcement** is implemented in [`lib/chat/pi/director-loop.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/chat/pi/director-loop.ts) within the `runPiDirectorLoop` function and its `afterToolCall` handler (lines 38‑45 and 66‑68), which manages tool call budgets and termination conditions.