Nuxt Agent 现已在 nuxt.com 上进入 Beta 版。我们亲自构建了它,将其接入网站,并连接到了我们的文档、模块目录、博客和部署指南。
从文档小部件到真正的 agent
过去几年里,Kapa AI 作为文档问答小部件很好地服务了我们。它会搜索文档并总结答案,仅此而已。但 Nuxt 不只是文档。这里还有模块、模板、部署提供商、更新日志、GitHub issues、playground,以及贯穿整个站点的真实导航。
我们希望拥有一个能够处理这一切的 agent,并且使用与 nuxt.com 其他部分相同的设计语言,以及我们已经在运行的相同内容流水线(Nuxt Content)。所以我们基于去年 11 月发布的 Nuxt MCP 服务器 构建了自己的实现。
以下是该 agent 目前能做的事情:
- 基于权威来源回答:通过 MCP 工具,而不是检索到的文本片段,基于官方 Nuxt 文档和生态数据作答。
- 渲染富 UI:模块、模板、博客文章、托管提供商和 playground 链接会以可点击卡片的形式返回,而不是普通链接。
- 流式输出一切:在运行过程中持续输出,包括工具调用进度。
- 形成闭环:反馈、投票和问题报告会流入我们的内部工具,这样我们就能持续改进它。
认识这个 agent
与它交互的三种方式
你可以通过三种方式访问 agent:
- 大屏幕上固定在右侧的 侧边栏,在小屏幕上则会滑出覆盖。可通过页头或 ⌘I 切换。
/docs和/blog页面底部的 提问栏,这样你无需离开当前阅读页面就能发问。- 位于 /chat 的 全屏聊天,适合更长时间的会话。
它知道你当前在哪个页面
当你一边阅读文档一边问“我该如何为我的应用自定义这个?”时,agent 会自动将该页面作为上下文带入。页脚里一个小小的“Agent 正在使用此页面”指示器会明确显示这一点,而且你可以随时关闭它。
富答案,而不只是文本
回答返回的不只是文本。询问某个模块时,你会得到一个带有从 api.nuxt.com 实时拉取元数据的模块卡片。询问 starter 模板时,你会得到一排可点击的模板卡片。询问部署时,你会得到链接到正确指南的提供商卡片。需要复现 bug?agent 还能根据对话本身生成一个 StackBlitz playground 链接。
nuxt-ui-dashboard、nuxt-ui-saas、nuxt-ui-landing、nuxt-ui-chat、nuxt-ui-docs、nuxt-ui-portfolio),这些卡片可一键打开。内置反馈
每条助手消息都有一个赞/踩按钮。如果你想分享更多内容(缺失内容、错误答案、想法),Report issue 操作会打开一个简短表单,并在我们这边创建一条附带对话内容的 Linear 工单,这样我们就拥有跟进所需的一切信息。
agent 也可以自己打开这个表单。如果你要求“提交反馈”或“报告问题”,或者对话开始显得有些沮丧,agent 会调用 report_issue 工具,并在内联中打开同样的表单。无需到处找按钮。
对话会被保存,并可在刷新后继续,因此你可以离开后再回来接着上次的位置继续。
agent 实际能做什么
agent 的底层依据来自 Nuxt MCP 服务器,也就是 Cursor、Claude Desktop 和 ChatGPT 连接的同一个服务器。这意味着 Nuxt Agent 和你本地的 AI 助手共享相同的结构化数据:官方文档、模块目录、博客、部署指南,以及 Nuxt 仓库的更新日志。
在这些底层依据之上,agent 还拥有一组原生工具,会在聊天中以 UI 形式呈现:模块和模板卡片、托管提供商、博客文章、StackBlitz playground 链接,以及跨 nuxt、nuxt-modules 和 nuxt-content 的 GitHub issue 搜索。每当你粘贴错误信息时,agent 会优先调用该 issue 搜索。
Web 也可用,通过 Anthropic 的原生 web_search,但仅作为模型无法合理知道内容时的后备方案:比如刚发布的 Vue 版本、新近公开的 RFC、生态系统的最新新闻。它不是通用搜索引擎,系统提示词对此也有明确说明。对于应当从文档或通过 MCP 暴露的其他 Nuxt 内容中回答的问题,我们从不使用 web_search。
内部实现
技术栈
一个位于 server/api/agent.post.ts 的 Nitro 处理器驱动全部流程。客户端使用指向 /api/agent 的 @ai-sdk/vue Chat 实例。服务端则使用 AI SDK v6 的 streamText 调用 claude-sonnet-4.6,工具由我们自己的 MCP 服务器(/mcp,同源)和少量原生工具(show_*、open_playground、report_issue)合并而成。聊天状态存放在 Drizzle ORM 中,而 evlog 会为 token、成本和工具调用提供结构化遥测包装。
使用 AI SDK v6 的 UIMessage 流式传输
整个流水线运行在 AI SDK v6 的 UIMessage 流式模型之上。服务端代码如下:
const stream = createUIMessageStream({
execute: async ({ writer }) => {
const result = streamText({
model: ai.wrap(MODEL),
maxOutputTokens: 4000,
stopWhen: stopWhenResponseComplete,
system: systemPrompt,
messages: await convertToModelMessages(messages),
tools: {
...mcpTools as ToolSet,
web_search: anthropic.tools.webSearch_20250305(),
search_github_issues: createSearchGitHubIssuesTool(event),
show_module: showModuleTool,
show_template: createShowTemplateTool(event),
show_blog_post: createShowBlogPostTool(event),
show_hosting: createShowHostingTool(event),
open_playground: openPlaygroundTool,
report_issue: reportIssueTool
},
experimental_telemetry: {
isEnabled: true,
integrations: [createEvlogIntegration(ai)]
}
})
writer.merge(result.toUIMessageStream({
sendSources: true,
originalMessages: messages,
onFinish: ({ messages: finalizedMessages }) => {
event.waitUntil(saveChat(finalizedMessages))
}
}))
}
})
有两个细节值得指出。stopWhen: stopWhenResponseComplete 是一个自定义谓词,只要模型生成了文本且不再有其他工具调用,就会立刻结束循环,并且最多限制在 10 步内。这避免了经典的“模型在工具上无限循环”的故障模式。还有 event.waitUntil(saveChat(...)),它将持久化操作放到响应生命周期之外,因此流会立即为用户结束,而聊天记录会在后台完成 upsert。
一个 MCP 服务器,两个消费者
agent 和外部 AI 助手使用的是同一个 MCP 服务器。这是我们做出的最重要的架构选择。路由处理器会打开一个指向自身 /mcp 端点的 HTTP MCP 客户端:
const httpClient = await createMCPClient({
transport: { type: 'http', url: `${getRequestURL(event).origin}${MCP_PATH}` }
})
const mcpTools = await httpClient.tools()
这些工具随后会与原生 UI 工具合并成一个传递给 streamText 的单一 tools 对象。好处在于:我们添加到 MCP 服务器中的任何工具,都会立即对 Nuxt Agent 以及所有指向它的外部助手可用,无需额外接线。我们在去年 11 月还为 MCP 服务器本身的工作方式写了一篇 单独的文章。
持久化、成本和速率限制
聊天记录保存在一张 agent_chats 表中,并以客户端每次请求都会发送的 x-chat-id 头作为键。Drizzle 的 onConflictDoUpdate 会在整个会话生命周期内累加 token 使用量、估算成本、耗时和请求次数。这让我们免费获得每个聊天的分析数据。
每个请求在流式输出开始前还会先经过一个小型的 consumeAgentRateLimit 辅助函数。当前限制是每个 IP 指纹每天 20 条消息,这对于真实使用来说已经足够,同时也足以在某些逻辑开始循环时防止成本失控。
简洁而有力的系统提示词
agent 的很多质量都来自提示词。几个规则承担了大部分作用:当用户粘贴错误时优先使用 search_github_issues;当答案应以卡片形式展示时,优先使用 show_module 而不是 get_module;除非问题确实超出了模型能知道的范围,否则绝不调用 web_search;并且绝不只通过一次工具调用就结束一个回合。正是这些规则一起减少了工具噪音和幻觉,使 agent 能始终聚焦于手头任务。
接下来是什么
该 agent 正在以 Beta 版启动。短期内,我们专注于基础能力:更好的回答质量、跨轮次更丰富的记忆,以及更清晰的来源引用。
从更长远来看,我们希望 nuxt.com 感觉更像一个应用,而不是一个静态网站。下一步是用户账号。每个登录用户都会拥有自己的会话、会被保存且可在不同设备间继续的聊天记录,而 Nuxt Agent 将成为这个更像应用的 nuxt.com 的第一个真正构建模块。
我们很希望你能帮助塑造它接下来的发展方向。如果 agent 出了问题,或者遗漏了你希望看到的内容,请使用聊天中的 Report issue 按钮。它会在我们这边创建一张工单,并附上完整的对话记录,我们会逐一阅读。
nuxt.com 的完整源代码都在 GitHub 上,包括 agent、MCP server,以及上面提到的所有工具。agent handler 位于 server/api/agent.post.ts,原生工具位于 server/utils/tools/,UI 组件位于 app/components/agent/。你可以将其中任何内容作为自己应用的灵感。如果你想构建自己的 MCP server,Nuxt MCP Toolkit 能在几分钟内帮你完成。