Статья·  

Представляем Nuxt Agent

Наш собственный AI-агент на nuxt.com, основанный на официальной документации и экосистеме Nuxt. Мы создали его внутри команды с использованием AI SDK, нашего MCP-сервера и компонентов Nuxt UI.
Hugo Richard

Hugo Richard

@hugorcd

Sébastien Chopin

Sébastien Chopin

@Atinux

Прежде всего, мы хотим поблагодарить Kapa.ai, которые обеспечивали работу нашего виджета AI-чата на протяжении последних нескольких лет благодаря их спонсорской поддержке и продолжают поддерживать наше сообщество через наш Discord-сервер.
Мы решили создать собственного агента, чтобы продемонстрировать возможности Nuxt и предложить более глубокую интеграцию с фреймворком и его экосистемой.

Nuxt Agent теперь доступен в бета-версии на nuxt.com. Мы создали его самостоятельно, интегрировали в сайт и подключили к нашей документации, каталогу модулей, блогу и гайдам по деплою.

Откройте агента в любом месте nuxt.com с помощью ⌘I (или Ctrl+I), или сразу перейдите в полноэкранный режим по адресу /chat.

От виджета документации к настоящему агенту

Kapa AI хорошо служила нам в течение последних нескольких лет как виджет для вопросов и ответов по документации. Она искала по документам и формировала ответы, и на этом всё заканчивалось. Но Nuxt — это больше, чем просто документация. Есть модули, шаблоны, провайдеры деплоя, история изменений, GitHub-ишьюсы, песочницы и реальная навигация по сайту.

Мы хотели агента, который мог бы справляться со всем этим, используя тот же дизайн-язык, что и остальная часть nuxt.com, и ту же систему контента (Nuxt Content), которую мы уже используем. Поэтому мы создали собственного агента на основе Nuxt MCP-сервера, который мы запустили в ноябре прошлого года.

Вот что умеет агент сегодня:

  • Основывает ответы на официальной документации Nuxt и данных экосистемы через инструменты MCP, а не на извлеченных текстовых фрагментах.
  • Отображает расширенный UI. Модули, шаблоны, посты блога, провайдеры хостинга и ссылки на песочницы возвращаются в виде кликабельных карточек вместо обычных ссылок.
  • Стримит всё в процессе работы, включая прогресс вызовов инструментов.
  • Замыкает цикл обратной связи. Отзывы, голосования и отчеты об ошибках попадают в наши внутренние инструменты, чтобы мы могли постоянно улучшать его.

Познакомьтесь с агентом

Три способа общения с ним

Вы можете связаться с агентом тремя способами:

  • Боковая панель, закрепленная справа на больших экранах и выдвигающаяся поверх контента на меньших. Переключайте её из заголовка или с помощью ⌘I.
  • Панель вопросов внизу страниц /docs и /blog, чтобы задать вопрос, не покидая страницу, которую вы читаете.
  • Полноэкранный чат по адресу /chat для длительных сессий.

Он знает, на какой странице вы находитесь

Спросите "как настроить это для моего приложения?" во время чтения документации, и агент автоматически подтянет эту страницу как контекст. Небольшой индикатор "Агент использует эту страницу" внизу страницы показывает это явно, и вы можете закрыть его в любое время.

Богатые ответы, а не только текст

Ответы приходят в виде чего-то большего, чем просто текст. Спросите о модуле — и получите карточку модуля с метаданными, полученными в реальном времени с api.nuxt.com. Спросите о стартовых шаблонах — получите ряд кликабельных карточек шаблонов. Спросите о деплое — получите карточки провайдеров со ссылками на нужные гайды. Нужно воспроизвести баг? Агент может сгенерировать ссылку на песочницу StackBlitz прямо из разговора.

Попробуйте спросить: "Покажи мне официальные стартовые шаблоны" — и вы получите полный набор (nuxt-ui-dashboard, nuxt-ui-saas, nuxt-ui-landing, nuxt-ui-chat, nuxt-ui-docs, nuxt-ui-portfolio) в виде карточек, которые можно открыть одним кликом.

Обратная связь встроена

У каждого сообщения ассистента есть кнопки "палец вверх/вниз". Если хотите поделиться большим (пропущенная информация, неверный ответ, идея), действие Сообщить о проблеме открывает короткую форму и создает тикет в Linear с приложенным разговором, так что у нас есть всё необходимое для разбора.

Агент тоже может открыть эту форму. Если вы попросите "отправить фидбек" или "сообщить о проблеме", или если разговор начинает вызывать разочарование, агент вызывает инструмент report_issue и та же форма открывается встроенной. Не нужно искать кнопки.

Разговоры сохраняются и возобновляются после перезагрузки, так что вы можете отойти и вернуться к тому месту, где остановились.

Что агент может делать на самом деле

Обоснование ответов агента идет от Nuxt MCP-сервера, того же, к которому подключаются Cursor, Claude Desktop и ChatGPT. Это означает, что Nuxt Agent и ваш локальный AI-ассистент используют одни и те же структурированные данные: официальную документацию, каталог модулей, блог, гайды по деплою и историю изменений репозиториев Nuxt.

Поверх этого обоснования агент имеет небольшой набор нативных инструментов, которые отображаются как UI в чате: карточки модулей и шаблонов, провайдеры хостинга, посты блога, ссылки на песочницы StackBlitz и поиск по GitHub-ишьюсам в репозиториях nuxt, nuxt-modules и nuxt-content. Агент обращается к поиску ишьюсов первым делом, когда вы вставляете ошибку.

Веб также доступен через нативный инструмент Anthropic web_search, но только как запасной вариант для вещей, которых модель разумно не может знать: совсем новый релиз Vue, свежий RFC, недавние новости экосистемы. Это не поисковая система общего назначения, и системный промпт явно говорит об этом. Мы никогда не используем web_search для того, что должно быть отвечено из документации или остального контента Nuxt, доступного через MCP.

Под капотом

Стек

Единый Nitro-обработчик в server/api/agent.post.ts управляет всем. На клиенте экземпляр Chat из @ai-sdk/vue указывает на /api/agent. На сервере streamText из AI SDK v6 вызывает claude-sonnet-4.6, с инструментами, объединенными из нашего собственного MCP-сервера (/mcp, тот же origin) и нескольких нативных (show_*, open_playground, report_issue). Состояние чата хранится в Drizzle ORM, и evlog оборачивает модель для структурированной телеметрии по токенам, стоимости и вызовам инструментов.

UIMessage стриминг с AI SDK v6

Весь конвейер работает на модели стриминга UIMessage из AI SDK v6. Серверная часть выглядит так:

server/api/agent.post.ts
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(...)) выносит персистентность за пределы жизненного цикла ответа, так что стрим завершается для пользователя сразу, а запись чата обновляется в фоне.

Один MCP-сервер, два потребителя

Агент и внешние AI-ассистенты общаются с одним и тем же MCP-сервером. Это самый важный архитектурный выбор, который мы сделали. Обработчик маршрута открывает HTTP MCP-клиент, указывающий на собственный /mcp endpoint:

server/api/agent.post.ts
const httpClient = await createMCPClient({
  transport: { type: 'http', url: `${getRequestURL(event).origin}${MCP_PATH}` }
})
const mcpTools = await httpClient.tools()

Эти инструменты затем объединяются с нативными UI-инструментами в единый объект tools, передаваемый в streamText. Выгода: любой инструмент, который мы добавляем в MCP-сервер, сразу становится доступен Nuxt Agent и каждому внешнему ассистенту, подключенному к нему, без дополнительной проводки. Мы написали отдельный пост о том, как работает сам MCP-сервер еще в ноябре.

Персистентность, стоимость и ограничение частоты

Чаты живут в единой таблице agent_chats, с ключом по заголовку x-chat-id, который клиент отправляет с каждым запросом. onConflictDoUpdate от Drizzle накапливает использование токенов, оценочную стоимость, продолжительность и количество запросов за всю жизнь разговора. Это дает нам аналитику по чатам бесплатно.

Каждый запрос также проходит через небольшой хелпер consumeAgentRateLimit перед началом стриминга. Текущий лимит — 20 сообщений в день на IP-отпечаток, чего достаточно для реального использования и достаточно мало, чтобы предотвратить неконтролируемые расходы, если что-то начнет зацикливаться.

Строгий системный промпт

Многое качество агента исходит из промпта. Несколько правил взяли на себя основную тяжесть: обращаться к search_github_issues первым делом, когда пользователь вставляет ошибку, предпочитать show_module над get_module, когда ответ должен отображаться как карточка, никогда не вызывать web_search, если вопрос действительно выходит за рамки того, что модель может знать, и никогда не заканчивать ход только вызовом инструмента. Вместе эти правила достаточно сокращают спам инструментами и галлюцинации, чтобы агент оставался сосредоточенным на текущей задаче.

Что дальше

Агент запускается в бета-версии. В краткосрочной перспективе мы сосредоточены на основах: качестве ответов, более богатой памяти между ходами и более чистых цитатах источников.

В более отдаленном будущем мы хотим, чтобы nuxt.com ощущался больше как приложение, чем как статический сайт. Следующий шаг там — пользовательские аккаунты. Каждый авторизованный пользователь получает свою сессию, историю чатов, сохраненную и возобновляемую между устройствами, и Nuxt Agent становится первым реальным строительным блоком этого более похожего на приложение nuxt.com.

Мы будем рады вашей помощи в формировании дальнейшего пути. Если агент что-то не так понимает или упускает что-то, что вам нужно, используйте кнопку Сообщить о проблеме внутри чата. Она создает тикет на нашей стороне с полным разговором в приложении, и мы читаем каждый.

Попробуйте Nuxt Agent сейчас: откройте его с помощью ⌘I, используйте панель вопросов на любой странице docs, или перейдите в /chat для полноэкранного режима.

Полный исходный код nuxt.com находится на GitHub, включая агента, MCP-сервер и каждый инструмент, описанный выше. Обработчик агента находится в server/api/agent.post.ts, нативные инструменты в server/utils/tools/, а UI-компоненты в app/components/agent/. Возьмите любую часть как вдохновение для ваших собственных приложений. И если хотите создать свой MCP-сервер, Nuxt MCP Toolkit поможет сделать это за несколько минут.

← Вернуться в блог
Nuxt в LinkedInNuxt в BlueskyNuxt в X