Runtime Context
This example demonstrates how to use runtime context to create a single agent that dynamically adapts its behavior, capabilities, model selection, tools, memory configuration, input/output processing, and quality scoring based on user subscription tiers.
Prerequisites
This example uses OpenAI models through Mastra's model router. Make sure to add OPENAI_API_KEY to your .env file.
.env
OPENAI_API_KEY=<your-api-key>
Creating the Dynamic Agent
Create an agent that adapts all its properties based on the user's subscription tier:
src/mastra/agents/support-agent.ts
import { Agent } from "@mastra/core/agent";
import { Memory } from "@mastra/memory";
import { LibSQLStore } from "@mastra/libsql";
import { TokenLimiterProcessor } from "@mastra/core/processors";
import { RuntimeContext } from "@mastra/core/runtime-context";
import {
  knowledgeBase,
  ticketSystem,
  advancedAnalytics,
  customIntegration,
} from "../tools/support-tools";
import { CharacterLimiterProcessor } from "../processors/character-limiter";
import { responseQualityScorer } from "../scorers/response-quality";
export type UserTier = "free" | "pro" | "enterprise";
export type SupportRuntimeContext = {
  "user-tier": UserTier;
  language: "en" | "es" | "ja" | "fr";
};
export const supportAgent = new Agent({
  name: "dynamic-support-agent",
  description: "AI support agent that adapts to user subscription tiers",
  instructions: async ({
    runtimeContext,
  }: {
    runtimeContext: RuntimeContext<SupportRuntimeContext>;
  }) => {
    const userTier = runtimeContext.get("user-tier");
    const language = runtimeContext.get("language");
    return `You are a customer support agent for our SaaS platform.
    The current user is on the ${userTier} tier and prefers ${language} language.
    Support guidance based on tier:
    ${userTier === "free" ? "- Provide basic support and documentation links" : ""}
    ${userTier === "pro" ? "- Offer detailed technical support and best practices" : ""}
    ${userTier === "enterprise" ? "- Provide priority support with custom solutions and dedicated assistance" : ""}
    Always respond in ${language} language.
    ${userTier === "enterprise" ? "You have access to custom integrations and advanced analytics." : ""}`;
  },
  model: ({
    runtimeContext,
  }: {
    runtimeContext: RuntimeContext<SupportRuntimeContext>;
  }) => {
    const userTier = runtimeContext.get("user-tier");
    if (userTier === "enterprise") return "openai/gpt-5";
    if (userTier === "pro") return "openai/gpt-4o";
    return "openai/gpt-4o-mini";
  },
  tools: ({
    runtimeContext,
  }: {
    runtimeContext: RuntimeContext<SupportRuntimeContext>;
  }) => {
    const userTier = runtimeContext.get("user-tier");
    const baseTools = [knowledgeBase, ticketSystem];
    if (userTier === "pro" || userTier === "enterprise") {
      baseTools.push(advancedAnalytics);
    }
    if (userTier === "enterprise") {
      baseTools.push(customIntegration);
    }
    return baseTools;
  },
  memory: ({
    runtimeContext,
  }: {
    runtimeContext: RuntimeContext<SupportRuntimeContext>;
  }) => {
    const userTier = runtimeContext.get("user-tier");
    switch (userTier) {
      case "enterprise":
        return new Memory({
          storage: new LibSQLStore({ url: "file:enterprise.db" }),
          options: {
            semanticRecall: { topK: 15, messageRange: 8 },
            workingMemory: { enabled: true },
          },
        });
      case "pro":
        return new Memory({
          storage: new LibSQLStore({ url: "file:pro.db" }),
          options: {
            semanticRecall: { topK: 8, messageRange: 4 },
            workingMemory: { enabled: true },
          },
        });
      case "free":
      default:
        return new Memory({
          storage: new LibSQLStore({ url: "file:free.db" }),
          options: {
            semanticRecall: { topK: 3, messageRange: 2 },
            workingMemory: { enabled: false },
          },
        });
    }
  },
  inputProcessors: ({
    runtimeContext,
  }: {
    runtimeContext: RuntimeContext<SupportRuntimeContext>;
  }) => {
    const userTier = runtimeContext.get("user-tier");
    switch (userTier) {
      case "enterprise":
        return [];
      case "pro":
        return [new CharacterLimiterProcessor(2000)];
      case "free":
      default:
        return [new CharacterLimiterProcessor(500)];
    }
  },
  outputProcessors: ({
    runtimeContext,
  }: {
    runtimeContext: RuntimeContext<SupportRuntimeContext>;
  }) => {
    const userTier = runtimeContext.get("user-tier");
    switch (userTier) {
      case "enterprise":
        return [
          new TokenLimiterProcessor({ limit: 2000, strategy: "truncate" }),
        ];
      case "pro":
        return [
          new TokenLimiterProcessor({ limit: 500, strategy: "truncate" }),
        ];
      case "free":
      default:
        return [
          new TokenLimiterProcessor({ limit: 100, strategy: "truncate" }),
        ];
    }
  },
  scorers: ({
    runtimeContext,
  }: {
    runtimeContext: RuntimeContext<SupportRuntimeContext>;
  }) => {
    const userTier = runtimeContext.get("user-tier");
    if (userTier === "enterprise") {
      return [responseQualityScorer];
    }
    return [];
  },
});
See Agent for a full list of configuration options.
Registering the Agent
Register the agent in your main Mastra instance:
src/mastra/index.ts
import { Mastra } from "@mastra/core/mastra";
import { supportAgent } from "./agents/support-agent";
export const mastra = new Mastra({
  agents: { supportAgent },
});
Usage Examples
Free Tier User
src/examples/free-tier-usage.ts
import "dotenv/config";
import { mastra } from "../mastra";
import { RuntimeContext } from "@mastra/core/runtime-context";
import type { SupportRuntimeContext } from "../mastra/agents/support-agent";
const agent = mastra.getAgent("supportAgent");
const runtimeContext = new RuntimeContext<SupportRuntimeContext>();
runtimeContext.set("user-tier", "free");
runtimeContext.set("language", "en");
const response = await agent.generate(
  "I'm having trouble with API rate limits. Can you help?",
  { runtimeContext },
);
console.log(response.text);
Pro Tier User
src/examples/pro-tier-usage.ts
import "dotenv/config";
import { mastra } from "../mastra";
import { RuntimeContext } from "@mastra/core/runtime-context";
import type { SupportRuntimeContext } from "../mastra/agents/support-agent";
const agent = mastra.getAgent("supportAgent");
const runtimeContext = new RuntimeContext<SupportRuntimeContext>();
runtimeContext.set("user-tier", "pro");
runtimeContext.set("language", "es");
const response = await agent.generate(
  "I need detailed analytics on my API usage patterns and optimization recommendations.",
  { runtimeContext },
);
console.log(response.text);
Enterprise Tier User
src/examples/enterprise-tier-usage.ts
import "dotenv/config";
import { mastra } from "../mastra";
import { RuntimeContext } from "@mastra/core/runtime-context";
import type { SupportRuntimeContext } from "../mastra/agents/support-agent";
const agent = mastra.getAgent("supportAgent");
const runtimeContext = new RuntimeContext<SupportRuntimeContext>();
runtimeContext.set("user-tier", "enterprise");
runtimeContext.set("language", "ja");
const response = await agent.generate(
  "I need to integrate our custom webhook system with your platform and get real-time analytics on our usage across multiple environments.",
  { runtimeContext },
);
console.log(response.text);
Key Benefits
This runtime context approach provides:
- Cost Optimization: Enterprise users get premium models and features while free users get basic functionality
- Resource Management: Input and output limits prevent abuse on lower subscription tiers
- Quality Assurance: Response quality scoring only where it adds business value (enterprise tier)
- Scalable Architecture: A single agent definition serves all user segments without code duplication
- Personalization: Language preferences and tier-specific instructions create tailored experiences