Subchapter 3.3
references/mastra-studio.mdMarkdown6 KBView on GitHub
A Neon Function is a long-lived Node.js 24 process, which makes it a natural host for a Mastra agent: the agent keeps running for the life of the request, and you point its model at the Neon AI Gateway so there are no extra provider keys. You can keep while shipping its traces to a for observability — the agent runs on Neon, the traces are viewable in Mastra.
The shape mirrors any other Node integration (see sentry.md): instantiate at module load, gate on env vars so local dev and unconfigured branches stay a no-op, and pass secrets at deploy time via neon.ts. @mastra/core and @mastra/observability bundle cleanly through neon deploy‘s esbuild with no extra config.
With @mastra/core 1.47+, use a neon/<model> magic string — Mastra reads NEON_AI_GATEWAY_BASE_URL and NEON_AI_GATEWAY_TOKEN from the environment (injected by neon deploy / neon env pull when aiGateway is enabled in neon.ts). No manual url/apiKey or MLflow dialect swap is needed; Mastra routes each model to the correct gateway endpoint.
// src/mastra/agents/pricing.ts
import { Agent } from "@mastra/core/agent";
export const pricingAgent = new Agent({
id: "pricing-analyst",
name: "pricing-analyst",
instructions: "You are a meticulous pricing analyst. …",
model: "neon/gpt-5-mini",
});The MastraPlatformExporter (from @mastra/observability) sends traces to a Mastra Studio project. It reads MASTRA_PLATFORM_ACCESS_TOKEN and MASTRA_PROJECT_ID from the environment.
Gotcha: Observability requires at least one exporter — passing an empty exporters array throws OBSERVABILITY_INVALID_INSTANCE_CONFIG. So omit the observability option entirely until the platform creds are present, keeping the app runnable before the Mastra project exists (and in local dev).
// src/mastra/index.ts
import { Mastra } from "@mastra/core/mastra";
import { Observability, MastraPlatformExporter } from "@mastra/observability";
import { pricingAgent } from "./agents/pricing";
const platformReady = Boolean(
process.env.MASTRA_PLATFORM_ACCESS_TOKEN && process.env.MASTRA_PROJECT_ID,
);
const observability = platformReady
? new Observability({
configs: {
default: { serviceName: "my-app", exporters: [new MastraPlatformExporter()] },
},
})
: undefined;
export const mastra = new Mastra({
agents: { pricingAgent },
...(observability ? { observability } : {}),
});Agents must be registered on the Mastra instance (the agents map) for their .generate() / .stream() calls to be traced. Call them via mastra.getAgent("pricingAgent").
The gateway does not enforce native structured output, so a bare structuredOutput: { schema } can come back missing fields (e.g. a nested meta object), failing Zod validation. Set jsonPromptInjection: true so Mastra injects the schema into the prompt and the model returns the full shape:
const agent = mastra.getAgent("pricingAgent");
const result = await agent.generate(prompt, {
structuredOutput: { schema: myZodSchema, jsonPromptInjection: true },
abortSignal: AbortSignal.timeout(70_000), // bound each attempt; the gateway has an upstream timeout
});
const data = result.object; // validated against myZodSchemaFor resilience, register a second agent on a different model (e.g. neon/claude-haiku-4-5) and fall back to it if the primary attempt throws — both models are reachable on the gateway via the same env vars.
Install the Mastra CLI (npm i -g mastra) and authenticate. Project/token creation needs a live login session:
mastra auth login # opens a browser; required before the steps below
mastra auth whoami # shows your user + org id (org_…)mastra auth tokens create <name> prints a one-time secret (sk_…). This is your MASTRA_PLATFORM_ACCESS_TOKEN.mastra studio projects create TUI is hard to script. Instead, register the project as part of a Studio deploy, which is non-interactive with -y and writes the project id to .mastra-project.json:mastra studio deploy --org org_xxx --project my-app -y
# → .mastra-project.json: { "projectId": "…", "projectName": "my-app", "organizationId": "org_…" }Use that projectId as MASTRA_PROJECT_ID.
Two gotchas:
MASTRA_API_TOKEN in the env for project/deploy commands — it makes the CLI report No organizations found. Rely on the interactive login session instead..env.deploy and .env.local), studio deploy errors with Multiple env files found; pass --env-file <file> to disambiguate.Neon-injected vars (DATABASE_URL, AI Gateway NEON_AI_GATEWAY_*) are automatic. Declare only third-party vars under the function’s env, resolved from process.env at deploy time:
// neon.ts
functions: {
myapp: {
name: "my app",
source: "src/index.ts",
env: {
MASTRA_PROJECT_ID: process.env.MASTRA_PROJECT_ID!,
MASTRA_PLATFORM_ACCESS_TOKEN: process.env.MASTRA_PLATFORM_ACCESS_TOKEN!,
},
},
}Load the values from a git-ignored file at deploy time:
neon deploy --env .env.deploySend a request that exercises the agent, then open the Mastra Studio project’s Observability / Traces view — you’ll see the agent run (model calls, latency, token usage) under the serviceName you configured. Only SPAN_ENDED events are exported, buffered and flushed periodically, so a trace appears a few seconds after the agent run completes.
neon-ai-gateway skill