Mastra is a TypeScript agent framework with tools,
workflows, memory and evals. It has an object config for custom
OpenAI-compatible endpoints, which is the shortest path to Hyphen.
Setup guide: this config comes from Mastra's official documentation and has
not been run end to end against the gateway. Corrections to support@hyphen-solution.com.
The model config
Code
import { Agent } from "@mastra/core/agent";export const assistant = new Agent({ id: "assistant", name: "Assistant", instructions: "You are terse and technical. No preamble.", model: { id: "hyphen/minimax-m3", url: "https://api.hyphen-solution.com/v1", apiKey: process.env.HYPHEN_API_KEY, },});const res = await assistant.generate("Explain a Bloom filter in three sentences.");console.log(res.text);
Two things to get right:
url is the base URL. Mastra's docs are emphatic about this. Give it
https://api.hyphen-solution.com/v1, never
https://api.hyphen-solution.com/v1/chat/completions.
id is provider/model. The part before the slash is a label; the part
after is what gets sent upstream. hyphen/minimax-m3 sends minimax-m3,
which is what the gateway expects.
With a tool
Code
import { Agent } from "@mastra/core/agent";import { createTool } from "@mastra/core/tools";import { z } from "zod";export const weatherTool = createTool({ id: "weather-tool", description: "Fetches current weather for a location", inputSchema: z.object({ location: z.string() }), outputSchema: z.object({ location: z.string(), temperatureCelsius: z.number(), conditions: z.string(), }), execute: async ({ location }, { abortSignal }) => { const res = await fetch(`https://wttr.in/${location}?format=j1`, { signal: abortSignal, }); const data = await res.json(); return { location, temperatureCelsius: Number(data.current_condition[0].temp_C), conditions: data.current_condition[0].weatherDesc[0].value, }; },});export const weatherAgent = new Agent({ id: "weather-agent", name: "Weather Agent", instructions: "You are a weather assistant. Use weatherTool to fetch real data. Never guess.", model: { id: "hyphen/minimax-m3", url: "https://api.hyphen-solution.com/v1", apiKey: process.env.HYPHEN_API_KEY, }, tools: { weatherTool },});const res = await weatherAgent.generate("What is the weather in Kuala Lumpur?");console.log(res.text);
Custom headers
The object config also takes headers, which is useful behind a corporate
proxy:
If you already build AI SDK provider instances, Mastra accepts one directly:
Code
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";import { Agent } from "@mastra/core/agent";const hyphen = createOpenAICompatible({ name: "hyphen", baseURL: "https://api.hyphen-solution.com/v1", apiKey: process.env.HYPHEN_API_KEY!,});export const assistant = new Agent({ id: "assistant", name: "Assistant", instructions: "You are terse.", model: hyphen("minimax-m3"),});
This works, but Mastra vendors several AI SDK majors side by side, so your
provider package's major has to match the AI SDK version Mastra expects. The
object config skips that problem entirely, which is why it is the recommended
form on this page. See Vercel AI SDK for the provider
itself.
Per-agent models
Mastra agents each carry their own model, so mix them the way you would in any
multi-agent system. Flagship for the planner, fast model for the workers.
Code
const base = { url: "https://api.hyphen-solution.com/v1", apiKey: process.env.HYPHEN_API_KEY,};const planner = new Agent({ id: "planner", name: "Planner", instructions: "Break the task into steps.", model: { id: "hyphen/minimax-m3", ...base },});const summariser = new Agent({ id: "summariser", name: "Summariser", instructions: "Summarise in five bullets.", model: { id: "hyphen/minimax-m2.5", ...base },});
Both meter at the same per-token rate. minimax-m2.5 is the speed-and-volume
tier, so the saving is in tokens, not on the rate card. See
Choosing a model.
Gotchas
url is the base URL, not the chat endpoint.
id needs the provider/model shape.
Give it output headroom. The M-series reason before answering. Empty
agent replies usually mean the output budget was spent on thinking. See
Choosing a model.
No embedding models, so Mastra's vector memory needs an embedder from
elsewhere.
429 means the monthly budget is spent. Long workflows reach it faster
than single calls. See Handling the 429 cap.