PineRouterDocs
GuidesModelsAPI referenceApps
SDKs and frameworks

Mastra

Run Mastra agents in TypeScript on this API with a custom OpenAI-compatible model.

Mastra takes a custom OpenAI-compatible endpoint as the agent's model: an object with id, url and apiKey. Set url to https://pinerouter.ai/v1, the base URL, not the chat endpoint.

Install

npm install @mastra/core zod
pnpm add @mastra/core zod
bun add @mastra/core zod

Configure API keys

.env
API_KEY=sk-...

Load it with node --env-file=.env or your framework's own .env support. Keep the key out of your code.

Run

Text

import { Agent } from "@mastra/core/agent";

const model = {
  id: "custom/gpt-6-luna",
  url: "https://pinerouter.ai/v1",
  apiKey: process.env.API_KEY,
} as const;

const agent = new Agent({
  id: "assistant",
  name: "Assistant",
  instructions: "You are concise.",
  model,
});

const res = await agent.generate("Name three rivers in Europe.");
console.log(res.text);

Stream

const stream = await agent.stream("Write a haiku about rivers.");
for await (const chunk of stream.textStream) {
  process.stdout.write(chunk);
}

Tool calling

import { createTool } from "@mastra/core/tools";
import { z } from "zod";

const weatherTool = createTool({
  id: "get-weather",
  description: "Current weather for a city",
  inputSchema: z.object({ city: z.string() }),
  execute: async ({ city }) => ({ city, forecast: "Sunny, 21 C" }),
});

const weatherAgent = new Agent({
  id: "weather",
  name: "Weather",
  instructions: "Answer weather questions with the tool.",
  model,
  tools: { weatherTool },
});

console.log((await weatherAgent.generate("What is the weather in Paris?")).text);

Specifics

  • In id, the part before / is your own label and the part after it is our model id, so custom/gpt-6-luna calls gpt-6-luna.
  • Custom url models use Chat Completions by default. Add api: "responses" to use /v1/responses instead.
  • Mastra also accepts AI SDK providers as model, so the Vercel AI SDK provider works here too.
  • For images, video and other media call Jobs with the HTTP helper inside a tool.
  • Tool calling depends on the model. Test with the model you plan to use.

Next