# How AionUi's WorkerManage Spawns and Manages AI Agent Worker Processes (Gemini, Codex, ACP)

> Discover how AionUi's WorkerManage creates and controls AI agent processes like Gemini, Codex, and ACP using Electron's utilityProcess.fork for efficient agent lifecycle management.

- Repository: [OfficeAI/AionUi](https://github.com/iofficeai/aionui)
- Tags: internals
- Published: 2026-02-19

---

**AionUi's `WorkerManage` singleton spawns isolated child processes for each AI agent (Gemini, Codex, ACP) via Electron's `utilityProcess.fork`, caching active workers in a `taskList` array and orchestrating their lifecycle through type-specific `AgentManager` classes that communicate via a promise-based IPC protocol.**

AionUi implements a robust multi-process architecture to isolate AI model execution from the main Electron thread. The `WorkerManage` class located in [`src/process/WorkerManage.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/process/WorkerManage.ts) serves as the central orchestrator for spawning and managing separate worker processes. This design ensures that native WASM binaries and long-running LLM operations do not block the UI while maintaining clean inter-process communication channels.

## The WorkerManage Singleton Architecture

The `WorkerManage` singleton acts as the primary registry for all active AI agent processes. It maintains an in-memory cache of running tasks and exposes methods for creating, retrieving, and terminating worker instances.

### Creating Typed Agent Managers via buildConversation

The entry point for spawning workers is the `buildConversation()` method. This function receives a `TChatConversation` record and instantiates the appropriate manager based on `conversation.type`.

When `conversation.type` equals `'gemini'`, `'codex'`, or `'acp'`, `WorkerManage` constructs `GeminiAgentManager`, `CodexAgentManager`, or `AcpAgentManager` respectively. Each manager extends `BaseAgentManager` and embeds a `ForkTask` instance that launches the actual child process.

Source: [`src/process/WorkerManage.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/process/WorkerManage.ts) (lines 47-99)

### Caching and Task Lookup

All alive managers are stored in the private `taskList` array. The cache can be bypassed using the `skipCache` option when rebuilding conversations.

To retrieve a running manager, use `getTaskById()` for synchronous lookup or `getTaskByIdRollbackBuild()` for asynchronous fallback. The latter rebuilds the manager from the SQLite database or local chat-history file when the cache is empty, ensuring conversation persistence across app restarts.

Source: [`src/process/WorkerManage.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/process/WorkerManage.ts) (lines 28-60)

### Termination and Cleanup

The `kill(id)` method locates the manager by conversation ID, invokes its `task.kill()` method (which delegates to the underlying `ForkTask`), and removes the entry from `taskList`. For bulk cleanup during application shutdown, `clear()` iterates over all cached tasks, invokes `kill()` on each, and empties the array.

Source: [`src/process/WorkerManage.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/process/WorkerManage.ts) (lines 62-77)

## ForkTask - The Process Spawning Engine

The `ForkTask` class in [`src/worker/fork/ForkTask.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/worker/fork/ForkTask.ts) handles the low-level mechanics of spawning Node.js child processes using Electron's `utilityProcess` API.

### Working Directory Resolution for Packaged Apps

In packaged Electron applications, workers must execute from the `app.asar.unpacked` directory to access native WASM binaries required by `aioncli-core`. The `getWorkerCwd()` method determines the correct working directory dynamically, ensuring binary portability across development and production environments.

### Electron utilityProcess and Message Protocol

The core spawning logic uses `utilityProcess.fork(this.path, [], { cwd })` to launch worker scripts such as [`src/worker/gemini.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/worker/gemini.ts). Parent and child processes communicate through a lightweight protocol featuring `type`, `data`, and optional `pipeId` fields.

The `postMessagePromise()` method implements RPC-style communication: it sends a request to the child process and returns a Promise that resolves or rejects upon receiving the corresponding response. This enables clean asynchronous operations for commands like `start`, `confirm`, and custom tool executions.

### Graceful Shutdown

The `kill()` method forwards the termination signal to `fcp.kill()`, deregisters the `process.on('exit')` listener, and ensures no orphaned processes remain when closing conversations or quitting the application.

## Agent-Specific Manager Implementations

Each AI provider implements a specialized manager extending `BaseAgentManager`, which internally creates a `ForkTask` pointing to its dedicated worker script.

### GeminiAgentManager

Located in [`src/process/task/GeminiAgentManager.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/process/task/GeminiAgentManager.ts), this manager handles the Google Gemini SDK integration. It builds system prompts, manages tool-confirmation UI flows, supports auto-approval modes (`yolo`, `autoEdit`), and streams responses back to the renderer process.

### CodexAgentManager

Found in [`src/process/task/CodexAgentManager.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/process/task/CodexAgentManager.ts), this manager wraps the OpenAI SDK and mirrors Gemini's lifecycle architecture. It handles message processing, cron-command detection, and auto-approval workflows for the Codex model.

### AcpAgentManager

The `AcpAgentManager` in [`src/process/task/AcpAgentManager.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/process/task/AcpAgentManager.ts) implements the Model-Context-Protocol (MCP) bridge. It manages `set_mode` commands, tool call executions, and session persistence for the ACP agent type.

## Complete Lifecycle Example

The following TypeScript example demonstrates the full lifecycle of creating, using, and terminating a Gemini worker:

```typescript
import WorkerManage from '@/process/WorkerManage';

// 1️⃣ Build (or reuse) a Gemini conversation
const geminiTask = WorkerManage.buildConversation({
  id: 'conv-123',
  type: 'gemini',
  extra: {
    workspace: '/Users/me/projects/foo',
    presetRules: 'You are a helpful assistant.',
    enabledSkills: ['cron'],
    sessionMode: 'default',
  },
  model: { provider: 'gemini', model: 'gemini-1.5-pro' }
});

// 2️⃣ Send a user message to the worker
await geminiTask.sendMessage({
  input: 'Create a React component that shows a countdown timer.',
  msg_id: 'msg-001'
});

// 3️⃣ List all active workers (useful for debugging UI)
console.log(WorkerManage.listTasks());
// → [{ id: 'conv-123', type: 'gemini' }, …]

// 4️⃣ Terminate a specific worker
WorkerManage.kill('conv-123');

// 5️⃣ Flush everything (e.g., on app shutdown)
WorkerManage.clear();

```

## Summary

- **WorkerManage** acts as a singleton registry in [`src/process/WorkerManage.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/process/WorkerManage.ts), caching active agent managers in the `taskList` array and providing methods like `buildConversation()` and `kill()`.
- **Agent managers** (`GeminiAgentManager`, `CodexAgentManager`, `AcpAgentManager`) extend `BaseAgentManager` and embed a `ForkTask` to isolate each AI provider in its own process.
- **ForkTask** in [`src/worker/fork/ForkTask.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/worker/fork/ForkTask.ts) spawns child processes using `utilityProcess.fork()` with proper working directory handling via `getWorkerCwd()` for packaged apps.
- **RPC communication** occurs via `postMessagePromise()`, implementing a promise-based message protocol with `type`, `data`, and `pipeId` fields for bi-directional IPC.
- **Lifecycle management** includes `getTaskById()` for retrieval, `getTaskByIdRollbackBuild()` for persistent state recovery, `kill()` for individual termination, and `clear()` for bulk cleanup during shutdown.

## Frequently Asked Questions

### How does AionUi ensure worker processes can access native binaries in production?

AionUi uses the `getWorkerCwd()` method within `ForkTask` to detect packaged environments and set the working directory to `app.asar.unpacked`. This ensures that native WASM binaries used by `aioncli-core` remain accessible to forked worker processes, as these binaries cannot be executed from within the asar archive.

### What happens if a conversation is reopened after the app restarts?

The `getTaskByIdRollbackBuild()` method in `WorkerManage` handles cache misses by asynchronously rebuilding the agent manager from the SQLite database or local chat-history file. This ensures that conversation state persists even when the `taskList` cache is cleared during application restarts.

### Can multiple AI agents run simultaneously in AionUi?

Yes. `WorkerManage` maintains all active agents in the `taskList` array, allowing concurrent execution of Gemini, Codex, and ACP workers. Each operates in its own isolated process via separate `ForkTask` instances, preventing interference between different AI model executions.

### How does the IPC protocol handle asynchronous responses from workers?

The `postMessagePromise()` method in `ForkTask` implements a request-response correlation using unique message identifiers. When the parent sends a command like `start` or `confirm`, it returns a Promise that resolves upon receiving the corresponding response from the child process, enabling clean async/await patterns across process boundaries.