interact
Control AI agents in cmuxlayer by sending messages, interrupting tasks, switching models, resuming sessions, running skills, or checking usage. Manage agent interactions through direct commands.
Instructions
Send a message to an agent, or perform an agent action (interrupt, model switch, resume, skill, usage). If the agent is alive, sends directly. If not found, returns an error — use spawn_agent first.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| agent | Yes | Agent ID (from spawn_agent or list_agents) | |
| action | Yes | Action to perform | |
| text | No | Text to send (required for action=send) | |
| model | No | Model to switch to (required for action=model) | |
| session_id | No | Session ID to resume (optional for action=resume) | |
| command | No | Slash command to run (required for action=skill) |
Implementation Reference
- src/server.ts:953-1107 (handler)The `interact` tool definition and its handler logic, which dispatches various agent actions based on the provided input.
server.tool( "interact", "Send a message to an agent, or perform an agent action (interrupt, model switch, resume, skill, usage). If the agent is alive, sends directly. If not found, returns an error — use spawn_agent first.", { agent: z .string() .describe("Agent ID (from spawn_agent or list_agents)"), action: z .enum([ "send", "interrupt", "model", "resume", "skill", "usage", "mcp", ]) .describe("Action to perform"), text: z .string() .optional() .describe("Text to send (required for action=send)"), model: z .string() .optional() .describe("Model to switch to (required for action=model)"), session_id: z .string() .optional() .describe("Session ID to resume (optional for action=resume)"), command: z .string() .optional() .describe("Slash command to run (required for action=skill)"), }, async (args) => { try { // Runtime validation per action (Decision 2) switch (args.action) { case "send": if (!args.text) { return err( new Error( "text is required for action=send. Provide the message to send to the agent.", ), ); } break; case "model": if (!args.model) { return err( new Error( "model is required for action=model. Provide the model name to switch to (e.g. 'sonnet', 'opus').", ), ); } break; case "skill": if (!args.command) { return err( new Error( "command is required for action=skill. Provide the slash command (e.g. '/commit', '/review').", ), ); } break; // interrupt, resume, usage, mcp — no extra fields required } // Resolve agent const agent = engine.getAgentState(args.agent); if (!agent) { return err( new Error( `Agent not found: "${args.agent}". Use list_agents to see available agents, or spawn_agent to create one.`, ), ); } // Dispatch action switch (args.action) { case "send": { await engine.sendToAgent(args.agent, args.text!, true); return ok({ agent_id: args.agent, action: "send", applied: true, }); } case "interrupt": { await client.sendKey(agent.surface_id, "c-c", {}); return ok({ agent_id: args.agent, action: "interrupt", applied: true, }); } case "model": { const modelCmd = `/model ${args.model}`; await engine.sendToAgent(args.agent, modelCmd, true); return ok({ agent_id: args.agent, action: "model", model: args.model, applied: true, }); } case "resume": { const resumeCmd = args.session_id ? `/resume ${args.session_id}` : "/resume"; await engine.sendToAgent(args.agent, resumeCmd, true); return ok({ agent_id: args.agent, action: "resume", session_id: args.session_id, applied: true, }); } case "skill": { await engine.sendToAgent(args.agent, args.command!, true); return ok({ agent_id: args.agent, action: "skill", command: args.command, applied: true, }); } case "usage": { // Read screen to extract usage info const screen = await client.readScreen(agent.surface_id, { lines: 5, }); return ok({ agent_id: args.agent, action: "usage", surface_id: agent.surface_id, screen_tail: screen.text, }); } case "mcp": { // Read screen for MCP server status const mcpScreen = await client.readScreen(agent.surface_id, { lines: 10, }); return ok({ agent_id: args.agent, action: "mcp", surface_id: agent.surface_id, screen_tail: mcpScreen.text, }); } } } catch (e) { return err(e);