Architecture Overview¶
Morphix follows a layered architecture with strict boundaries between subsystems. Each layer depends only on the layers below it — never upward — ensuring clear separation of concerns, testability, and the ability to swap implementations without cascading changes.
Layer Map¶
| Layer | Directory | Role |
|---|---|---|
| Core | core/ |
Business logic single source of truth. Database engine, config, memory (FAISS), security (undercover mode, encryption), path resolution, workspace management, context compression. No UI dependencies. |
| LLM | llm/ |
LLM abstraction. ModelsController (retries, backoff, circuit breaker), LLMProvider (OpenAI/DeepSeek/Grok ↔ Ollama routing), parser (JSON extraction), prompts, offline mode. Exposes StreamChunk dataclass for unified streaming. |
| Agents | agents/ |
Agent system. Registry (global + per-workspace), YAML profile loader, base execution, AgentsService, audit trails. Agent profiles declare tools, system prompts, and model preferences. |
| Tools | tools/ |
Tool implementations. Dynamic .py file loading (global + per-workspace), decorator-based registration, ToolOrchestrator (token budgets), specs (function-calling schemas), 12 registered tools. |
| Orchestration | orchestration/ |
Workflow brains. WorkflowOrchestrator (4+ routes), agent loop (ReAct), TaskAnalyzer, Decomposer, AgentRouter, Supervisor, ResultAggregator, Finalizer. Sub-package workflows/ holds collaborative, coordinated, TDD, and blackboard variants. |
| Desktop | desktop/ |
PySide6 GUI. Services layer (desktop/services/) for config, dashboard, analytics, history. Widgets: ChatBlock, MaestroTab. Stateless — all state lives in orchestration/. |
How a Task Flows¶
graph TD
A[User Message] --> B[run_full_workflow]
B --> C{Direct tool cmd?}
C -->|yes| D[Direct Tool Route]
C -->|no| E{Active workflow?}
E -->|tdd| F[TDD Loop]
E -->|collaborative| G[CollaborativeOrchestrator]
E -->|coordinated| H[MultiAgentCoordinator]
E -->|development| I[Full Orchestration]
E -->|default| J[TaskAnalyzer]
J -->|simple| K[Simple Conversation]
J -->|complex| I
D --> M[User Response]
F --> M
G --> M
H --> M
I --> M
K --> M
-
WorkflowOrchestrator.run_full_workflow()receives aSession(context + events) and performs security checks viaundercover.check_query(). -
Direct tool detection: If the message matches
tool_name: action, key=valformat and the tool exists in the registry, it takes the fast path — one tool call, immediate response. -
Template dispatch (
_dispatch_route()): Evaluates the active workflow template and dispatches to one of:Route Trigger Description TDD Loop active_workflow == "tdd"Autonomous test-driven development cycle — write test, run, fix, repeat Collaborative template.type == "collaborative"Panel of agents contribute in parallel rounds Coordinated template.type == "coordinated"Phase-aware DAG execution with shared blackboard Development template.type == "development"Full orchestration: decompose → route → execute → supervise → aggregate Default No matching template TaskAnalyzerdecides: simple conversation or full orchestration -
Agent Loop (ReAct): The core execution unit. Each agent follows Reasoning → Action → Observation → Adjust. The loop calls
execute_agent_loop()inorchestration/loop.py, which:- Builds tool definitions and instructions from
tools/specs.py - Calls the LLM (streaming or non-streaming) with function-calling schemas
- Executes returned tool calls via
safe_tool_call() - Detects stalls (2+ iterations without file modifications → early exit)
- Supports clarification requests (
ask_clarificationpauses workflow) - Default max iterations: 8 (
MAX_AGENT_ITERATIONS)
- Builds tool definitions and instructions from
-
Tool Orchestrator:
ToolOrchestratorintools/orchestrator.pymanages token budgets per tool and coordinates approval requirements (on_approval_requiredcallback). -
Supervisor → Aggregator → Finalizer: After all subtasks execute, the
WorkflowSupervisorreviews agent assignments,ResultAggregatorsynthesizes results into a coherent response, andfinalize_workflow()persists the conversation and scorecard.
Why This Architecture¶
Layer Isolation¶
Each layer has no knowledge of layers above it. core/ doesn't import from orchestration/. orchestration/ doesn't import from desktop/. The WorkflowEvents dataclass decouples the orchestrator from any specific UI framework — PySide6, CLI, or tests all implement the same callback interface.
Workspace Isolation (PostgreSQL Schemas)¶
Each workspace is a separate PostgreSQL schema with its own tables (Conversation, Message, Workflow, User, PausedSession). The search_path mechanism routes queries transparently. This provides:
- Data isolation — no cross-workspace data leaks
- No migration conflicts — schemas are created independently
- Simple cleanup —
DROP SCHEMA ... CASCADE
Pluggable Tools and Agents¶
Tools live as standalone .py files in tools/ (global) and workspaces/<name>/tools/ (per-workspace). Loading uses decorator-based registration (@tools_registry.register("name")). Agents follow the same pattern via YAML profiles in templates/agents/ and workspaces/<name>/agents/.
Multiple Execution Strategies¶
Not every task needs full orchestration. A simple question gets a direct agent response. A git commit gets the fast direct-tool path. A complex multi-file feature gets decomposed into subtasks, routed to specialized agents, supervised, and aggregated. The routing layer adapts the execution strategy to the task complexity.