Architecture: Task Builder -- Visual Workflow Editor with MongoDB Persistence
Decisionβ
| Alternative | Pros | Cons | Decision |
|---|---|---|---|
| MongoDB as source of truth with YAML seeding (chosen) | Dynamic CRUD, no redeploy needed, seeding preserves existing workflows | Requires MongoDB dependency | Selected |
| YAML file only | Simple, version-controlled | Requires rebuild/redeploy for changes, no multi-user | Rejected |
| Git-backed YAML with auto-sync | Version-controlled, familiar workflow | Complex sync logic, merge conflicts | Rejected |
| Repurpose existing agent_skills collection | Reuses existing infrastructure | Different schema/purpose, migration risk | Rejected |
Solution Architectureβ
Data Flowβ
First Boot:
task_config.yaml ββseedβββΆ MongoDB (task_configs collection)
βββ POST /api/task-configs/seed
βββ Idempotent: skips if collection is non-empty
βββ Marks as is_system: true, owner_id: "system"
UI Workflow:
Task Builder βββΆ /api/task-configs (CRUD) βββΆ MongoDB
βββ POST: create new workflow
βββ PUT: update (owner or admin only)
βββ DELETE: remove (owner or admin, not system configs)
βββ GET: list visible configs (system + own + shared)
βββ GET ?format=yaml: export in task_config.yaml format
Supervisor:
deep_agent_single.py ββpymongoβββΆ MongoDB (primary)
ββfallbackβββΆ task_config.yaml (if MongoDB down)
βββ In-memory TTL cache (default 60s)
βββ invoke_self_service_task works identically with both sources
MongoDB Schemaβ
Collection: task_configs
interface TaskConfig {
id: string; // "task-config-<timestamp>-<random>"
name: string; // unique workflow name
category: string; // e.g., "GitHub Operations"
description?: string;
tasks: TaskStep[]; // ordered workflow steps
owner_id: string; // "system" or user email
is_system: boolean; // true for YAML-seeded
visibility: "private" | "team" | "global";
shared_with_teams?: string[];
metadata?: {
env_vars_required?: string[];
estimated_duration?: string;
tags?: string[];
};
created_at: Date;
updated_at: Date;
}
interface TaskStep {
display_text: string; // UI label
llm_prompt: string; // LLM instructions with variable substitution
subagent: string; // target subagent (caipe, github, etc.)
}
Indexes: name (unique), category, owner_id, is_system, created_at (descending)
Visual Flow Editorβ
Built with @xyflow/react, the Task Builder provides a visual canvas:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Toolbar (two-row) β
β [Name] [Category] [Description] β
β [Import βΎ] [Preview] [Download] [Save] β
ββββββββββββ¬βββββββββββββββββββββββ¬ββββββββββββββββββββ€
β Step β β Property Editor β
β Palette β Flow Canvas β ββββββββββββββββ β
β βββββββββ β β β display_text β β
β Search β ββββββββ β β llm_prompt β β
β βββββββ β β Step1 βββββ β β subagent β β
β CAIPE β ββββββββ β β β (dropdown) β β
β GitHub β ββββββββ β ββββββββββββββββ β
β Jira β β Step2 ββββ β β
β ArgoCD β ββββββββ β β Env Vars Panel β
β AWS β ββββββββ β β ββββββββββββββββ β
β ... β β Step3 βββββββ β β VAR1: step 1 β β
β (154 β ββββββββ β β VAR2: step 2 β β
β tools) β β ββββββββββββββββ β
ββββββββββββ΄βββββββββββββββββββββββ΄ββββββββββββββββββββ
Node types (color-coded, theme-aware via useTheme()):
- UserInput (yellow):
subagent: "caipe"-- collects user input - Generate (purple): processing subagents (github, backstage, jira, etc.)
- Output (green): notification/completion steps
Layout: S-curve pattern with bezier edges; nodes alternate left-right.
Key UX Featuresβ
| Feature | Implementation |
|---|---|
| Step Templates palette | 154 draggable tool templates, searchable, categorized by agent |
| CAIPE Form Builder | Structured form editor for caipe subagent steps |
| File I/O visualization | Nodes show file read/write badges; shared-file edges highlighted green |
| Unsaved changes guard | Zustand unsaved-changes-store.ts + GuardedLink wrapper; in-app dialog |
| Import dialog | Load from MongoDB, upload YAML, or import from HTTP URL |
| YAML preview/export | Syntax-highlighted preview with copy/download; js-yaml format |
| Workflow templates | Template picker dialog when creating new workflow |
| Clone workflow | Clone button on existing workflow cards |
Supervisor Integrationβ
def load_task_config():
if os.getenv("MONGODB_URI"):
configs = _load_from_mongodb() # pymongo query
if configs:
_CACHE[key] = (configs, time.time()) # TTL cache
return configs
return _load_from_yaml() # fallback
The shared pymongo client (mongodb_client.py) provides a singleton connection.
Components Changedβ
| File | Description |
|---|---|
ui/src/types/task-config.ts | TaskConfig and TaskStep interfaces |
ui/src/app/api/task-configs/route.ts | CRUD API with validation, auth, YAML export |
ui/src/app/api/task-configs/seed/route.ts | Idempotent YAML seeding endpoint |
ui/src/store/task-config-store.ts | Zustand store for client-side task config state |
ui/src/app/(app)/task-builder/page.tsx | Main Task Builder page |
ui/src/components/task-builder/TaskBuilderCanvas.tsx | React Flow canvas with S-curve layout |
ui/src/components/task-builder/TaskStepNode.tsx | Custom node component with subagent badges |
ui/src/components/task-builder/TaskBuilderSidebar.tsx | Property editor sidebar |
ui/src/components/task-builder/TaskBuilderToolbar.tsx | Two-row toolbar with metadata and actions |
ui/src/components/task-builder/StepPalette.tsx | 154 draggable tool templates |
ai_platform_engineering/utils/mongodb_client.py | Shared pymongo client singleton |
ai_platform_engineering/multi_agents/platform_engineer/deep_agent_single.py | Modified load_task_config() for MongoDB-first with YAML fallback |
Relatedβ
- Spec: spec.md