OpenMAIC Orchestration and Director Graph Implementation: Key Files Explained
OpenMAIC's multi-agent orchestration relies on a LangGraph-based state machine centered in lib/orchestration/director-graph.ts, which coordinates with prompt builders in director-prompt.ts and prompt-builder.ts, state utilities in the summarizers/ directory, and agent resolution via registry/store.ts to execute stateless, single-turn director-to-agent cycles.
OpenMAIC is an open-source framework for multi-agent conversational AI that uses a lightweight state machine to manage collaborative discussions. The orchestration logic driving these interactions resides primarily within the lib/orchestration package, implementing a deterministic director graph pattern that routes conversations between specialized agents. Understanding these key files is essential for developers extending OpenMAIC's conversational capabilities or debugging agent coordination logic.
The Director Graph State Machine (director-graph.ts)
The heart of OpenMAIC's orchestration lives in lib/orchestration/director-graph.ts, which defines the LangGraph StateGraph responsible for every conversation turn. This file implements a stateless, single-round orchestration contract where each request executes at most one director-to-agent transition.
Graph Structure and Node Definitions
The director-graph.ts file declares the OrchestratorState annotation to type the graph's state channels. It implements two primary computational nodes:
- Director node: Determines the next speaking agent based on conversation context, available agents, and whiteboard state
- Agent-generate node: Streams the selected agent's response using structured prompts
The graph follows a linear flow: START → director → agent_generate → END, ensuring deterministic execution for each turn.
Graph Compilation and State Initialization
Two critical factory functions manage graph lifecycle:
createOrchestrationGraph(): Compiles and returns the executableStateGraphinstancebuildInitialState(): Materializes anOrchestratorStatefrom aStatelessChatRequest, preparing the initial context for graph invocation
// Example: create an orchestration graph and run a single request
import { createOrchestrationGraph, buildInitialState } from '@/lib/orchestration/director-graph';
import { getDefaultLanguageModel } from '@/lib/providers/openai'; // (illustrative)
async function runOneTurn(request) {
const lm = await getDefaultLanguageModel(); // LanguageModel instance
const graph = createOrchestrationGraph(); // compiled StateGraph
const initial = buildInitialState(request, lm); // populate OrchestratorState
// `graph.invoke` executes the START → director → (agent_generate) → END flow
const result = await graph.invoke(initial);
return result; // contains agentResponses, whiteboardLedger, etc.
}
Prompt Engineering for Multi-Agent Coordination
Effective multi-agent orchestration requires carefully constructed prompts for both the director (orchestrator) and individual agents.
Director Prompt Construction (director-prompt.ts)
The lib/orchestration/director-prompt.ts file builds the system prompt presented to the director LLM. It assembles context including available agent descriptions, prior conversation responses, whiteboard actions, discussion context, and student profile metadata.
The module exports buildDirectorPrompt() for prompt generation and parseDirectorDecision() to deserialize the LLM's JSON output into actionable routing decisions.
// Example: build the director prompt directly (useful for testing)
import { buildDirectorPrompt } from '@/lib/orchestration/director-prompt';
import { exampleAgents, exampleHistory } from '@/test/fixtures';
const prompt = buildDirectorPrompt(
exampleAgents,
exampleHistory.summary,
[], // no agents have spoken yet
0, // first turn
{ topic: 'Photosynthesis' },
null, // no trigger agent
[], // empty whiteboard ledger
{ nickname: 'Alice' },
true
);
console.log(prompt); // → system prompt string passed to the LLM
Agent Prompt Generation (prompt-builder.ts)
Individual agents receive structured prompts via lib/orchestration/prompt-builder.ts. The buildStructuredPrompt() function composes each agent's context, incorporating store state, discussion history, and whiteboard ledger entries to ensure agents have complete conversational awareness.
State Management and Utilities
Supporting the core graph are specialized utilities that condense and format conversational state.
Conversation Summarization (summarizers/)
The lib/orchestration/summarizers/ directory contains essential state transformers:
conversation-summary.ts: Condenses chat history into concise summaries for the director promptmessage-converter.ts: Transforms internal message objects into OpenAI-compatible message structureswhiteboard-ledger.ts: Exposes whiteboard-specific context and action recordsstate-context.ts: Manages general state serialization for graph transitions
Agent Registry Resolution (registry/store.ts)
The lib/orchestration/registry/store.ts file maintains the global agent registry via useAgentRegistry. It provides applyGeneratedAgentsToRegistry() for dynamic agent registration and supports agent resolution through resolveAgent(). This function checks request-scoped overrides before falling back to the shared registry, enabling flexible agent substitution without modifying global state.
Type Safety and Shared Contracts (types.ts)
The lib/orchestration/types.ts file establishes the TypeScript contracts governing the entire orchestration layer. Key definitions include:
AgentTurnSummary: Metadata describing an agent's participation in a turnWhiteboardActionRecord: Structured representation of whiteboard modificationsStatelessChatRequest: The input contract for initiating orchestration cycles
These types ensure type safety across graph nodes, prompt builders, and registry operations.
Summary
lib/orchestration/director-graph.tsdefines the LangGraphStateGraphwith director and agent-generate nodes, providingcreateOrchestrationGraph()andbuildInitialState()for execution.lib/orchestration/director-prompt.tsconstructs the director LLM's system prompt and parses its JSON routing decisions viabuildDirectorPrompt()andparseDirectorDecision().lib/orchestration/prompt-builder.tssuppliesbuildStructuredPrompt()for generating per-agent system prompts with full conversational context.lib/orchestration/summarizers/utilities condense chat history, convert message formats, and manage whiteboard state for prompt injection.lib/orchestration/registry/store.tsmanages agent registration throughuseAgentRegistryand agent resolution viaresolveAgent()with support for request-scoped overrides.lib/orchestration/types.tsexports shared TypeScript definitions includingOrchestratorState,AgentTurnSummary, andStatelessChatRequestthat bind the orchestration layer together.
Frequently Asked Questions
What is the role of the director node in OpenMAIC's graph?
The director node is the decision-making component within lib/orchestration/director-graph.ts that determines which agent should speak next based on the current conversation state. It receives the assembled prompt from director-prompt.ts, queries the LLM, and parses the response to identify the target agent for the current turn.
How does OpenMAIC maintain state across multiple conversation turns?
OpenMAIC implements a stateless, single-round orchestration contract where the server does not maintain session state between requests. The client serializes the conversation history and whiteboard ledger, passing them in each StatelessChatRequest. The buildInitialState() function materializes the full OrchestratorState from this request payload, allowing the graph to execute deterministically without server-side persistence.
Can I override specific agents for a single request without modifying the global registry?
Yes. The resolveAgent() function in lib/orchestration/registry/store.ts first checks for request-scoped agent overrides before falling back to the global registry accessed via useAgentRegistry. This enables temporary agent substitution for specific conversation turns while leaving the shared registry unchanged.
What data structure carries conversation context between the director and agent nodes?
The OrchestratorState annotation, defined in lib/orchestration/director-graph.ts and typed in types.ts, carries all context including conversation history, whiteboard actions, agent responses, and student profiles. The summarizers in lib/orchestration/summarizers/ condense this state into prompts suitable for LLM consumption.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →