← Home System Overview Architecture Data Pipeline Health System Usage System Workflows MCP Tools

Data Pipeline — ManyAI Desktop

Blueprint · Last updated 2026-05-03

Message Flow

User types a message in ChatScreen, which triggers a workflow-specific provider chain. The RouteEntry chain is iterated in order, with callProvider() sending the request. On failure, the system tries the next entry in the chain. Responses are streamed to the chat UI in real-time. For multi-step execution, the agent loop handles sequential processing.

Manual Routing Pipeline

Per-workflow RouteEntry chains are stored in localStorage for built-in workflows and JSON files for custom workflows.

resolveProvider() checks each entry in order:

  1. Provider has a key or is keyless
  2. Provider is not disabled
  3. Model capabilities include all required workflowType values

Returns the first matching entry or null if nothing is usable.

Smart Routing Pipeline (opt-in)

Replaces the manual chain when smartRouting is enabled for a workflow. scoreProvider() calculates a 0–1 score:

score = successRate(last 20 calls) × 0.7
      + speedScore(avgLatencyMs / 30000, capped) × 0.3
      − healthPenalty(from healthCheck)

Three modes:

Image Generation Path

callImageProvider.ts handles image workflows separately, routing to Pollinations (free, no key required) or DALL·E based on available keys. Responses are rendered inline in the chat UI and can be downloaded.

File Attachment

fileHandler.ts processes attached files:

  1. Reads file content (text, source code, etc.)
  2. Injects content silently into every subsequent message until detached
  3. Auto-saves AI-generated code responses to a .tmp file in the working directory

Agent Loop

lib/agentLoop.ts implements a tool-use agent using the OpenAI tool_calls API. The AI receives a merged set of tool definitions and can request tool executions in its response. The loop executes the requested tools and feeds results back until the model produces a plain-text response with no tool calls. Maximum 20 iterations per run; 10-minute timeout per API call.

Native Tools (9)

ToolDescription
read_file(path)Reads a file from the filesystem via window.api
write_file(path, content)Writes or overwrites a file with full content
rename_file(old_path, new_path)Moves/renames a file; creates destination parent dirs automatically
delete_file(path)Permanently deletes a file
list_directory(path)Returns a recursive directory tree as formatted text
create_directory(path)Creates a directory and any missing parents (mkdir -p)
search_web(query)Searches the web via Jina Search (s.jina.ai/?q=) — no API key required
fetch_url(url)Fetches a URL as readable text via Jina Reader (r.jina.ai/<url>)
read_image(path)Loads a local image (jpeg/png/gif/webp) and injects it as a vision message

Dynamic MCP Tools

At the start of every agent run, window.api.listTools() is called to discover all tools from connected MCP servers. These are merged with the 9 native tools and sent to the model. MCP tools are prefixed mcp__<server>__<tool>. See MCP Tools blueprint for details.

Vision Injection

read_image returns a sentinel string __IMG__:<dataUri>. The loop handles this specially:

  1. Pushes a text tool result ("Image loaded.") to satisfy the API's tool result requirement
  2. Pushes a separate user message with a image_url content block containing the base64 data URI

This works around the OpenAI API constraint that tool result messages cannot contain image content.

File-Based Logging (src/main/ipc/fileIpc.ts)

Conversation and tool activity are written to plain-text log files in the working directory. SQLite (userData/manyai.db) is reserved for configuration only — no logging tables.

Log Layout

{workingDir}/logs/{workflowType}/YYYY-MM-DD.log

When a file exceeds 512 KB, subsequent writes go to YYYY-MM-DD-2.log, then YYYY-MM-DD-3.log, etc. A new rotation file is only created when the current one also exceeds 512 KB — appending always targets the latest file with remaining space.

IPC Handler

ChannelDescription
log-messageAppends one entry to the appropriate log file. Args: workingDir, type, role, content, meta?

Entry Format

Each entry uses a friendly section header:

****************************************
User Posted Content   [2026-05-03 14:22:11]
****************************************

[user text]

****************************************
Answer from Provider — gemini/gemini-2.5-flash-lite (1842ms)   [2026-05-03 14:22:13]
****************************************

[assistant response]

Logging Points