Skip to content

Migrate From Mastra

Mastra is a TypeScript agent framework focused on typed workflows, MCP integration, and developer experience. personaforge covers the same surface area and adds durable DAG execution, circuit breakers, budget enforcement, eval, and a control-plane dashboard in a single package.


Quick comparison

Mastra conceptpersonaforge equivalent
new Agent({ name, instructions, model, tools })createAgent({ name, instructions, model, tools })
createWorkflow().then().commit()createGraph() + DAGEngine or pipe().then()
createStep()Graph task node or pipe().then() stage
tool()tool({ name, description, schema, execute })
MCPClientMCP Client & Server
Memory / thread storageagent.createSession({ sessionId })
createTool() with Zodtool() with Zod schema
generate() / stream()agent.run() / agent.stream()
evalsEvaluation & Benchmarking
deploy() / serverProduction + automatic REST API
TelemetryObservability & OTLP — OpenTelemetry-native

Agent migration

ts
// Mastra
import { Agent } from '@mastra/core/agent';

const agent = new Agent({
  name: 'weather-agent',
  instructions: 'Answer weather questions using the available tools.',
  model: openai('gpt-4o'),
  tools: { getWeather },
});

const result = await agent.generate('What is the weather in London?');
ts
// personaforge
import { createAgent } from 'personaforge';

const agent = createAgent({
  name: 'weather-agent',
  instructions: 'Answer weather questions using the available tools.',
  model: 'gpt-4o',
  apiKey: process.env.OPENAI_API_KEY!,
  tools: [getWeather],
});

const result = await agent.run('What is the weather in London?');
// result.text

Typed step workflow → graph engine

ts
// Mastra
import { createWorkflow, createStep } from '@mastra/core/workflows';

const fetchStep = createStep({
  id: 'fetch',
  execute: async ({ inputData }) => fetchContent(inputData.url),
});

const analyseStep = createStep({
  id: 'analyse',
  execute: async ({ inputData }) => analyseContent(inputData),
});

const workflow = createWorkflow({ id: 'content-pipeline' })
  .then(fetchStep)
  .then(analyseStep)
  .commit();

const result = await workflow.execute({ url: 'https://example.com' });
ts
// personaforge
import { createGraph } from 'personaforge';
import { DAGEngine } from 'personaforge/graph';

const graph = createGraph('content-pipeline', { version: '1.0' })
  .addNode('fetch', {
    kind: 'task',
    execute: (ctx) => fetchContent(ctx.state.variables.url as string),
  })
  .addNode('analyse', {
    kind: 'task',
    execute: (ctx) => analyseContent(ctx.state.results['fetch']),
  })
  .chain('fetch', 'analyse')
  .build();

const engine = new DAGEngine(graph);
const execution = await engine.execute({ variables: { url: 'https://example.com' } });
// execution.state.results

For simpler linear pipelines without full graph semantics, use pipe():

ts
import { pipe } from 'personaforge';

const pipeline = pipe(fetchAgent)
  .then(analyseAgent, { transform: (r) => r.text })
  .then(publishAgent);

const result = await pipeline.run('https://example.com/article');

Tools

ts
// Mastra
import { createTool } from '@mastra/core/tools';
import { z } from 'zod';

const getWeather = createTool({
  id: 'get_weather',
  description: 'Get weather for a city.',
  inputSchema: z.object({ city: z.string() }),
  execute: async ({ context }) => fetchWeather(context.city),
});
ts
// personaforge
import { tool } from 'personaforge';
import { z } from 'zod';

const getWeather = tool({
  name: 'get_weather',
  description: 'Get weather for a city.',
  schema: z.object({ city: z.string().describe('City name') }),
  execute: async ({ city }) => fetchWeather(city),
});

MCP integration

ts
// Mastra
import { MCPClient } from '@mastra/mcp';

const mcp = new MCPClient({ servers: { filesystem: { url: '...' } } });
const tools = await mcp.getTools();
ts
// personaforge
import { createMCPClient } from 'personaforge/mcp';

const mcp = await createMCPClient({
  servers: { filesystem: { command: 'npx', args: ['-y', '@modelcontextprotocol/server-filesystem', '/tmp'] } },
});
const tools = await mcp.listTools();

const agent = createAgent({
  name: 'filesystem-agent',
  instructions: 'Use filesystem tools to answer questions.',
  model: 'gpt-4o',
  apiKey: process.env.OPENAI_API_KEY!,
  tools,
});

See MCP Client & Server for full setup.


Streaming

ts
// Mastra
const stream = await agent.stream('Explain async/await');
for await (const chunk of stream.textStream) process.stdout.write(chunk);

// personaforge
for await (const chunk of agent.stream('Explain async/await')) {
  process.stdout.write(chunk);
}

// Event-level streaming (tool calls, steps)
for await (const event of agent.streamEvents('Plan my vacation')) {
  if (event.type === 'text-delta') process.stdout.write(event.delta ?? '');
  if (event.type === 'tool-call')  console.log('Calling:', event.tool?.name);
}

Memory / threads

ts
// Mastra — thread-based memory
const result = await agent.generate('Hello', { threadId: 'user-123' });
const followUp = await agent.generate('What did I just say?', { threadId: 'user-123' });

// personaforge — explicit sessions
const session = agent.createSession({ sessionId: 'user-123' });
await session.run('Hello');
const result = await session.run('What did I just say?');

What you gain by switching

Mastra gappersonaforge answer
No durable DAG engineGraph Engine — conditional edges, fan-out, event sourcing
No circuit breakersResilience & Circuit Breakers
No USD budget capsBudget Enforcement
Limited multi-tenancyMulti-Tenancy
Partial enterprise auditSOC2/HIPAA audit logging + Control Plane
100+ built-in toolsBuilt-in Tools — web search, databases, code execution, and more

Where to go next

Released under the MIT License.