Overview
ManyAI Desktop separates its tab types into two categories: built-in modules (IRC, RSS, Terminal, Programming) and file-backed workflows (coding, image, reasoning, etc.). Built-ins are toggled via Settings → Built-in and are never shown in the New Tab picker. File-backed workflows appear in the picker and can be created, edited, and deleted by the user.
WorkflowPlugin Interface
interface WorkflowPlugin {
type: string; // unique identifier, e.g. 'coding'
label: string; // display name shown on tab
icon: string; // emoji or icon
description: string; // shown in workflow picker
defaultRoutes: RouteEntry[]; // ordered provider chain
workflowType: WorkflowType[]; // required model capabilities
}
interface RouteEntry {
provider: string;
model: string;
enabled?: boolean;
instanceId?: string; // stable GUID — survives reorder, resets on delete+re-add
}
Built-in Modules (4) — Settings → Built-in tab
These are modular features, not workflows. They are defined in SYSTEM_TYPES and excluded from the workflow picker by enabledUserWorkflows(). Each has a checkbox in Settings → Built-in. Checking opens a tab of that type; unchecking closes all open tabs of that type. Toggle state is derived live from tabs.some(t => t.workflowType === type) — no separate persistence flag.
| Type | Label | Use Case | Notes |
|---|---|---|---|
irc | IRC 💬 | IRC client | Raw TCP via main process; publishes to workflowBus |
rss | RSS 📰 | RSS feed reader | Publishes to workflowBus |
terminal | Terminal 🖥️ | SSH/Telnet/SFTP/FTP client | xterm.js + ssh2 + basic-ftp |
programming | Programming ⚙️ | Autonomous coding agent | agentLoop — 9 native tools + dynamic MCP tools; file tree with Browse + Refresh; max 20 iterations |
File-backed Workflows (6) — appear in New Tab picker
Seeded to {workingDir}/workflows/*.json on first run. User-editable via Settings → Workflows. The picker uses enabledUserWorkflows() which filters out SYSTEM_TYPES so built-ins never appear here.
| Type | Label | Use Case | Default Routes |
|---|---|---|---|
image | Image | Image generation | pollinations/flux |
coding | Code | Code generation and explanation | mistral, openai, anthropic |
reasoning | Reasoning | Deep analysis and logic | sambanova, anthropic, openai |
creative | Creative | Writing and brainstorming | mistral, anthropic, openai |
summarization | Summarize | Long text compression | gemini, cohere, groq |
translation | Translate | Language translation | gemini, mistral |
Custom Workflows
Created via Settings → Workflows. Stored as JSON files in the working directory and loaded by lib/workflows.ts at startup. Custom workflows can define: a custom system prompt, provider chain, and workflowType array. They appear alongside the 6 built-in file-backed types in the New Tab picker.
Capability Gating
Each model in a providers/*.json file has a capabilities[] array. A model is only offered for a workflow if its capabilities include all values in that workflow's workflowType array. This prevents mismatched routing — for example, a text-only model will never appear in the image workflow's provider list.
enabledUserWorkflows()
Exported from lib/workflows.ts. Returns loadWorkflows().filter(w => w.enabled && !SYSTEM_TYPES.has(w.type)). Used by RightPanel to populate the New Tab workflow picker. Built-in module types are always excluded regardless of their enabled state.
WORKFLOW_REGISTRY
workflows/index.ts is the single source of truth for all registered plugins. Custom workflows are merged at load time via lib/workflows.ts. The registry drives tab rendering, the New Tab picker, and routing resolution.
Adding a New File-backed Workflow
- Create
src/renderer/src/workflows/myworkflow.tsexporting aWorkflowPlugin. - Import it in
workflows/index.tsand add toWORKFLOW_REGISTRY. - Ensure the type is NOT in
SYSTEM_TYPES— it will then appear in the picker automatically.
Adding a New Built-in Module
- Add the type string to
SYSTEM_TYPESinlib/workflows.ts. - Add a checkbox entry in
settings/SettingsScreen.tsx→BuiltinSettingscomponent. - Add the rendering branch in
App.tsxtab content area. - Wire up any required IPC in
src/main/ipc/.