Mastra

Run a Mastra Agent inside a framework route with key-value memory

Mastra gives you a typed Agent class with .generate(), .stream(), and tool composition. Drop a Mastra agent into a Hono route, store conversation history in key-value storage, and deploy with the rest of your app.

npm install hono @mastra/core @agentuity/keyvalue valibot

Define the Agent

Agent accepts a model spec, instructions, and an optional tool map. Mastra resolves provider strings (openai/..., anthropic/...) through its built-in registry. Run locally with agentuity dev when you want those provider calls to use AI Gateway env wiring.

typescriptsrc/lib/chat-agent.ts
import { Agent } from '@mastra/core/agent';
 
const model = process.env.MASTRA_MODEL;
 
if (!model) {
  throw new Error('Set MASTRA_MODEL to the provider model this agent should use.');
}
 
export const chatAgent = new Agent({
  id: 'chat',
  name: 'Chat Agent',
  instructions: 'You are a concise product support assistant.',
  model,
});

Wire the Route

Validate the request, load the conversation, call agent.generate(), store the new turn. The route is thin; the Mastra agent owns the model call.

typescriptsrc/index.ts
import { Hono } from 'hono';
import { KeyValueClient } from '@agentuity/keyvalue';
import * as v from 'valibot';
import { chatAgent } from './lib/chat-agent';
 
const HISTORY_NAMESPACE = 'mastra-chat';
const HISTORY_LIMIT = 20;
 
const messageSchema = v.object({
  role: v.picklist(['user', 'assistant']),
  content: v.string(),
});
 
const requestSchema = v.object({
  conversationId: v.string(),
  message: v.string(),
});
 
const historySchema = v.array(messageSchema);
 
type ChatMessage = v.InferOutput<typeof messageSchema>;
 
const kv = new KeyValueClient();
const app = new Hono();
 
app.post('/api/chat', async (c) => {
  const body: unknown = await c.req.json();
  const input = v.parse(requestSchema, body);
 
  const stored = await kv.get<unknown>(HISTORY_NAMESPACE, input.conversationId);
  const history: readonly ChatMessage[] = stored.exists
    ? v.parse(historySchema, stored.data)
    : [];
 
  const userMessage: ChatMessage = { role: 'user', content: input.message };
  const result = await chatAgent.generate([...history, userMessage]);
 
  const assistantMessage: ChatMessage = {
    role: 'assistant',
    content: result.text,
  };
 
  const next = [...history, userMessage, assistantMessage].slice(-HISTORY_LIMIT);
  await kv.set(HISTORY_NAMESPACE, input.conversationId, next, {
    ttl: 60 * 60 * 24 * 30,
  });
 
  return c.json({
    conversationId: input.conversationId,
    message: assistantMessage,
    messageCount: next.length,
  });
});
 
export default app;

Tools

Mastra tools are typed with the same createTool() pattern Mastra users already know. Pass them through the tools field on new Agent({ ... }).

import { createTool } from '@mastra/core/tools';
import { z } from 'zod';
 
const model = process.env.MASTRA_MODEL;
 
if (!model) {
  throw new Error('Set MASTRA_MODEL to the provider model this agent should use.');
}
 
const lookupOrder = createTool({
  id: 'lookup-order',
  description: 'Look up an order by ID',
  inputSchema: z.object({ orderId: z.string() }),
  execute: async (input) => {
    // call your database, API, etc.
    return { status: 'shipped', orderId: input.orderId };
  },
});
 
export const supportAgent = new Agent({
  id: 'support',
  name: 'Order Support',
  instructions: 'Help customers with order questions. Use lookup-order when asked about a specific order.',
  model,
  tools: { lookupOrder },
});

The Mastra tool loop runs entirely inside agent.generate(). The route still owns HTTP and storage.

When to reach for Mastra

Pick Mastra when you want its agent abstractions (workflows, multi-agent handoffs, structured output via Mastra primitives) and you do not want to build them on AI SDK directly. Pick raw AI SDK when you want fewer layers.

Next Steps

  • Agents: the plain-function pattern this page wraps
  • Chat with History: the same KV layout, without Mastra
  • AI Gateway: local dev routing and deployed provider env choices