reply
Provide clarification or additional information to continue conversations with AI agents, enabling bidirectional collaboration until tasks are completed.
Instructions
Reply to an agent that is waiting for clarification. Continues the conversation until the agent returns a result or asks another question.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| agentId | Yes | Session ID returned from spawn_agent | |
| message | Yes | Clarification or additional information to send to the agent |
Implementation Reference
- src/tools/reply.ts:18-148 (handler)The handler implementation for the "reply" tool, which processes incoming messages, triggers agent execution, and handles conversation state updates.
async (params) => { const { agentId, message } = params; const session = sessionManager.getSession(agentId); if (!session) { return { content: [ { type: 'text' as const, text: JSON.stringify({ error: `Session "${agentId}" not found. It may have already completed or been killed.`, }), }, ], isError: true, }; } if (session.status !== 'waiting_for_reply') { return { content: [ { type: 'text' as const, text: JSON.stringify({ error: `Session "${agentId}" is not waiting for a reply. Current status: ${session.status}`, agentId, status: session.status, }), }, ], isError: true, }; } sessionManager.addConversation(agentId, { role: 'host', message }); const updatedSession = sessionManager.getSession(agentId)!; const prompt = buildReplyPrompt(updatedSession.conversation, message); const profile = getAgentProfile(session.agent); if (!profile) { sessionManager.updateStatus(agentId, 'error'); return { content: [ { type: 'text' as const, text: JSON.stringify({ error: `Agent profile "${session.agent}" no longer found.`, agentId, }), }, ], isError: true, }; } sessionManager.updateStatus(agentId, 'working'); let result; try { result = await runAgent(profile, prompt, { timeoutMs: session.timeout, model: session.model }); } catch (err) { sessionManager.updateStatus(agentId, 'error'); return { content: [ { type: 'text' as const, text: JSON.stringify({ error: `Agent process failed: ${err instanceof Error ? err.message : String(err)}`, agentId, }), }, ], isError: true, }; } if (result.timedOut) { sessionManager.updateStatus(agentId, 'error'); return { content: [ { type: 'text' as const, text: JSON.stringify({ error: `Agent timed out after ${session.timeout}ms`, agentId, }), }, ], isError: true, }; } const parsed = parseAgentOutput(result.stdout); if (parsed.type === 'question') { sessionManager.updateStatus(agentId, 'waiting_for_reply'); sessionManager.addConversation(agentId, { role: 'agent', message: parsed.message }); return { content: [ { type: 'text' as const, text: JSON.stringify({ agentId, status: 'waiting_for_reply', question: parsed.message, }), }, ], }; } sessionManager.updateStatus(agentId, 'done'); sessionManager.addConversation(agentId, { role: 'agent', message: parsed.message }); return { content: [ { type: 'text' as const, text: JSON.stringify({ agentId, status: 'done', result: parsed.message, }), }, ], }; } ); - src/tools/reply.ts:9-149 (registration)Registration of the "reply" tool within the MCP server.
export function registerReply(server: McpServer, sessionManager: SessionManager): void { server.tool( 'reply', 'Reply to an agent that is waiting for clarification. Continues the conversation until the agent returns a result or asks another question.', { agentId: z.string().describe('Session ID returned from spawn_agent'), message: z.string().describe('Clarification or additional information to send to the agent'), }, { readOnlyHint: false, destructiveHint: false }, async (params) => { const { agentId, message } = params; const session = sessionManager.getSession(agentId); if (!session) { return { content: [ { type: 'text' as const, text: JSON.stringify({ error: `Session "${agentId}" not found. It may have already completed or been killed.`, }), }, ], isError: true, }; } if (session.status !== 'waiting_for_reply') { return { content: [ { type: 'text' as const, text: JSON.stringify({ error: `Session "${agentId}" is not waiting for a reply. Current status: ${session.status}`, agentId, status: session.status, }), }, ], isError: true, }; } sessionManager.addConversation(agentId, { role: 'host', message }); const updatedSession = sessionManager.getSession(agentId)!; const prompt = buildReplyPrompt(updatedSession.conversation, message); const profile = getAgentProfile(session.agent); if (!profile) { sessionManager.updateStatus(agentId, 'error'); return { content: [ { type: 'text' as const, text: JSON.stringify({ error: `Agent profile "${session.agent}" no longer found.`, agentId, }), }, ], isError: true, }; } sessionManager.updateStatus(agentId, 'working'); let result; try { result = await runAgent(profile, prompt, { timeoutMs: session.timeout, model: session.model }); } catch (err) { sessionManager.updateStatus(agentId, 'error'); return { content: [ { type: 'text' as const, text: JSON.stringify({ error: `Agent process failed: ${err instanceof Error ? err.message : String(err)}`, agentId, }), }, ], isError: true, }; } if (result.timedOut) { sessionManager.updateStatus(agentId, 'error'); return { content: [ { type: 'text' as const, text: JSON.stringify({ error: `Agent timed out after ${session.timeout}ms`, agentId, }), }, ], isError: true, }; } const parsed = parseAgentOutput(result.stdout); if (parsed.type === 'question') { sessionManager.updateStatus(agentId, 'waiting_for_reply'); sessionManager.addConversation(agentId, { role: 'agent', message: parsed.message }); return { content: [ { type: 'text' as const, text: JSON.stringify({ agentId, status: 'waiting_for_reply', question: parsed.message, }), }, ], }; } sessionManager.updateStatus(agentId, 'done'); sessionManager.addConversation(agentId, { role: 'agent', message: parsed.message }); return { content: [ { type: 'text' as const, text: JSON.stringify({ agentId, status: 'done', result: parsed.message, }), }, ], }; } ); }