Orchestration Plan 4
Scope: Build the Spawn MCP tool and Ralph Wiggum monitor — the mechanisms for spawning sub-agents with disconnect/monitor modes and programmatically detecting stalls, missing tools, and errors (Spec §4, §5).
Spec: Orchestration Spec
Prior plan: Plan 3
Task 1 — Create the Spawn MCP Server
The Spawn MCP tool (Spec §4.1) is an MCP tool that an LLM can call to spawn a sub-agent via the UI Chat API. It supports two modes: disconnect (fire-and-forget) and monitor (Ralph Wiggum). This is a separate MCP server from forge-discovery.
-
Create directory:
mcp-servers/forge-spawn/ -
Initialize TypeScript project:
package.json,tsconfig.json -
Install dependencies:
@modelcontextprotocol/sdk,eventsource,dotenv -
Create entry point:
src/index.ts— MCP server using Streamable HTTP transport -
Register the
spawn_agenttool with parameters (Spec §4.1):Parameter Type Description agent_id string Target agent ID task_prompt string The task to execute conversation_id string "new"or existing UUID for continuationmode enum disconnect|monitorrequired_tools string[] Tools the sub-agent must call (for Ralph Wiggum validation) max_duration_seconds number Stall timeout (for Ralph Wiggum) -
Return type (Spec §4.1):
Field Type Description conversation_id UUID The LibreChat conversation ID stream_id UUID Same as conversation_id (for SSE subscription) status string "started" -
The spawn tool must import and use the same
AuthManagerandChatClientfrom the orchestrator service (or reimplement them — they’re small). The MCP server needs its own JWT auth lifecycle, including browser User-Agent headers on all requests and ADMIN role for the service account (Spec §1.5). -
Add the MCP server to
Forge/Configs/LibreChat_Service/librechat.yamlas an MCP server entry
Deliverable: Spawn MCP server with the spawn_agent tool registered and callable.
Task 2 — Implement Disconnect Mode
Disconnect mode (Spec §4.1 Mode 1): spawn the sub-agent, record the
conversationId, then disconnect. The caller checks for completion later.
- In
spawn_agenthandler, whenmode === "disconnect":- Call
ChatClient.invokeAgent()with the provided parameters - Create an
AgentJobrecord in Postgres with statusrunning - Return
{ conversation_id, stream_id, status: "started" }immediately
- Call
- Add a
check_jobtool to the MCP server:- Parameters:
job_idorconversation_id - Queries
AgentJobtable for status - If still running, also calls
ChatClient.checkStatus(conversationId)for live status - Returns job status, conversation_id, and if completed, a summary
- Parameters:
- Test: spawn an agent in disconnect mode, verify job is created, poll until completion, verify final status
Deliverable: Disconnect mode working end-to-end — spawn, track, check completion.
Task 3 — Implement Ralph Wiggum Monitor
The Ralph Wiggum monitor (Spec §5) subscribes to a running agent’s SSE stream, watches behavior in real-time, and intervenes when needed. This is TypeScript code monitoring via SSE events, not an LLM monitoring another LLM (Spec §5 intro).
-
In
spawn_agenthandler, whenmode === "monitor":- Call
ChatClient.invokeAgent()with the provided parameters - Create an
AgentJobrecord with statusrunning - Subscribe to SSE stream via
ChatClient.subscribeToStream()
- Call
-
Monitoring behavior (Spec §5.1):
- Track tool calls made (via
on_run_stepevents withstepDetails.type: "tool_calls") - Track token output progress (via
on_message_deltaevents) - Track completion (via
finalevent) - Track last event timestamp for stall detection
- Track tool calls made (via
-
Stall detection: if no events received for
max_duration_seconds, trigger intervention -
Intervention conditions (Spec §5.2):
Condition Action No events for max_duration_secondsAbort → restart in fresh conversation with context: “Previous attempt stalled. Resume from: [state summary]“ Agent completes but didn’t call a required tool Continue in same conversation: “You must call {tool_name} before finishing. Current state: [state]“ Agent errors out Check partial work in MongoDB. If yes, continue same conversation. If no, restart fresh Agent times out (generation-level) Abort → restart fresh with filesystem state context Maximum retries exceeded (default: 3) Append [ ] 🚫 item to Forge/Output/Erik_Todo.md, notify user -
Continuation strategy (Spec §5.3):
- Same conversation (preferred when partial work exists): pass existing
conversationId+parentMessageIdfrom last assistant message - Fresh conversation (when previous attempt corrupted):
conversationId: "new"with summary of task + current state in prompt
- Same conversation (preferred when partial work exists): pass existing
-
Context is a cache, not state (Spec §5.4): the agent must reconstruct its situation from filesystem and database state alone. The monitor doesn’t pass accumulated context; it relies on the filesystem as source of truth.
-
The monitor runs as an async loop in the MCP server process. On completion, it updates the
orchestration_jobsrecord and returns the result.
Deliverable: Ralph Wiggum monitor that tracks SSE events, detects stalls, and intervenes with abort/restart.
Task 4 — Deploy forge-spawn MCP to Railway
- Create
Dockerfilefor the spawn MCP server - Create the Railway service:
- Name:
forge-spawn-mcp - Environment variables:
LIBRECHAT_URL,LIBRECHAT_EMAIL,LIBRECHAT_PASSWORD,FORGE_DB_URL(Postgres),PORT - The
LIBRECHAT_EMAILaccount must have ADMIN role in LibreChat (Spec §1.5)
- Name:
- Deploy and verify:
- MCP server is reachable at its internal URL
- LibreChat picks up the MCP configuration
spawn_agenttool appears in agent tool lists
- End-to-end test: from a LibreChat chat, call
spawn_agentin disconnect mode → agent runs → check AgentJob status - End-to-end test: from a LibreChat chat, call
spawn_agentin monitor mode → agent runs → monitor tracks → completion detected
Deliverable: forge-spawn MCP deployed and functional with both disconnect and monitor modes.