skills/runtime/references/wiring-mastra.md
Mastra — local-first TypeScript agent framework wired via @ag-ui/mastra.
pnpm add @ag-ui/mastra
# plus your Mastra SDK:
pnpm add @mastra/core
import {
CopilotRuntime,
createCopilotRuntimeHandler,
} from "@copilotkit/runtime/v2";
import { MastraAgent } from "@ag-ui/mastra";
import { Mastra } from "@mastra/core";
import { weatherAgent } from "./agents/weather"; // your Mastra agent
const mastra = new Mastra({
agents: { weather: weatherAgent },
});
const runtime = new CopilotRuntime({
agents: MastraAgent.getLocalAgents({
mastra,
// Required ONLY when your Mastra agent has Memory enabled AND a threadId
// is supplied (the runtime always supplies a threadId, so Memory-enabled
// agents effectively always need this). Passing an empty string throws
// AGENT_MEMORY_MISSING_RESOURCE_ID on every turn. Agents without Memory
// can omit resourceId — e.g. the in-tree `examples/integrations/mastra`
// quickstart calls `MastraAgent.getLocalAgents({ mastra })` with no
// resourceId. Pick a stable per-user identifier in production; a literal
// "default" is fine as a placeholder for single-tenant demos.
resourceId: "default",
}),
});
const handler = createCopilotRuntimeHandler({
runtime,
basePath: "/api/copilotkit",
});
export default { fetch: handler };
If Mastra is running as a separate HTTP service, the simplest wiring is the
generic HttpAgent from @ag-ui/client — it speaks the AG-UI protocol that
Mastra's HTTP server already emits:
import { HttpAgent } from "@ag-ui/client";
const runtime = new CopilotRuntime({
agents: {
weather: new HttpAgent({ url: `${process.env.MASTRA_URL!}/weather` }),
},
});
getLocalAgents already returns Record<string, AbstractAgent>. Wrapping it in a key
({ mastra: getLocalAgents(...) }) breaks the registry.
Source: docs/content/docs/integrations/mastra/quickstart.mdx:213-220.