CodeWorlds
Powrót do kolekcji
Przewodnik14 min czytaniaZespół CodeWorlds

Mastra, framework agentowy w TypeScripcie

Mastra 1.61.0 to agenci, workflow i scorery w TypeScripcie. Tempo wydań, licencja Apache 2.0 z wyjątkiem katalogów ee, domyślna pamięć i cennik platformy.

Mastra, framework agentowy w TypeScripcie

Mastra to biblioteka do budowania agentów LLM w TypeScripcie: definiujesz agenta z modelem, narzędziami i pamięcią, składasz z kroków przepływ pracy, oceniasz odpowiedzi scorerami i oglądasz przebiegi w lokalnym panelu. Bieżąca wersja @mastra/core to 1.61.0 z 21 sierpnia 2026 roku, opublikowana na licencji Apache 2.0 z istotnym wyjątkiem, który opisuję niżej.

Co Mastra daje i czego nie daje

Rdzeń pakietu @mastra/core eksportuje kilkadziesiąt podścieżek, ale realnie pracujesz z czterema pojęciami. Agent to obiekt z instrukcją, modelem, zestawem narzędzi i opcjonalną pamięcią. Narzędzie to funkcja z opisem i schematem wejścia oraz wyjścia. Workflow to graf kroków z typowanym przepływem danych. Scorer to funkcja oceniająca wynik agenta i zapisująca liczbę wraz z uzasadnieniem.

Do tego dochodzi warstwa serwerowa. Pakiet @mastra/server wystawia agentów i workflow jako HTTP, a osobne adaptery podpinają to pod istniejącą aplikację: @mastra/hono, @mastra/express, @mastra/fastify, @mastra/koa, @mastra/nestjs, @mastra/next i @mastra/tanstack-start. Jeśli budujesz na Next.js, agent nie musi być osobnym procesem.

Mastra nie jest dostawcą modeli i nie ma własnego API do inferencji. Pod spodem siedzi AI SDK, i to w trzech pokoleniach naraz: rdzeń deklaruje aliasy @ai-sdk/provider-v5 na wersję 2.0.3, @ai-sdk/provider-v6 na 3.0.14 i @ai-sdk/provider-v7 na 4.0.4, z analogicznym kompletem provider-utils. To wygodne przy migracjach, ale oznacza, że jedna instalacja niesie trzy równoległe warstwy zgodności.

Wśród zależności rdzenia są też dwie, które warto zobaczyć przed audytem. posthog-node w wersji ^5.46.1 to telemetria wbudowana w bibliotekę, a nie doklejona wtyczka. chat w wersji ^4.34.0 to Chat SDK z repozytorium vercel/chat, czyli integracje ze Slackiem, Teams i Google Chat wciągane niezależnie od tego, czy ich używasz. Rozpakowana paczka @mastra/core 1.61.0 waży około 65 MB przy archiwum 13,9 MB.

Wersje, tempo wydań i rodzina pakietów

Wersja 1.0.0 ukazała się 20 stycznia 2026 roku, a 1.61.0 dwudziestego pierwszego sierpnia. To 61 podbić wersji mniejszej w 213 dni, czyli jedno co około trzy i pół dnia. Stabilnych wydań z linii 1.x jest w rejestrze 71, co daje jedno co trzy dni. Dla porządku: w rejestrze wisi 1505 wersji @mastra/core, ale zdecydowana większość to migawki z gałęzi o numerach 0.0.0-<nazwa-gałęzi>-<data>, publikowane przy każdym pull requeście.

Sprawdziłem, czy w rejestrze nie ma wersji wycofanej udającej najnowszą. Oznaczone jako deprecated są dokładnie dwie, 0.10.13 i 0.15.0, obie ze starej linii 0.x. Na szczycie linii 1.x nic nie jest wycofane, a znaczniki alpha i beta wskazują odpowiednio 1.62.0-alpha.2 i 1.1.0-alpha.2.

Rodzina jest duża. Zapytanie o @mastra w rejestrze npm zwraca co najmniej 168 pakietów w tym zakresie nazw, licząc tylko pierwsze 250 wyników. Numeracja jest rozjechana celowo: @mastra/deployer i @mastra/server idą w zamku z rdzeniem na 1.61.0, @mastra/memory jest na 1.27.0, @mastra/rag na 2.6.0, @mastra/mcp na 1.17.1, a @mastra/playground-ui na 51.0.0.

Zakresy zależności równorzędnych sprawdziłem osobno, bo to typowe miejsce na konflikt przy instalacji. Wszystkie mają postać >=X-0 <2.0.0-0, czyli są otwarte w górę i przy najnowszym rdzeniu nic się nie kłóci. Rozjeżdżają się natomiast dolne progi: @mastra/rag, @mastra/evals i @mastra/mcp przyjmują dowolny rdzeń 1.x, @mastra/libsql wymaga co najmniej 1.51.0, @mastra/pg co najmniej 1.53.0, a @mastra/inngest co najmniej 1.58.0. Przypięcie starszego rdzenia po to, żeby uniknąć zmian w interfejsie, wyklucza więc najnowsze adaptery.

Licencja z trzech źródeł

W repozytorium mastra-ai/mastra nie ma pliku LICENSE. Jest wyłącznie LICENSE.md, i to samo na gałęzi main oraz master. Warianty LICENSE, LICENSE.MD, LICENSE.txt, LICENCE i COPYING zwracają 404, więc skaner szukający tylko nazwy bez rozszerzenia nie znajdzie niczego.

Treść tego pliku nie jest czystym Apache 2.0. Zaczyna się od wyłączenia: wszystko, co leży w dowolnym katalogu o nazwie ee/, w tym packages/core/src/auth/ee/ i packages/server/src/server/auth/ee/, podlega licencji z pliku ee/LICENSE. Dopiero reszta jest na Apache 2.0, z notą praw autorskich Kepler Software, Inc.

Plik ee/LICENSE istnieje i nosi tytuł Mastra Enterprise Edition (EE) License. Zezwala na modyfikowanie kodu do własnych celów rozwojowych i testowych, natomiast użycie produkcyjne wymaga zawartej na piśmie umowy z Kepler Software. Za produkcję uznaje się każde użycie wykraczające poza rozwój i testy na własnych systemach, przy czym środowisko staging jest wprost zaliczone do testów. Kopiowanie, dystrybucja i sprzedaż są zabronione.

Drugie źródło, czyli pole license w rejestrze npm, mówi po prostu Apache-2.0, bez śladu tego wyłączenia. Trzecie źródło jest jeszcze ciekawsze. Opublikowana paczka @mastra/core 1.61.0 nie zawiera żadnego pliku licencyjnego, bo pole files w jej package.json to ["dist", "CHANGELOG.md", "./**/*.d.ts"]. Zawiera natomiast 66 ścieżek pod katalogami ee/, między innymi dist/auth/ee/fga-check.js i dist/agent-builder/ee/. Innymi słowy: kod objęty licencją komercyjną jedzie w paczce zadeklarowanej jako Apache 2.0, a tekstu licencji w paczce nie ma wcale.

W rodzinie pakietów zgodność też nie jest jednolita. @mastra/inngest 1.8.7 zachowuje się odwrotnie niż rdzeń: nie ma pola license w ogóle, za to dołącza plik LICENSE.md z pełnym tekstem wyłączenia. To samo pole brakuje w @mastra/editor 0.14.0 i @mastra/redis-streams 0.4.0. Pakiety @mastra/memory, @mastra/rag, @mastra/evals, @mastra/mcp, @mastra/libsql i CLI mastra dołączają plik licencyjny prawidłowo.

Praktyczny wniosek: jeśli prowadzisz rejestr licencji zależności, wpis „Apache-2.0” dla @mastra/core jest niepełny. Sprawdź, czy używasz czegokolwiek z @mastra/core/auth/ee albo z buildera agentów, bo to inny reżim prawny.

Code
Bash
# rdzeń i CLI
npm install @mastra/core mastra

# trwały magazyn zamiast domyślnej pamięci procesu
npm install @mastra/libsql

# to, co zwykle dochodzi później
npm install @mastra/memory @mastra/evals @mastra/mcp

# lokalne studio na porcie 4111
npx mastra dev

# build do .mastra/output
npx mastra build

# czym naprawdę jest licencja w paczce
npm pack @mastra/core@1.61.0
tar tzf mastra-core-1.61.0.tgz | grep -E "^package/(LICENSE|LICENCE)"

Agent, narzędzia i pamięć w kodzie

Konfiguracja agenta przyjmuje pola id, name, instructions, model, tools, memory, workflows, agents, scorers, inputProcessors, outputProcessors, defaultOptions i maxSteps. Narzędzie tworzysz przez createTool z polami id, description, inputSchema, outputSchema oraz execute. Od linii 1.x pierwszym argumentem execute są bezpośrednio dane wejściowe, a nie obiekt z polem context, co jest najczęstszą pułapką przy przepisywaniu starszych przykładów.

Code
TypeScript
import { Mastra } from '@mastra/core'
import { Agent } from '@mastra/core/agent'
import { createTool } from '@mastra/core/tools'
import { Memory } from '@mastra/memory'
import { LibSQLStore } from '@mastra/libsql'
import { z } from 'zod'

const invoiceTool = createTool({
  id: 'fetch-invoice',
  description: 'Pobiera fakturę po numerze',
  inputSchema: z.object({ number: z.string() }),
  outputSchema: z.object({ total: z.number(), currency: z.string() }),
  requireApproval: false,
  execute: async (inputData) => {
    const res = await fetch(`https://erp.internal/invoices/${inputData.number}`)
    return res.json()
  }
})

const memory = new Memory({
  storage: new LibSQLStore({ id: 'agent-memory', url: 'file:./agent-memory.db' }),
  options: {
    lastMessages: 20,
    semanticRecall: { topK: 5, messageRange: 2, scope: 'resource' },
    workingMemory: {
      enabled: true,
      scope: 'resource',
      template: '# Profil klienta\n- **Nazwa**:\n- **Waluta rozliczeń**:'
    }
  }
})

export const mastra = new Mastra({
  agents: {
    billing: new Agent({
      id: 'billing',
      name: 'Billing',
      instructions: 'Odpowiadasz wyłącznie na pytania o faktury.',
      model: 'openai/gpt-5-mini',
      tools: { invoiceTool },
      memory
    })
  },
  storage: new LibSQLStore({ id: 'runs', url: 'file:./mastra-runs.db' })
})

Pole requireApproval przyjmuje wartość logiczną albo funkcję i wstrzymuje wykonanie narzędzia do czasu zatwierdzenia. Razem z suspendSchema i resumeSchema daje to obsługę człowieka w pętli bez własnej kolejki zadań.

Rdzeń wymaga Node co najmniej 22.13.0 i deklaruje zależność równorzędną zod w zakresie ^3.25.0 || ^4.0.0. Schematy przechodzą przez Standard Schema, więc zod nie jest formalnie jedyną opcją, ale to jego wersja jest sprawdzana przy instalacji. Kto pisze wyłącznie w TypeScripcie, dostaje wnioskowanie typów od schematu narzędzia aż po wynik kroku workflow.

Przepływy pracy i scorery

Workflow tworzysz przez createWorkflow, kroki przez createStep, a graf składasz metodami then, parallel, branch, dountil, dowhile, foreach, map, sleep, sleepUntil i waitForEvent, zamykając całość wywołaniem commit. Uruchomienie idzie przez createRun. Deklaracja schedule automatycznie przełącza przepływ na silnik zdarzeniowy.

Code
TypeScript
import { createWorkflow, createStep } from '@mastra/core/workflows'
import { z } from 'zod'

const parse = createStep({
  id: 'parse',
  inputSchema: z.object({ raw: z.string() }),
  outputSchema: z.object({ items: z.array(z.string()) }),
  execute: async ({ inputData }) => ({ items: inputData.raw.split('\n') })
})

const enrich = createStep({
  id: 'enrich',
  inputSchema: z.object({ items: z.array(z.string()) }),
  outputSchema: z.object({ enriched: z.number() }),
  execute: async ({ inputData }) => ({ enriched: inputData.items.length })
})

export const ingest = createWorkflow({
  id: 'ingest',
  inputSchema: z.object({ raw: z.string() }),
  outputSchema: z.object({ enriched: z.number() })
})
  .then(parse)
  .then(enrich)
  .commit()

Ewaluacja mieszka w @mastra/evals 1.9.0, z podścieżkami ./scorers/prebuilt, ./scorers/utils i ./checks. Gotowe scorery obejmują między innymi createAnswerRelevancyScorer, createFaithfulnessScorer, createHallucinationScorer, createToxicityScorer, createBiasScorer, createContextPrecisionScorer, createToolCallAccuracyScorerCode i createTrajectoryAccuracyScorerLLM. Własny scorer budujesz przez createScorer z polami id, description, judge, type i prepareRun, a potem łańcuchem preprocess, analyze, generateScore i generateReason.

Code
TypeScript
import { createScorer } from '@mastra/core/evals'
import { createFaithfulnessScorer } from '@mastra/evals/scorers/prebuilt'
import { z } from 'zod'

const hasInvoiceNumber = createScorer({
  id: 'has-invoice-number',
  description: 'Sprawdza, czy odpowiedź zawiera numer faktury',
  type: { input: z.object({ number: z.string() }), output: z.string() }
})
  .analyze(({ run }) => ({ found: run.output.includes(run.input.number) }))
  .generateScore(({ results }) => (results.analyze.found ? 1 : 0))
  .generateReason(({ results }) =>
    results.analyze.found ? 'Numer obecny' : 'Brak numeru w odpowiedzi'
  )

const faithfulness = createFaithfulnessScorer({ model: 'openai/gpt-5-mini' })

Wyniki scorerów trafiają do tego samego magazynu co przebiegi, więc panel pokazuje je obok śladów wykonania. Jeśli już zbierasz metryki w Langfuse albo Braintrust, są dla nich osobne pakiety mostkowe.

Studio, magazyn przebiegów i płatna platforma

Polecenie mastra dev podnosi lokalne studio na porcie 4111, o ile zmienna PORT nie mówi inaczej. Interfejs jest wbudowany w pakiet mastra, w katalogu dist/studio, więc nie instalujesz go osobno. Build trafia do .mastra/output.

Kluczowe pytanie brzmi, gdzie lądują przebiegi i pamięć, kiedy nic nie skonfigurujesz. Odpowiedź jest jednoznaczna i widać ją w kodzie: konstruktor Mastra sprawdza pole storage, a gdy go nie ma, tworzy InMemoryStore i planuje ostrzeżenie o treści:

Code
TEXT
No `storage` configured on Mastra — falling back to an in-memory store. In-memory
storage is not durable: all data is lost on restart, and it is not safe for
production. Configure a persistent storage adapter (e.g. @mastra/libsql,
@mastra/pg, @mastra/cloudflare).

Domyślnie nie ma więc ani pliku SQLite, ani niczego innego na dysku. Wszystko żyje w pamięci procesu i znika po restarcie. Panel jest narzędziem deweloperskim; żeby cokolwiek z niego przetrwało wdrożenie, musisz podpiąć adapter i utrzymywać bazę, a to kolejna ruchoma część w architekturze.

Płatna oferta dzieli się na dwie ścieżki. Wariant samodzielnie hostowany jest darmowy na Apache 2.0, a płatny dodatek Enterprise obejmuje RBAC, SSO, IAM i politykę sieciową, przy jednej rocznej opłacie ryczałtowej bez rozliczania za ślad. To dokładnie te funkcje, które w repozytorium siedzą pod ee/. Druga ścieżka to hostowana Mastra Platform.

PozycjaStarterTeams
Cena miesięczna0 USD250 USD
Zdarzenia obserwowalności100 tys., dalej 10 USD/100 tys.1 mln, dalej 8 USD/100 tys.
Czas CPU24 h, dalej 0,35 USD/h250 h, dalej 0,25 USD/h
Retencja danych15 dni6 miesięcy
Transfer wychodzący10 GB, dalej 0,10 USD/GB100 GB, dalej 0,10 USD/GB
Magazyn wyszukiwania250 MB, dalej 20 USD/GB1 GB, dalej 20 USD/GB
Tokeny przez gatewaystawka rynkowa + 5,5%stawka rynkowa + 5,5%

Cennik renderuje się po stronie serwera, więc da się go odczytać bez uruchamiania JavaScriptu. Dwie rzeczy w nim zwracają uwagę. Po pierwsze, wiersz dla LibSQL nosi nagłówek „Rows Written”, a nadwyżkę wycenia na 2,50 USD za milion odczytów w planie Starter i 2 USD w Teams; zapis i odczyt to dwie różne rzeczy i tabela sama sobie przeczy. Po drugie, dodatek CPU dla planu Enterprise podany jest jako 0,00008 USD za sekundę, co po przeliczeniu daje 0,288 USD za godzinę, czyli wartość pomiędzy stawkami obu tańszych planów.

Sam próg opłacalności też warto policzyć. Licząc wyłącznie linię obserwowalności, Starter kosztuje 10 USD za każde 100 tys. zdarzeń ponad pierwsze 100 tys., a Teams 250 USD plus 8 USD za każde 100 tys. ponad milion. Zrównują się przy 9 mln zdarzeń miesięcznie, gdzie oba wychodzą po 890 USD. Poniżej tego progu Teams kupujesz za retencję, SSO i limity CPU, a nie za tańsze zdarzenia.

Mastra na tle innych frameworków agentowych

Główny argument za Mastrą jest prosty: to biblioteka napisana w TypeScripcie dla TypeScriptu, a nie port z Pythona. Ten argument trzeba jednak podać uczciwie, bo w wersji „konkurencja nie ma niczego w JavaScripcie” już się nie broni.

FrameworkJęzyk pierwotnyOdpowiednik w npmStan portu
MastraTypeScript@mastra/core 1.61.0jedyna implementacja
LangGraphPython@langchain/langgraph 1.4.12aktywny, numer wyższy niż w Pythonie
OpenAI Agents SDKPython@openai/agents 0.17.0aktywny, wciąż linia 0.x
PydanticAIPythonbrakbrak portu
CrewAIPythontylko nieoficjalny crewai 1.0.1martwy od sierpnia 2024
LangChain AgentsPython@langchain/core 1.2.9aktywny

Port LangGraph do JavaScriptu wydano 19 sierpnia 2026 roku, czyli trzy dni przed tym pomiarem, a jego numer wersji jest nawet wyższy niż pythonowej 1.2.11. Twierdzenie o zaniedbanych portach broni się natomiast w innych miejscach: @instructor-ai/instructor stanął na 1.7.0 z 27 stycznia 2025 roku, PydanticAI nie ma w npm nic, a pakiet crewai w npm to prywatna implementacja z repozytorium jaafarskafi1/crew-js, nie kod zespołu CrewAI.

Różnice są więc nie tyle w dostępności, co w charakterze. LangGraph opisuje graf stanu i to jest jego jedyny model. PydanticAI stawia na typowane wyjście przez walidację. CrewAI organizuje pracę wokół ról w zespole. OpenAI Agents SDK jest najwygodniejszy przy jednym dostawcy. Mastra przykrywa szerszy zakres: agent, workflow, pamięć, RAG, ewaluacja, panel i deployer w jednym repozytorium. Ta szerokość jest zaletą przy starcie i obciążeniem przy utrzymaniu, bo aktualizujesz wszystko naraz, a wydania idą co trzy dni.

Firma stojąca za projektem to Kepler Software, Inc., założona w październiku 2024 roku przez ludzi wcześniej związanych z Gatsbym, w tym Sama Bhagwata i Abhiego Aiyera. Strona projektu podaje 27,4 tys. gwiazdek w repozytorium. Zależność od jednej spółki jest realnym ryzykiem: to ona decyduje o tym, co trafia pod ee/, a granica między częścią otwartą a komercyjną przebiega przez katalogi, nie przez osobne pakiety.

Typowe błędy

Uruchomienie na produkcji bez pola storage to najczęstszy. Aplikacja startuje, agent odpowiada, a po restarcie kontenera nie ma ani wątków rozmów, ani śladów wykonania. Ostrzeżenie leci do logu i łatwo je przegapić.

Drugi błąd to potraktowanie Apache-2.0 z rejestru npm jako pełnej odpowiedzi na pytanie o licencję. Wyłączenie dla katalogów ee/ żyje wyłącznie w LICENSE.md w repozytorium, a paczka nie niesie żadnego tekstu licencji.

Trzeci to zakres wersji w package.json. Przy 61 wydaniach mniejszych w siedem miesięcy zapis ^1.0.0 oznacza, że ktoś w zespole wciągnie inny rdzeń niż reszta. Przypnij dokładną wersję i podnoś ją świadomie.

Czwarty to przepisywanie starych przykładów. Sygnatura execute w narzędziach zmieniła się na przekazywanie danych wejściowych wprost, a panel przemianowano z playground na studio, przy czym pakiet @mastra/playground-ui nadal istnieje pod starą nazwą i ma numer 51.0.0.

Piąty to mieszanie adapterów z przypiętym starszym rdzeniem. Progi zależności równorzędnych są różne dla różnych pakietów i @mastra/inngest nie zainstaluje się z rdzeniem starszym niż 1.58.0, nawet jeśli reszta projektu działa. Jeżeli potrzebujesz trwałych, długo żyjących przebiegów, rozważ zamiast tego most do Inngest albo Temporal, które mają do tego własne pakiety.

FAQ

Czy Mastra jest w pełni otwartoźródłowa?

Nie w całości. Kod poza katalogami o nazwie ee/ jest na Apache 2.0. Zawartość katalogów ee/, w tym packages/core/src/auth/ee/, podlega osobnej licencji Enterprise Edition, która dopuszcza rozwój i testy, a użycie produkcyjne uzależnia od pisemnej umowy z Kepler Software.

Gdzie Mastra zapisuje pamięć i przebiegi domyślnie?

Nigdzie trwale. Bez pola storage konstruktor tworzy InMemoryStore, a dane znikają po restarcie procesu. Trwałość włączasz adapterem, na przykład @mastra/libsql z url: 'file:./mastra.db', @mastra/pg albo @mastra/cloudflare.

Czy tempo wydań jest problemem?

Zależy od dyscypliny. Sześćdziesiąt jeden wersji mniejszych w 213 dni to jedna co trzy i pół dnia, a linia 1.x nie ma wersji wycofanych. Przy przypiętej dokładnej wersji i świadomych aktualizacjach da się z tym żyć; przy zakresie ^ czekają cię niespodzianki między środowiskami.

Czym Mastra różni się od LangGraph?

LangGraph modeluje graf stanu i ma port do JavaScriptu w wersji 1.4.12, wydany równolegle z pythonowym. Mastra pokrywa więcej warstw naraz, w tym pamięć, ewaluację i lokalny panel, i jest pisana wyłącznie w TypeScripcie, więc nie tłumaczy pojęć z innego języka.

Ile kosztuje hostowana Mastra Platform?

Plan Starter jest darmowy z limitem 100 tys. zdarzeń obserwowalności, 24 godzinami CPU i 15 dniami retencji. Plan Teams kosztuje 250 USD miesięcznie za 1 mln zdarzeń, 250 godzin CPU i pół roku retencji. Enterprise ma cenę indywidualną.

Czy da się używać Mastry bez jej serwera?

Tak. Agenta i workflow można wywołać bezpośrednio z kodu aplikacji. Adaptery @mastra/next, @mastra/hono czy @mastra/nestjs służą do wystawienia ich w istniejącej aplikacji, a nie do uruchamiania osobnego procesu.

Źródła: repozytorium mastra-ai/mastra, pakiet @mastra/core w npm, cennik Mastra.

Czytaj dalej

Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie