ADR-001: Agent Orchestrator Architecture¶
Metadata¶
- Status: Superseded
- Date: 2025-02-26
- Decision Makers: Vijaykumar Singh
- Related ADRs: None
Update (2026-05-04)¶
This ADR captures the original move away from a monolithic orchestrator, but it
no longer describes the current steady-state runtime.
Current runtime shape:
AgentOrchestratoris the composition root, session boundary, and
compatibility hotspot.- Canonical effectful behavior lives in
ChatService,ToolService,
SessionService,ContextService,ProviderService, and
RecoveryService. - State-passed coordinators are used selectively for exploration, safety,
system-prompt classification, and coordination recommendation. - Facades and deprecated coordinators remain compatibility or grouping
surfaces; they are not the canonical ownership layer for new behavior.
See docs/architecture.md (canonical system architecture) and
ADR-019 (the decomposition target the
service-first runtime is converging toward) for the authoritative current runtime architecture.
Context¶
Victor needs a core orchestration system that can:
- Manage conversation flow between users and LLMs
- Coordinate tool execution
- Handle multi-turn conversations
- Support different LLM providers
- Enable extensibility through plugins and verticals
The challenge is balancing:
- Simplicity of the public API
- Flexibility for advanced use cases
- Performance for production workloads
- Maintainability over time
Historical Decision¶
We will use a Coordinator Pattern with the Agent Orchestrator as the central coordinator, delegating specialized responsibilities to focused coordinator classes.
Architecture¶
Agent (Public API)
↓
AgentOrchestrator (Central Coordinator)
↓
├── ConversationCoordinator (Message history, context management)
├── SafetyCoordinator (Safety rules, pattern matching)
├── ToolCoordinator (Tool execution, result caching)
├── MetricsCoordinator (Performance tracking, observability)
└── ProviderCoordinator (LLM provider abstraction)
Key Components¶
- Agent: Simple facade providing
run(),stream(),chat()methods - AgentOrchestrator: Central coordinator managing the conversation loop
- Specialized Coordinators: Each handles a specific aspect of agent behavior
- Provider Adapters: Abstract LLM provider differences
- Tool Registry: Dynamic tool discovery and execution
Rationale¶
Why Coordinator Pattern?¶
Pros:
- Single Responsibility: Each coordinator has one clear purpose
- Testability: Coordinators can be tested in isolation
- Extensibility: New capabilities added via new coordinators
- Maintainability: Changes localized to specific coordinators
Cons:
- Complexity: More classes to understand
- Coordination overhead: Need to manage coordinator interactions
Why Not Alternatives?¶
Monolithic Orchestrator:
- ✗ Hard to test
- ✗ Difficult to extend
- ✗ Violates SRP
Microservices:
- ✗ Too complex for single-process framework
- ✗ Overhead of inter-service communication
- ✗ Deployment complexity
Plugin Architecture:
- ✗ Less type-safe
- ✗ Dynamic loading complexity
- ✗ Harder to debug
Consequences¶
Positive¶
- Clear separation of concerns: Each coordinator has a focused responsibility
- Easy to extend: Add new coordinators without modifying existing code
- Testable: Each coordinator can be unit tested independently
- Observable: MetricsCoordinator provides built-in observability
- Safe: SafetyCoordinator enforces security policies
Negative¶
- Learning curve: Developers need to understand multiple coordinator classes
- Overhead: Coordination between coordinators adds some complexity
- Initialization: More setup required for agent creation
Neutral¶
- Public API: Agent facade remains simple
- Performance: Minimal overhead from coordinator pattern
- Compatibility: Existing code continues to work
Implementation¶
Phase 1: Core Coordinators (Completed)¶
- ✅ ConversationCoordinator - Message and context management
- ✅ SafetyCoordinator - Safety rules and enforcement
- ✅ ToolCoordinator - Tool execution and caching
- ✅ MetricsCoordinator - Performance tracking
Phase 2: Enhanced Coordinators (In Progress)¶
- 🔄 StateCoordinator - Enhanced state management
- 🔄 CacheCoordinator - Multi-level caching strategy
- 🔄 EventCoordinator - Event streaming and subscriptions
Phase 3: Advanced Coordinators (Planned)¶
- ⏳ TeamCoordinator - Multi-agent coordination
- ⏳ WorkflowCoordinator - Workflow orchestration
- ⏳ VerticalCoordinator - Vertical-specific enhancements
Code Example¶
from victor import Agent
# Simple API (facade)
agent = Agent.create()
# Internally creates:
# - AgentOrchestrator
# - ConversationCoordinator
# - SafetyCoordinator
# - ToolCoordinator
# - MetricsCoordinator
result = await agent.run("Hello!")
Alternatives Considered¶
1. Direct Orchestrator (Monolithic)¶
Description: Single orchestrator class handling all responsibilities
Rejected Because:
- Violates Single Responsibility Principle
- Hard to test
- Difficult to extend
2. Plugin Architecture¶
Description: Dynamic loading of capability plugins
Rejected Because:
- Less type-safe
- Dynamic loading complexity
- Harder to debug
3. Microservices¶
Description: Separate services for each concern
Rejected Because:
- Too complex for single-process framework
- Overhead of inter-service communication
- Deployment complexity
References¶
Revision History¶
| Date | Version | Changes | Author |
|---|---|---|---|
| 2025-02-26 | 1.0 | Initial ADR | Vijaykumar Singh |
| 2026-05-04 | 1.1 | Marked superseded; redirected to current service-first runtime docs | Vijaykumar Singh |
| 2026-07-29 | 1.2 | Reconciliation: fixed dead CURRENT_STATE.md pointer → architecture.md; linked ADR-019 as the decomposition target |
Vijaykumar Singh |