rush-ai 0.6.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: rush-task
3
- description: " Claude Code 中创建 Rush Agent 任务并跟踪执行过程。当用户想让 Rush Agent(如 UI 生成、代码分析、文档撰写等)执行任务时使用此 Skill。"
4
- version: 0.2.0
3
+ description: "Create and track tasks on the Rush platform from an IDE (Cursor, Claude Code, etc). Use this when the user wants a Rush agent to build / generate / analyze something — hand off the context you already have, then watch it run."
4
+ version: 0.3.0
5
5
  author: kanyun
6
6
  tags:
7
7
  - rush
@@ -10,80 +10,87 @@ tags:
10
10
  argument-hint: <prompt>
11
11
  ---
12
12
 
13
- # Rush Task — Agent 任务执行
13
+ # Rush Task — hand off work to a Rush agent
14
14
 
15
- 你可以通过 Rush MCP 工具来创建和管理 Agent 任务。
15
+ Use this skill when the user is talking to you and the next step belongs on the Rush platform. You already have full context from the conversation; don't make them restate it.
16
16
 
17
- ## 前置条件
17
+ ## Primary path: `rush-ai` CLI
18
18
 
19
- 在执行任何操作前,确认以下条件:
20
- - MCP server "rush" 已连接(tools 列表中有 `rush_*` 开头的工具)
21
- - 如果 MCP 工具不可用,提示用户运行 `rush-ai plugin doctor` 诊断问题
19
+ The CLI is the primary interface — it works in any shell, needs no per-IDE setup, and is always in sync with the platform.
22
20
 
23
- ## 使用流程
21
+ ### Prerequisites
24
22
 
25
- ### Step 1: 列出可用 Agent
23
+ - `rush-ai` is on PATH, or you can run it via `npx rush-ai`. If neither is true, ask the user to install with `npm i -g rush-ai` (or just use `npx`).
26
24
 
27
- 调用 `rush_agent_list` 获取当前可用的 Agent 列表。
25
+ ### Canonical flow
28
26
 
29
- **失败处理:**
30
- - 如果返回鉴权错误(`Not authenticated`),提示用户运行 `rush-ai auth login`
31
- - 如果连接失败或超时,提示用户运行 `rush-ai plugin doctor` 检查配置
27
+ ```bash
28
+ # 1. Confirm auth — this MUST be the first step.
29
+ npx rush-ai auth status --json
30
+ # If the response says not authenticated: STOP. Print to the user:
31
+ # "Rush 还没登录。请在终端里跑 `npx rush-ai auth login`(会打开浏览器),登录成功后告诉我一声。"
32
+ # Do NOT run auth login yourself — it needs a browser / CAS.
32
33
 
33
- ### Step 2: 选择 Agent
34
+ # 2. (Optional) Browse the agent shelf. Start narrow, widen only if needed.
35
+ npx rush-ai agent list --default --json # just the built-in defaults
36
+ npx rush-ai agent list --search "人力" --json # fuzzy-filter by name / desc
37
+ npx rush-ai agent list --all --json # full catalog (can be long)
34
38
 
35
- - 如果只有一个 Agent,直接使用
36
- - 如果有多个 Agent,向用户展示列表(名称 + 能力描述),让用户选择
37
- - 如果没有可用 Agent,告知用户当前无可用 Agent,建议联系管理员配置
39
+ # 3. Create the task. Use --json whenever you need to parse the result.
40
+ npx rush-ai task create -a <agent> -p "<prompt synthesized from context>" --json
38
41
 
39
- ### Step 3: 执行任务(策略分流)
42
+ # 4. Poll status until it reaches a terminal state
43
+ # (completed / failed / cancelled). Poll every ~15–30s.
44
+ npx rush-ai task status <id> --json
40
45
 
41
- 根据任务复杂度选择执行策略:
46
+ # 5. Iterate on the same task — don't create a new one for tweaks.
47
+ npx rush-ai task send <id> -p "<follow-up>" --json
42
48
 
43
- **短任务(简单查询、快速操作):**
44
- 使用 `rush_task_run` 同步执行,直接返回结果。
45
- - 适用场景:用户明确说"快速"、"简单查询"、"查看状态"
49
+ # 6. If the user wants live output, stream instead of polling.
50
+ npx rush-ai task watch <id>
51
+ ```
46
52
 
47
- **长任务(复杂生成、多步骤处理):**
48
- 1. 调用 `rush_task_create` 创建异步任务
49
- 2. 调用 `rush_task_watch` 跟踪进度(默认超时 5 分钟)
50
- 3. 向用户实时展示进度信息
51
- - 适用场景:用户要求"生成"、"创建"、"分析"、"重构"
53
+ ### Which agent to pass to `-a`?
52
54
 
53
- **判断策略:**
54
- - 用户明确说"快速"、"简单查询" → 短任务(`rush_task_run`)
55
- - 用户要求"生成"、"创建"、"分析"等复杂操作 长任务(`rush_task_create`)
56
- - 不确定时默认使用异步模式(`rush_task_create`)
55
+ | Situation | Agent |
56
+ |---|---|
57
+ | The user wants a live website / landing page / marketing page — anything that ends with a shareable preview URL | `web-builder` (returns `previewUrl` + `gitRepoUrl` on completion) |
58
+ | General-purpose task (chat, analysis, generation) | `rush` (the platform default) |
59
+ | The user explicitly named a specialist agent | that agent's name verbatim (confirm with `agent list --search`) |
57
60
 
58
- ### Step 4: 获取结果
61
+ When in doubt, run `agent list --all --json` and pick by name / description. Never invent an agent name.
59
62
 
60
- - 调用 `rush_task_result` 获取最终结果
61
- - 如果任务失败,展示错误信息并建议:
62
- - 修改 prompt 重试
63
- - 检查 Agent 是否支持该类型任务
64
- - 如果有输出文件,调用 `rush_task_files` 列出并展示:
65
- - 代码文件(code):展示文件路径和内容摘要
66
- - 图片文件(image):展示 URL 供用户查看
67
- - 文档文件(document):展示内容
63
+ ### What to give the user
68
64
 
69
- ### Step 5: 后续操作
65
+ - One-liner confirmation right after `task create`: task id + "running on Rush, I'll watch it".
66
+ - When `task status` returns `completed`:
67
+ - For `web-builder`: present `previewUrl` (primary) and `gitRepoUrl`.
68
+ - For other agents: present `result`.
69
+ - If `status == failed`: surface `error` verbatim, ask whether to retry via `task send` or abort. Do not silently retry.
70
70
 
71
- - 用户可以基于结果继续对话("修改一下..."、"重新生成...")
72
- - 继续操作时创建新任务,在 prompt 中引用之前的 task_id 提供上下文
73
- - 用户可以随时用 `rush_task_cancel` 取消运行中的任务
74
- - 用 `rush_task_list` 查看历史任务
71
+ ### Anti-patterns (don't do these)
75
72
 
76
- ## 可用 MCP 工具参考
73
+ - Re-prompting the user for requirements they already stated in-thread.
74
+ - ❌ Creating a new task for every tweak — always prefer `task send <id>`.
75
+ - ❌ Running `auth login` yourself (it needs a browser).
76
+ - ❌ Ignoring `--json` when you need to parse the result — the table view is for humans.
77
77
 
78
- | 工具 | 用途 |
79
- |------|------|
80
- | `rush_agent_list` | 列出可用 Agent |
81
- | `rush_agent_info` | 获取 Agent 详细信息 |
82
- | `rush_task_run` | 同步执行任务(阻塞直到完成) |
83
- | `rush_task_create` | 创建异步任务 |
84
- | `rush_task_status` | 查询任务状态 |
85
- | `rush_task_result` | 获取任务结果 |
86
- | `rush_task_watch` | 实时跟踪任务进度(SSE) |
87
- | `rush_task_list` | 列出历史任务 |
88
- | `rush_task_files` | 列出任务输出文件 |
89
- | `rush_task_cancel` | 取消运行中的任务 |
78
+ For the complete playbook, run `npx rush-ai skill hand-off`. For sub-agent / workflow composition, run `npx rush-ai skill agent-shelf`.
79
+
80
+ ## Optional path: MCP tools
81
+
82
+ If the Rush MCP server is installed and the IDE exposes its tools (`rush_task_create`, `rush_task_status`, ...), you can use them instead of shelling out. The MCP path is functionally equivalent to the CLI path; use whichever is available. Mapping:
83
+
84
+ | CLI command | MCP tool |
85
+ |-------------|----------|
86
+ | `rush-ai agent list` | `rush_agent_list` |
87
+ | `rush-ai agent info <name>` | `rush_agent_info` |
88
+ | `rush-ai task create` | `rush_task_create` (async) / `rush_task_run` (short/sync) |
89
+ | `rush-ai task status <id>` | `rush_task_status` |
90
+ | `rush-ai task result <id>` | `rush_task_result` |
91
+ | `rush-ai task watch <id>` | `rush_task_watch` |
92
+ | `rush-ai task list` | `rush_task_list` |
93
+ | `rush-ai task files <id>` | `rush_task_files` |
94
+ | `rush-ai task cancel <id>` | `rush_task_cancel` |
95
+
96
+ If MCP tools aren't present — the common case — **just use the CLI**. Don't wait on MCP; don't try to configure it mid-conversation.
@@ -1,11 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- consumeSSEStreamWithReconnect
4
- } from "./chunk-MG4HY2PD.js";
5
- import {
3
+ consumeSSEStreamWithReconnect,
6
4
  createClient,
7
5
  getAuthToken
8
- } from "./chunk-UJLVFMWM.js";
6
+ } from "./chunk-SZO6LEQX.js";
9
7
 
10
8
  // src/commands/mcp/server.ts
11
9
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -656,4 +654,4 @@ async function startMcpServer() {
656
654
  export {
657
655
  startMcpServer
658
656
  };
659
- //# sourceMappingURL=server-MRWAFK5G.js.map
657
+ //# sourceMappingURL=server-KFDYSF4T.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/mcp/server.ts"],"sourcesContent":["import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { getAuthToken } from '../../util/auth.js';\nimport { createClient } from '../../util/client.js';\nimport {\n consumeSSEStreamWithReconnect,\n type SSEEvent,\n} from '../../util/sse.js';\nimport type { McpServer as McpRegistryServer } from './index.js';\n\ninterface AgentListResponse {\n agents: Array<{\n id: string;\n name: string;\n description: string;\n capabilities: string[];\n skillCount: number;\n mcpCount: number;\n status: string;\n }>;\n total: number;\n}\n\ninterface TaskCreateResponse {\n id: string;\n status: string;\n}\n\ninterface TaskStatusResponse {\n id: string;\n status: string;\n agent: string;\n prompt: string;\n result?: unknown;\n error?: string;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface TaskListResponse {\n tasks: TaskStatusResponse[];\n total: number;\n}\n\ninterface AgentDetailResponse {\n agent: {\n id: string;\n name: string;\n description: string | null;\n capabilities: string[] | null;\n skills: string[] | null;\n mcp_servers: unknown[] | null;\n status: string;\n visibility: string;\n provider_type: string;\n provider_model: string | null;\n system_prompt: string | null;\n created_at: string;\n updated_at: string;\n created_by_id: string | null;\n is_builtin: boolean;\n };\n}\n\ninterface TaskFile {\n id: string;\n filePath: string;\n fileName: string;\n ossPath?: string;\n ossUrl?: string;\n category: string;\n source: string;\n timestamp?: number;\n url?: string;\n conversationId?: string;\n}\n\ninterface TaskFilesResponse {\n files: TaskFile[];\n totalCount: number;\n}\n\nexport async function startMcpServer(): Promise<void> {\n const server = new Server(\n {\n name: 'rush-ai',\n version: '0.2.0',\n },\n {\n capabilities: {\n tools: {},\n },\n }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: [\n {\n name: 'rush_agent_list',\n description: 'List available Rush AI agents',\n inputSchema: {\n type: 'object' as const,\n properties: {},\n },\n },\n {\n name: 'rush_task_run',\n description:\n 'Run a task on a Rush AI agent. Creates an async task and polls until completion (up to 5 minutes).',\n inputSchema: {\n type: 'object' as const,\n properties: {\n agent: {\n type: 'string',\n description: 'Agent name',\n },\n prompt: {\n type: 'string',\n description: 'Task prompt',\n },\n skills: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional skills to add',\n },\n mcpServers: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional MCP servers to add',\n },\n timeout: {\n type: 'number',\n description:\n 'Max seconds to wait for completion (default: 300, max: 600)',\n },\n },\n required: ['agent', 'prompt'],\n },\n },\n {\n name: 'rush_task_send',\n description:\n 'Send a follow-up message to an existing task/project. Sends the message and polls until completion (up to 5 minutes).',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task/Project ID',\n },\n prompt: {\n type: 'string',\n description: 'Message to send',\n },\n skills: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional skills to add',\n },\n mcpServers: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional MCP servers to add',\n },\n timeout: {\n type: 'number',\n description:\n 'Max seconds to wait for completion (default: 300, max: 600)',\n },\n },\n required: ['id', 'prompt'],\n },\n },\n {\n name: 'rush_task_create',\n description: 'Create an asynchronous task on a Rush AI agent',\n inputSchema: {\n type: 'object' as const,\n properties: {\n agent: {\n type: 'string',\n description: 'Agent name',\n },\n prompt: {\n type: 'string',\n description: 'Task prompt',\n },\n skills: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional skills to add',\n },\n mcpServers: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional MCP servers to add',\n },\n },\n required: ['agent', 'prompt'],\n },\n },\n {\n name: 'rush_task_status',\n description: 'Get the status of a task',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_task_result',\n description: 'Get the result of a completed task',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_task_list',\n description: 'List tasks',\n inputSchema: {\n type: 'object' as const,\n properties: {\n limit: {\n type: 'number',\n description: 'Max results (default: 20)',\n },\n status: {\n type: 'string',\n description:\n 'Filter by status: pending, running, completed, failed, cancelled',\n },\n },\n },\n },\n {\n name: 'rush_task_files',\n description:\n 'List files generated by a task (code, images, documents, etc.)',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n category: {\n type: 'string',\n enum: ['code', 'image', 'document', 'other'],\n description: 'Optional filter by file category',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_task_watch',\n description:\n 'Watch task execution in real-time. Blocks until task completes or timeout. Returns accumulated events.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n timeout: {\n type: 'number',\n description: 'Max seconds to watch (default: 300, max: 600)',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_task_cancel',\n description: 'Cancel a running task',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_agent_info',\n description: 'Get detailed information about a specific agent',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Agent ID',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_mcp_list',\n description:\n 'List available MCP servers registered on the platform. Use to discover what MCP servers can be passed to the --mcp parameter when creating tasks.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n category: {\n type: 'string',\n description:\n 'Filter by category (knowledge, dev-tools, observability, data, design, ci-cd, utilities)',\n },\n search: {\n type: 'string',\n description: 'Search by name or description',\n },\n page: {\n type: 'number',\n description: 'Page number (default: 1)',\n },\n },\n },\n },\n ],\n };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const token = getAuthToken();\n if (!token) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'Error: Not authenticated. Run `rush-ai auth login` first.',\n },\n ],\n isError: true,\n };\n }\n\n const client = createClient();\n const args = (request.params.arguments ?? {}) as Record<string, unknown>;\n\n try {\n switch (request.params.name) {\n case 'rush_agent_list': {\n const { data } = await client.get<AgentListResponse>('/api/agents');\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_run': {\n // Create task via /api/tasks, then poll until completion\n const { data: created } = await client.post<TaskCreateResponse>(\n '/api/tasks',\n {\n agent: args.agent,\n prompt: args.prompt,\n skills: args.skills,\n mcpServers: args.mcpServers,\n }\n );\n\n const timeoutSec = Math.min(\n Math.max(Number(args.timeout) || 300, 1),\n 600\n );\n const deadline = Date.now() + timeoutSec * 1000;\n const TERMINAL = ['completed', 'failed', 'cancelled'];\n let status: TaskStatusResponse | null = null;\n\n while (Date.now() < deadline) {\n const { data: current } = await client.get<TaskStatusResponse>(\n `/api/tasks/${encodeURIComponent(created.id)}`\n );\n if (TERMINAL.includes(current.status)) {\n status = current;\n break;\n }\n // Poll every 2 seconds\n await new Promise((r) => setTimeout(r, 2000));\n }\n\n if (!status) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n {\n id: created.id,\n status: 'timeout',\n message: `Task did not complete within ${timeoutSec}s. Use rush_task_status to check later.`,\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n // If completed, also fetch the result\n if (status.status === 'completed') {\n try {\n const { data: resultData } = await client.get<{\n result: unknown;\n }>(`/api/tasks/${encodeURIComponent(created.id)}/result`);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { ...status, result: resultData.result },\n null,\n 2\n ),\n },\n ],\n };\n } catch {\n // Fall through to return status without result\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(status, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_send': {\n // Send message to existing task via /api/tasks/{id}/send\n const { data: sendResult } = await client.post<TaskCreateResponse>(\n `/api/tasks/${encodeURIComponent(String(args.id))}/send`,\n {\n prompt: args.prompt,\n skills: args.skills,\n mcpServers: args.mcpServers,\n }\n );\n\n const sendTimeoutSec = Math.min(\n Math.max(Number(args.timeout) || 300, 1),\n 600\n );\n const sendDeadline = Date.now() + sendTimeoutSec * 1000;\n const SEND_TERMINAL = ['completed', 'failed', 'cancelled'];\n let sendStatus: TaskStatusResponse | null = null;\n\n while (Date.now() < sendDeadline) {\n const { data: current } = await client.get<TaskStatusResponse>(\n `/api/tasks/${encodeURIComponent(sendResult.id)}`\n );\n if (SEND_TERMINAL.includes(current.status)) {\n sendStatus = current;\n break;\n }\n // Poll every 2 seconds\n await new Promise((r) => setTimeout(r, 2000));\n }\n\n if (!sendStatus) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n {\n id: sendResult.id,\n status: 'timeout',\n message: `Task did not complete within ${sendTimeoutSec}s. Use rush_task_status to check later.`,\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n // If completed, also fetch the result\n if (sendStatus.status === 'completed') {\n try {\n const { data: resultData } = await client.get<{\n result: unknown;\n }>(`/api/tasks/${encodeURIComponent(sendResult.id)}/result`);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { ...sendStatus, result: resultData.result },\n null,\n 2\n ),\n },\n ],\n };\n } catch {\n // Fall through to return status without result\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(sendStatus, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_create': {\n const { data } = await client.post<TaskCreateResponse>('/api/tasks', {\n agent: args.agent,\n prompt: args.prompt,\n skills: args.skills,\n mcpServers: args.mcpServers,\n });\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_status': {\n const { data } = await client.get<TaskStatusResponse>(\n `/api/tasks/${encodeURIComponent(String(args.id))}`\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_result': {\n const { data } = await client.get<{\n result: unknown;\n }>(`/api/tasks/${encodeURIComponent(String(args.id))}/result`);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_list': {\n const params = new URLSearchParams();\n if (args.limit) params.set('limit', String(args.limit));\n if (args.status) params.set('status', String(args.status));\n const { data } = await client.get<TaskListResponse>(\n `/api/tasks?${params.toString()}`\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_files': {\n const { data } = await client.get<TaskFilesResponse>(\n `/api/chat/${encodeURIComponent(String(args.id))}/files`\n );\n const validCategories = ['code', 'image', 'document', 'other'];\n let files = data.files;\n if (\n args.category &&\n typeof args.category === 'string' &&\n validCategories.includes(args.category)\n ) {\n files = files.filter((f) => f.category === args.category);\n }\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { files, totalCount: files.length },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n case 'rush_task_watch': {\n const TERMINAL_STATUSES = ['completed', 'failed', 'cancelled'];\n const timeoutSec = Math.min(\n Math.max(Number(args.timeout) || 300, 1),\n 600\n );\n const events: SSEEvent[] = [];\n let truncated = false;\n let watchError: string | null = null;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n truncated = true;\n controller.abort();\n }, timeoutSec * 1000);\n\n try {\n const connectFn = async () => {\n const response = await client.fetchRaw(\n `/api/tasks/${encodeURIComponent(String(args.id))}/events`,\n { method: 'GET' }\n );\n if (!response.body) throw new Error('No response body');\n return response.body;\n };\n\n await consumeSSEStreamWithReconnect(\n connectFn,\n (event) => {\n events.push(event);\n },\n {\n signal: controller.signal,\n isTerminal: (event) =>\n event.type === 'status' &&\n TERMINAL_STATUSES.includes(event.data),\n }\n );\n } catch (err) {\n if (!truncated) {\n // Real error (not timeout) — report it\n watchError = err instanceof Error ? err.message : 'Unknown error';\n }\n } finally {\n clearTimeout(timeoutId);\n }\n\n // If we got no events and there was an error, return as error\n if (events.length === 0 && watchError) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: ${watchError}`,\n },\n ],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n {\n events,\n truncated,\n eventCount: events.length,\n ...(watchError ? { error: watchError } : {}),\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n case 'rush_task_cancel': {\n await client.delete(\n `/api/tasks/${encodeURIComponent(String(args.id))}`\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { id: args.id, status: 'cancelled' },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n case 'rush_agent_info': {\n const { data } = await client.get<AgentDetailResponse>(\n `/api/agents/${encodeURIComponent(String(args.id))}`\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_mcp_list': {\n const params = new URLSearchParams();\n if (args.category) params.set('category', String(args.category));\n if (args.search) params.set('search', String(args.search));\n if (args.page) params.set('page', String(args.page));\n params.set('limit', '100');\n const { data } = await client.get<{\n data: McpRegistryServer[];\n }>(`/api/mcp-registry?${params.toString()}`);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n default:\n return {\n content: [\n {\n type: 'text' as const,\n text: `Unknown tool: ${request.params.name}`,\n },\n ],\n isError: true,\n };\n }\n } catch (err) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: ${err instanceof Error ? err.message : 'Unknown error'}`,\n },\n ],\n isError: true,\n };\n }\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/commands/mcp/server.ts"],"sourcesContent":["import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { getAuthToken } from '../../util/auth.js';\nimport { createClient } from '../../util/client.js';\nimport {\n consumeSSEStreamWithReconnect,\n type SSEEvent,\n} from '../../util/sse.js';\nimport type { McpServer as McpRegistryServer } from './index.js';\n\ninterface AgentListResponse {\n agents: Array<{\n id: string;\n name: string;\n description: string;\n capabilities: string[];\n skillCount: number;\n mcpCount: number;\n status: string;\n }>;\n total: number;\n}\n\ninterface TaskCreateResponse {\n id: string;\n status: string;\n}\n\ninterface TaskStatusResponse {\n id: string;\n status: string;\n agent: string;\n prompt: string;\n result?: unknown;\n error?: string;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface TaskListResponse {\n tasks: TaskStatusResponse[];\n total: number;\n}\n\ninterface AgentDetailResponse {\n agent: {\n id: string;\n name: string;\n description: string | null;\n capabilities: string[] | null;\n skills: string[] | null;\n mcp_servers: unknown[] | null;\n status: string;\n visibility: string;\n provider_type: string;\n provider_model: string | null;\n system_prompt: string | null;\n created_at: string;\n updated_at: string;\n created_by_id: string | null;\n is_builtin: boolean;\n };\n}\n\ninterface TaskFile {\n id: string;\n filePath: string;\n fileName: string;\n ossPath?: string;\n ossUrl?: string;\n category: string;\n source: string;\n timestamp?: number;\n url?: string;\n conversationId?: string;\n}\n\ninterface TaskFilesResponse {\n files: TaskFile[];\n totalCount: number;\n}\n\nexport async function startMcpServer(): Promise<void> {\n const server = new Server(\n {\n name: 'rush-ai',\n version: '0.2.0',\n },\n {\n capabilities: {\n tools: {},\n },\n }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: [\n {\n name: 'rush_agent_list',\n description: 'List available Rush AI agents',\n inputSchema: {\n type: 'object' as const,\n properties: {},\n },\n },\n {\n name: 'rush_task_run',\n description:\n 'Run a task on a Rush AI agent. Creates an async task and polls until completion (up to 5 minutes).',\n inputSchema: {\n type: 'object' as const,\n properties: {\n agent: {\n type: 'string',\n description: 'Agent name',\n },\n prompt: {\n type: 'string',\n description: 'Task prompt',\n },\n skills: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional skills to add',\n },\n mcpServers: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional MCP servers to add',\n },\n timeout: {\n type: 'number',\n description:\n 'Max seconds to wait for completion (default: 300, max: 600)',\n },\n },\n required: ['agent', 'prompt'],\n },\n },\n {\n name: 'rush_task_send',\n description:\n 'Send a follow-up message to an existing task/project. Sends the message and polls until completion (up to 5 minutes).',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task/Project ID',\n },\n prompt: {\n type: 'string',\n description: 'Message to send',\n },\n skills: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional skills to add',\n },\n mcpServers: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional MCP servers to add',\n },\n timeout: {\n type: 'number',\n description:\n 'Max seconds to wait for completion (default: 300, max: 600)',\n },\n },\n required: ['id', 'prompt'],\n },\n },\n {\n name: 'rush_task_create',\n description: 'Create an asynchronous task on a Rush AI agent',\n inputSchema: {\n type: 'object' as const,\n properties: {\n agent: {\n type: 'string',\n description: 'Agent name',\n },\n prompt: {\n type: 'string',\n description: 'Task prompt',\n },\n skills: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional skills to add',\n },\n mcpServers: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional MCP servers to add',\n },\n },\n required: ['agent', 'prompt'],\n },\n },\n {\n name: 'rush_task_status',\n description: 'Get the status of a task',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_task_result',\n description: 'Get the result of a completed task',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_task_list',\n description: 'List tasks',\n inputSchema: {\n type: 'object' as const,\n properties: {\n limit: {\n type: 'number',\n description: 'Max results (default: 20)',\n },\n status: {\n type: 'string',\n description:\n 'Filter by status: pending, running, completed, failed, cancelled',\n },\n },\n },\n },\n {\n name: 'rush_task_files',\n description:\n 'List files generated by a task (code, images, documents, etc.)',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n category: {\n type: 'string',\n enum: ['code', 'image', 'document', 'other'],\n description: 'Optional filter by file category',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_task_watch',\n description:\n 'Watch task execution in real-time. Blocks until task completes or timeout. Returns accumulated events.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n timeout: {\n type: 'number',\n description: 'Max seconds to watch (default: 300, max: 600)',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_task_cancel',\n description: 'Cancel a running task',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_agent_info',\n description: 'Get detailed information about a specific agent',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Agent ID',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_mcp_list',\n description:\n 'List available MCP servers registered on the platform. Use to discover what MCP servers can be passed to the --mcp parameter when creating tasks.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n category: {\n type: 'string',\n description:\n 'Filter by category (knowledge, dev-tools, observability, data, design, ci-cd, utilities)',\n },\n search: {\n type: 'string',\n description: 'Search by name or description',\n },\n page: {\n type: 'number',\n description: 'Page number (default: 1)',\n },\n },\n },\n },\n ],\n };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const token = getAuthToken();\n if (!token) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'Error: Not authenticated. Run `rush-ai auth login` first.',\n },\n ],\n isError: true,\n };\n }\n\n const client = createClient();\n const args = (request.params.arguments ?? {}) as Record<string, unknown>;\n\n try {\n switch (request.params.name) {\n case 'rush_agent_list': {\n const { data } = await client.get<AgentListResponse>('/api/agents');\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_run': {\n // Create task via /api/tasks, then poll until completion\n const { data: created } = await client.post<TaskCreateResponse>(\n '/api/tasks',\n {\n agent: args.agent,\n prompt: args.prompt,\n skills: args.skills,\n mcpServers: args.mcpServers,\n }\n );\n\n const timeoutSec = Math.min(\n Math.max(Number(args.timeout) || 300, 1),\n 600\n );\n const deadline = Date.now() + timeoutSec * 1000;\n const TERMINAL = ['completed', 'failed', 'cancelled'];\n let status: TaskStatusResponse | null = null;\n\n while (Date.now() < deadline) {\n const { data: current } = await client.get<TaskStatusResponse>(\n `/api/tasks/${encodeURIComponent(created.id)}`\n );\n if (TERMINAL.includes(current.status)) {\n status = current;\n break;\n }\n // Poll every 2 seconds\n await new Promise((r) => setTimeout(r, 2000));\n }\n\n if (!status) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n {\n id: created.id,\n status: 'timeout',\n message: `Task did not complete within ${timeoutSec}s. Use rush_task_status to check later.`,\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n // If completed, also fetch the result\n if (status.status === 'completed') {\n try {\n const { data: resultData } = await client.get<{\n result: unknown;\n }>(`/api/tasks/${encodeURIComponent(created.id)}/result`);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { ...status, result: resultData.result },\n null,\n 2\n ),\n },\n ],\n };\n } catch {\n // Fall through to return status without result\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(status, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_send': {\n // Send message to existing task via /api/tasks/{id}/send\n const { data: sendResult } = await client.post<TaskCreateResponse>(\n `/api/tasks/${encodeURIComponent(String(args.id))}/send`,\n {\n prompt: args.prompt,\n skills: args.skills,\n mcpServers: args.mcpServers,\n }\n );\n\n const sendTimeoutSec = Math.min(\n Math.max(Number(args.timeout) || 300, 1),\n 600\n );\n const sendDeadline = Date.now() + sendTimeoutSec * 1000;\n const SEND_TERMINAL = ['completed', 'failed', 'cancelled'];\n let sendStatus: TaskStatusResponse | null = null;\n\n while (Date.now() < sendDeadline) {\n const { data: current } = await client.get<TaskStatusResponse>(\n `/api/tasks/${encodeURIComponent(sendResult.id)}`\n );\n if (SEND_TERMINAL.includes(current.status)) {\n sendStatus = current;\n break;\n }\n // Poll every 2 seconds\n await new Promise((r) => setTimeout(r, 2000));\n }\n\n if (!sendStatus) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n {\n id: sendResult.id,\n status: 'timeout',\n message: `Task did not complete within ${sendTimeoutSec}s. Use rush_task_status to check later.`,\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n // If completed, also fetch the result\n if (sendStatus.status === 'completed') {\n try {\n const { data: resultData } = await client.get<{\n result: unknown;\n }>(`/api/tasks/${encodeURIComponent(sendResult.id)}/result`);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { ...sendStatus, result: resultData.result },\n null,\n 2\n ),\n },\n ],\n };\n } catch {\n // Fall through to return status without result\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(sendStatus, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_create': {\n const { data } = await client.post<TaskCreateResponse>('/api/tasks', {\n agent: args.agent,\n prompt: args.prompt,\n skills: args.skills,\n mcpServers: args.mcpServers,\n });\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_status': {\n const { data } = await client.get<TaskStatusResponse>(\n `/api/tasks/${encodeURIComponent(String(args.id))}`\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_result': {\n const { data } = await client.get<{\n result: unknown;\n }>(`/api/tasks/${encodeURIComponent(String(args.id))}/result`);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_list': {\n const params = new URLSearchParams();\n if (args.limit) params.set('limit', String(args.limit));\n if (args.status) params.set('status', String(args.status));\n const { data } = await client.get<TaskListResponse>(\n `/api/tasks?${params.toString()}`\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_files': {\n const { data } = await client.get<TaskFilesResponse>(\n `/api/chat/${encodeURIComponent(String(args.id))}/files`\n );\n const validCategories = ['code', 'image', 'document', 'other'];\n let files = data.files;\n if (\n args.category &&\n typeof args.category === 'string' &&\n validCategories.includes(args.category)\n ) {\n files = files.filter((f) => f.category === args.category);\n }\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { files, totalCount: files.length },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n case 'rush_task_watch': {\n const TERMINAL_STATUSES = ['completed', 'failed', 'cancelled'];\n const timeoutSec = Math.min(\n Math.max(Number(args.timeout) || 300, 1),\n 600\n );\n const events: SSEEvent[] = [];\n let truncated = false;\n let watchError: string | null = null;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n truncated = true;\n controller.abort();\n }, timeoutSec * 1000);\n\n try {\n const connectFn = async () => {\n const response = await client.fetchRaw(\n `/api/tasks/${encodeURIComponent(String(args.id))}/events`,\n { method: 'GET' }\n );\n if (!response.body) throw new Error('No response body');\n return response.body;\n };\n\n await consumeSSEStreamWithReconnect(\n connectFn,\n (event) => {\n events.push(event);\n },\n {\n signal: controller.signal,\n isTerminal: (event) =>\n event.type === 'status' &&\n TERMINAL_STATUSES.includes(event.data),\n }\n );\n } catch (err) {\n if (!truncated) {\n // Real error (not timeout) — report it\n watchError = err instanceof Error ? err.message : 'Unknown error';\n }\n } finally {\n clearTimeout(timeoutId);\n }\n\n // If we got no events and there was an error, return as error\n if (events.length === 0 && watchError) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: ${watchError}`,\n },\n ],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n {\n events,\n truncated,\n eventCount: events.length,\n ...(watchError ? { error: watchError } : {}),\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n case 'rush_task_cancel': {\n await client.delete(\n `/api/tasks/${encodeURIComponent(String(args.id))}`\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { id: args.id, status: 'cancelled' },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n case 'rush_agent_info': {\n const { data } = await client.get<AgentDetailResponse>(\n `/api/agents/${encodeURIComponent(String(args.id))}`\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_mcp_list': {\n const params = new URLSearchParams();\n if (args.category) params.set('category', String(args.category));\n if (args.search) params.set('search', String(args.search));\n if (args.page) params.set('page', String(args.page));\n params.set('limit', '100');\n const { data } = await client.get<{\n data: McpRegistryServer[];\n }>(`/api/mcp-registry?${params.toString()}`);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n default:\n return {\n content: [\n {\n type: 'text' as const,\n text: `Unknown tool: ${request.params.name}`,\n },\n ],\n isError: true,\n };\n }\n } catch (err) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: ${err instanceof Error ? err.message : 'Unknown error'}`,\n },\n ],\n isError: true,\n };\n }\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,48 @@
1
+ # Rush-ai skills for AI agents
2
+
3
+ `rush-ai` is a CLI for the Rush platform. If you are an AI agent (Cursor, Claude Code, a local sub-agent) reading this, these guides tell you when and how to invoke `rush-ai` on behalf of the user.
4
+
5
+ ## When to use rush-ai
6
+
7
+ Pick the guide that matches the situation:
8
+
9
+ - **You are in the middle of a conversation with the user (inside an IDE) and part of the work belongs on Rush.**
10
+ → Read [`hand-off.md`](./hand-off.md). Typical trigger: "build me a landing page", "turn this sketch into a site", "generate the docs site".
11
+
12
+ - **You are composing a workflow and need a specialist agent as one of the steps.**
13
+ → Read [`agent-shelf.md`](./agent-shelf.md). Typical trigger: a workflow node that needs domain expertise you don't have (HR analytics, observability Q&A, physics reasoning, etc).
14
+
15
+ Still unsure? Run `npx rush-ai agent list` first — seeing the available agents usually makes the decision obvious.
16
+
17
+ ## Cheat sheet
18
+
19
+ ```bash
20
+ # Discover
21
+ npx rush-ai agent list --default # just the built-in defaults (web-builder, rush, skill-publisher, ...)
22
+ npx rush-ai agent list --search "人力" # fuzzy-filter the full shelf
23
+ npx rush-ai agent list --all # everything (can be long)
24
+ npx rush-ai agent info <agent> # inspect one agent's skills / MCP servers
25
+
26
+ # Hand off
27
+ npx rush-ai task create -a <agent> -p "<prompt>" # create a task
28
+ npx rush-ai task status <task-id> # check status (includes preview / git URLs when ready)
29
+ npx rush-ai task send <task-id> -p "<follow-up>" # iterate on a running task
30
+ npx rush-ai task watch <task-id> # stream execution (SSE)
31
+
32
+ # Defaults
33
+ -a rush # general-purpose agent; this is the CLI default, so `-a` can be omitted when you want `rush`
34
+ -a web-builder # site/landing-page builder; returns previewUrl + gitRepoUrl
35
+ -a <other> # any other agent name from `agent list` — confirm it exists first
36
+ ```
37
+
38
+ `--json` on any command gives machine-readable output; use it when you need to parse the result.
39
+
40
+ ## Prerequisites the agent should enforce
41
+
42
+ Before creating a task, make sure the user is authenticated:
43
+
44
+ ```bash
45
+ npx rush-ai auth status
46
+ ```
47
+
48
+ If not authenticated, tell the user to run `npx rush-ai auth login` in their terminal (the command is interactive and requires a browser — you cannot complete it on their behalf).
@@ -0,0 +1,102 @@
1
+ # Skill: Call a Rush agent as your sub-agent
2
+
3
+ Use this skill when you are composing a workflow — your own, or one the user described — and a step calls for domain expertise you don't have. Rush hosts a shelf of specialist agents. You can invoke any of them with one `rush-ai task create` call and feed the result back into your workflow.
4
+
5
+ ## When this skill applies
6
+
7
+ Triggers:
8
+
9
+ - The user's instructions name a specialist by role ("use the HR analytics expert", "ask the physics reasoning agent", "let the observability agent check it").
10
+ - You're drafting a multi-step plan and one node is outside your competence (e.g. "analyze RUM data", "write a physics problem set", "summarize an HR report").
11
+ - The user asks "what can Rush do that I can't?" — that's a prompt to show the shelf.
12
+
13
+ Do NOT use this skill when:
14
+
15
+ - The task fits the default general-purpose agent (`rush`) — that's a hand-off, not a sub-agent call. See `hand-off.md`.
16
+ - The task needs a live web artifact — use `web-builder` via `hand-off.md`.
17
+
18
+ ## Playbook
19
+
20
+ ### 1. Discover — don't guess
21
+
22
+ Always start by listing the shelf, unless the user already named a specific agent. Use the right scope for the question at hand:
23
+
24
+ ```bash
25
+ # Just the built-in defaults — useful when you're looking for the general fallback
26
+ npx rush-ai agent list --default --json
27
+
28
+ # Fuzzy-filter when the user hinted at a domain
29
+ npx rush-ai agent list --search "人力" --json
30
+
31
+ # Full catalog — use sparingly, can be hundreds of entries
32
+ npx rush-ai agent list --all --json
33
+ ```
34
+
35
+ Pick the best match by name + description. If multiple are plausible, inspect one:
36
+
37
+ ```bash
38
+ npx rush-ai agent info <agent-name> --json
39
+ ```
40
+
41
+ If nothing fits, tell the user what's available and ask how to proceed — don't force-fit a wrong agent.
42
+
43
+ ### 2. Call it as a node in your workflow
44
+
45
+ Treat the agent call like a pure function: input prompt, output task result. Compose your own prompt with the context the agent needs (not the whole conversation — just the inputs for this step).
46
+
47
+ ```bash
48
+ npx rush-ai task create -a <agent-name> \
49
+ -p "<focused prompt — inputs + expected output format>" \
50
+ --json
51
+ ```
52
+
53
+ For a workflow node you need synchronously, poll:
54
+
55
+ ```bash
56
+ npx rush-ai task status <id> --json
57
+ ```
58
+
59
+ When `status == completed`, the response has the output. For agents that produce structured results, request `--json` and parse it.
60
+
61
+ ### 3. Feed the result back into your workflow
62
+
63
+ The sub-agent's output is just another piece of context for the next step of your plan. Incorporate it into the next action the way you would any tool result.
64
+
65
+ If the output is unsatisfactory, either:
66
+
67
+ - refine via `task send <id> -p "<clarification>"` (same sub-agent, same context), or
68
+ - fall back to your plan B (try a different agent, or escalate to the user).
69
+
70
+ ## Example
71
+
72
+ User: "帮我分析一下 Q1 的部门人效,然后根据结论写一段给 CEO 的周会汇报。"
73
+
74
+ Your plan:
75
+
76
+ 1. Call a data-analysis sub-agent on Rush to do the number-crunching.
77
+ 2. Use the analysis output to draft the exec-summary locally.
78
+
79
+ ```bash
80
+ # Step 1 — find the HR analytics specialist (--json returns { agents, pagination })
81
+ npx rush-ai agent list --search "人力" --json | jq '.agents[] | {name, description}'
82
+ # → matches "人力资源分析专家"
83
+
84
+ # Step 2 — call it as a sub-agent node
85
+ npx rush-ai task create -a 人力资源分析专家 \
86
+ -p "分析 Q1 各部门人效趋势,输出 3 条关键结论。" \
87
+ --json
88
+ # → {"id": "t_abc", "status": "pending"}
89
+
90
+ # Step 3 — wait for the node to finish
91
+ npx rush-ai task status t_abc --json
92
+ # → {"status": "completed", "result": "..."}
93
+
94
+ # Step 4 — you take the result and draft the exec summary locally.
95
+ ```
96
+
97
+ ## Anti-patterns
98
+
99
+ - ❌ Inventing an agent name. If `agent list` doesn't show it, it doesn't exist — tell the user.
100
+ - ❌ Passing the entire original conversation as the sub-agent's prompt. Give it only the inputs it needs.
101
+ - ❌ Using `web-builder` for non-website work. It's specialized for producing deployable sites.
102
+ - ❌ Abandoning the workflow if the sub-agent call fails. Surface the error, offer a fallback.