Еще недавно интеграция LLM в веб-приложение обычно выглядела довольно просто: отправляем запрос в API модели, получаем текст и показываем его пользователю.
Но как только хочется сделать не просто чат, а полноценного AI-агента, быстро появляются дополнительные задачи: вызов функций приложения, хранение истории, работа с файлами, выполнение последовательности действий, RAG, MCP, стриминг, несколько агентов и наблюдаемость.
Все это можно собирать самостоятельно. Но для TypeScript уже существует фреймворк, который объединяет эти задачи в одну систему — Mastra.
Официальный сайт: mastra.ai
Исходный код: GitHub — mastra-ai/mastra
Что такое Mastra
Mastra — open-source TypeScript-фреймворк для разработки приложений на базе LLM и AI-агентов.
Если проводить аналогию с обычной веб-разработкой, вызов API языковой модели — это примерно fetch(). Он решает одну конкретную задачу, но вокруг реального приложения все равно приходится строить инфраструктуру.
Mastra предлагает более высокий уровень абстракции:
LLM
↓
Agent
├── Instructions
├── Tools
├── Memory
├── Workflows
├── RAG
└── MCP
При этом Mastra не является отдельной языковой моделью. Она работает поверх существующих моделей и позволяет подключать разных провайдеров через единый интерфейс.
По сути, это backend-фреймворк для той части приложения, где решения принимает LLM.
Agent
Центральная сущность Mastra — Agent.
Простейший агент выглядит примерно так:
import { Agent } from '@mastra/core/agent'
export const assistant = new Agent({
id: 'assistant',
name: 'Assistant',
instructions: `
Ты помощник пользователя.
Отвечай коротко и по существу.
`,
model: 'openai/gpt-5.5',
})
Сам по себе такой агент пока мало отличается от обычного обращения к LLM.
Интереснее становится, когда мы начинаем давать ему инструменты.
В Mastra агент предназначен именно для открытых задач, где заранее неизвестна точная последовательность действий: модель сама решает, какие инструменты вызвать, сколько действий выполнить и когда закончить работу.
Tools
Допустим, у нас есть административная панель интернет-магазина.
Пользователь пишет:
Покажи последние пять заказов.
Языковая модель сама по себе не имеет доступа к нашей базе данных. Поэтому ей необходимо предоставить инструмент.
Упрощенно это может выглядеть так:
const getOrders = createTool({
id: 'get-orders',
description: 'Получить список заказов',
inputSchema: z.object({
limit: z.number().default(5),
}),
execute: async ({ limit }) => {
return orderService.findLatest(limit)
},
})
После этого инструмент подключается к агенту:
export const assistant = new Agent({
id: 'assistant',
name: 'Assistant',
instructions: `
Ты помощник администратора интернет-магазина.
`,
model: 'openai/gpt-5.5',
tools: {
getOrders,
},
})
Теперь пользователь может написать:
Какие были последние заказы?
Модель понимает, что для ответа нужны данные, вызывает getOrders, получает результат и формирует ответ.
Схема получается такой:
Пользователь
↓
Agent
↓
LLM
↓
нужны данные
↓
Tool
↓
наш backend
↓
результат
↓
LLM
↓
Пользователь
Именно tools превращают обычный чат с моделью в интерфейс управления приложением.
Агент не должен заменять бизнес-логику
Здесь есть важный архитектурный момент.
Не стоит помещать бизнес-логику непосредственно внутрь tools.
Плохой вариант:
execute: async ({ campaignId }) => {
// 200 строк работы с БД
}
Лучше оставить tool тонким:
execute: async ({ campaignId }) => {
return campaignService.getStatistics(campaignId)
}
Тогда структура приложения остается привычной:
Mastra Agent
↓
Tool
↓
Application Service
↓
Repository / API / Database
Mastra в такой архитектуре становится еще одним транспортным слоем приложения.
REST-контроллер вызывает сервис по HTTP-запросу.
CLI-команда вызывает тот же сервис из консоли.
А Mastra Tool позволяет вызвать его по решению языковой модели.
Это довольно удобное разделение ответственности.
Workflows
Не каждую задачу стоит отдавать агенту.
Представим процесс:
создать кампанию
↓
проверить бюджет
↓
создать размещения
↓
подключить площадки
↓
запустить кампанию
Можно дать модели пять tools и попросить самостоятельно выполнить их в правильном порядке.
Но если порядок известен заранее, надежнее описать его явно.
Для этого в Mastra существуют workflows.
Например:
const workflow = createWorkflow({
id: 'campaign-create',
inputSchema,
})
.then(validateCampaign)
.then(createCampaign)
.then(createPlacements)
.then(connectPublishers)
.commit()
Получается полезное разделение:
Agent
подходит для задачи:
"Разберись, почему кампания плохо откручивается"
А:
Workflow
лучше использовать для:
"Создай кампанию по стандартному процессу"
То есть Agent выбирает путь, а Workflow описывает известный путь. Сама документация Mastra рекомендует workflows для заранее определенных многошаговых процессов.
Memory
Для нормального чата одного массива messages довольно быстро становится недостаточно.
Например:
— Покажи кампании за сегодня.
— Только активные.
— А теперь сравни их со вчерашним днем.
Последние две команды невозможно нормально интерпретировать без предыдущего контекста.
Mastra предоставляет отдельный механизм памяти. В актуальном API доступны, в частности, хранение последних сообщений, semantic recall и observational memory.
Концептуально это выглядит так:
User
↓
Thread
↓
Memory
↓
Agent
То есть состояние диалога становится частью инфраструктуры агента, а не набором самостоятельно написанных костылей вокруг API модели.
RAG
Еще одна типичная задача — дать агенту доступ к большому объему информации.
Например:
документация
статьи
инструкции
FAQ
описания товаров
внутренние регламенты
Засовывать все это в system prompt невозможно и не нужно.
Используется RAG:
Документы
↓
chunking
↓
embeddings
↓
vector storage
↓
Запрос пользователя
↓
semantic search
↓
релевантные фрагменты
↓
LLM
Mastra предоставляет инструменты для построения такой схемы, поэтому RAG не приходится полностью собирать отдельно от агента.
MCP
Особенно интересно наличие поддержки Model Context Protocol.
MCP позволяет стандартизировать взаимодействие AI-приложений с внешними инструментами и источниками данных.
Вместо жесткой связи:
Agent → конкретный API
можно получить:
Agent
↓
MCP
↓
External tools
Причем Mastra умеет не только использовать MCP-инструменты, но и создавать MCP-серверы, через которые можно публиковать собственные tools и другие возможности приложения.
Это интересно для систем, где один набор инструментов должен использоваться разными AI-клиентами.
Например:
┌─ Web chat
│
Backend ─ MCP ──┼─ IDE
│
├─ Telegram bot
│
└─ другой агент
Несколько агентов
Необязательно делать одного огромного агента с сотней инструментов.
Систему можно разделить по специализациям:
Supervisor
│
├── Analytics Agent
│ ├── statistics
│ └── reports
│
├── Campaign Agent
│ ├── campaigns
│ └── placements
│
└── Support Agent
├── documentation
└── knowledge base
Пользователь при этом по-прежнему может видеть один чат.
Разделение агентов остается внутренней архитектурой приложения.
В актуальной Mastra для таких сценариев есть supervisor agents и механизмы координации агентов.
Как это использовать с Vue
Mastra не требует писать frontend на React.
Например, приложение может выглядеть совершенно обычно:
Vue / Nuxt
↓
HTTP / Stream
↓
Mastra
↓
Agent
↓
Tools
↓
Backend services
То есть Vue остается интерфейсом:
const response = await fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({
message: text.value,
}),
})
А вся агентная логика работает на сервере.
Это особенно удобно, если основной стек уже TypeScript:
Vue
+
Node.js
+
Mastra
Не приходится заводить отдельный Python-сервис только ради AI-части приложения.
Отдельный сервис или часть существующего backend
Оба варианта возможны.
Для небольшого приложения Mastra можно держать рядом с остальным backend:
src/
├── modules/
├── services/
├── repositories/
└── mastra/
├── agents/
├── tools/
└── workflows/
В более крупной системе мне больше нравится отдельный слой:
Vue
↓
Application API
↓
Mastra
↓
Internal API / MCP
↓
основной backend
В этом случае агент вообще не знает, как устроена база данных.
Он работает только с публичными возможностями системы:
getCampaignStatistics
createPlacement
findPublisher
generateReport
Такую архитектуру проще контролировать и безопаснее развивать.
Что с production
Агентное приложение сложно отлаживать обычным console.log.
Нужно понимать:
какой prompt получил агент;
какую модель вызвал;
какой tool выбрал;
с какими аргументами;
сколько занял запрос;
где произошла ошибка;
каким получился результат.
Поэтому в Mastra есть observability, traces, metrics, logs, evals и scorers.
Это важная часть фреймворка: AI-приложение рассматривается не как один вызов API, а как система, поведение которой необходимо наблюдать и тестировать.
Быстрый старт
Создать проект можно через CLI:
npm create mastra@latest
После установки получается обычный TypeScript-проект, который можно запускать локально и постепенно добавлять agents, tools и workflows. Именно этот способ сейчас рекомендует сам проект.
Когда Mastra действительно полезна
Mastra имеет смысл, когда приложение выходит за пределы простого:
llm.generate(prompt)
Например, если нужен:
- чат с историей;
- вызов backend-функций;
- агент, самостоятельно выбирающий действия;
- стриминг ответа;
- RAG;
- MCP;
- workflows;
- несколько специализированных агентов;
- наблюдаемость и тестирование поведения AI.
Для одного запроса к модели подключение полноценного фреймворка будет избыточным.
Но если AI становится отдельным интерфейсом к приложению, количество собственной инфраструктуры начинает быстро расти. Именно эту инфраструктуру Mastra и пытается стандартизировать.
Итог
Мне нравится смотреть на Mastra не как на очередную библиотеку для вызова LLM, а как на application framework для AI-части backend.
Обычное приложение уже имеет:
HTTP → Controller → Service → Database
С появлением AI добавляется еще один путь:
Chat → Agent → Tool → Service → Database
А поверх него постепенно возникают memory, workflows, RAG, MCP, tracing и evals.
Можно написать все это самостоятельно. Иногда это действительно будет лучшим решением.
Но если нужен полноценный агент внутри TypeScript-приложения, Mastra дает достаточно интересный набор готовых архитектурных примитивов и при этом не заставляет менять привычный Node.js/TypeScript-стек.
Именно поэтому на Mastra стоит смотреть не как на «обертку над ChatGPT», а как на инфраструктуру для нового типа интерфейса приложения — интерфейса, в котором пользователь формулирует цель, а система сама решает, какие доступные ей действия необходимо выполнить.


Добавить комментарий