@mastra/server 1.79.0-alpha.8 → 1.79.0-alpha.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/{api-schema-manifest-CXiWNHBm.js → api-schema-manifest-CWRIJP-B.js} +2 -2
  2. package/dist/{api-schema-manifest-CXiWNHBm.js.map → api-schema-manifest-CWRIJP-B.js.map} +1 -1
  3. package/dist/{api-schema-manifest-Cs2cYG-m.cjs → api-schema-manifest-DUseI2VG.cjs} +2 -2
  4. package/dist/{api-schema-manifest-Cs2cYG-m.cjs.map → api-schema-manifest-DUseI2VG.cjs.map} +1 -1
  5. package/dist/{dist-BGzSzjTX.cjs → dist-9c3PXXpk.cjs} +100 -7
  6. package/dist/{dist-BGzSzjTX.cjs.map → dist-9c3PXXpk.cjs.map} +1 -1
  7. package/dist/{dist-BeXd4jq2.js → dist-DGCnbhNe.js} +100 -7
  8. package/dist/{dist-BeXd4jq2.js.map → dist-DGCnbhNe.js.map} +1 -1
  9. package/dist/docs/SKILL.md +1 -1
  10. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  11. package/dist/docs/references/docs-guides-mcp-authentication-authorization.md +2 -2
  12. package/dist/docs/references/reference-observability-tracing-advanced-queries.md +11 -9
  13. package/dist/{observability-new-endpoints-outfOdc8.cjs → observability-new-endpoints-AMp9bnMV.cjs} +4 -4
  14. package/dist/observability-new-endpoints-AMp9bnMV.cjs.map +1 -0
  15. package/dist/{observability-new-endpoints-7wGwP3se.js → observability-new-endpoints-BU8JYPfh.js} +5 -5
  16. package/dist/{observability-new-endpoints-7wGwP3se.js.map → observability-new-endpoints-BU8JYPfh.js.map} +1 -1
  17. package/dist/{routes-gZRBp2vK.cjs → routes-DPojsNf1.cjs} +2 -2
  18. package/dist/{routes-gZRBp2vK.cjs.map → routes-DPojsNf1.cjs.map} +1 -1
  19. package/dist/{routes-BYcXmjX3.js → routes-rwufkyUe.js} +2 -2
  20. package/dist/{routes-BYcXmjX3.js.map → routes-rwufkyUe.js.map} +1 -1
  21. package/dist/server/handlers/agent-builder.cjs +1 -1
  22. package/dist/server/handlers/agent-builder.js +1 -1
  23. package/dist/server/handlers/agent-controller.cjs +190 -170
  24. package/dist/server/handlers/agent-controller.cjs.map +1 -1
  25. package/dist/server/handlers/agent-controller.d.ts +165 -155
  26. package/dist/server/handlers/agent-controller.d.ts.map +1 -1
  27. package/dist/server/handlers/agent-controller.js +190 -170
  28. package/dist/server/handlers/agent-controller.js.map +1 -1
  29. package/dist/server/handlers/observability-new-endpoints.cjs +1 -1
  30. package/dist/server/handlers/observability-new-endpoints.d.ts +8 -0
  31. package/dist/server/handlers/observability-new-endpoints.d.ts.map +1 -1
  32. package/dist/server/handlers/observability-new-endpoints.js +1 -1
  33. package/dist/server/handlers/observability-shared.cjs +31 -21
  34. package/dist/server/handlers/observability-shared.cjs.map +1 -1
  35. package/dist/server/handlers/observability-shared.d.ts +9 -4
  36. package/dist/server/handlers/observability-shared.d.ts.map +1 -1
  37. package/dist/server/handlers/observability-shared.js +31 -20
  38. package/dist/server/handlers/observability-shared.js.map +1 -1
  39. package/dist/server/handlers/observability.cjs +1 -1
  40. package/dist/server/handlers/observability.js +1 -1
  41. package/dist/server/handlers/system.cjs +2 -2
  42. package/dist/server/handlers/system.d.ts +4 -0
  43. package/dist/server/handlers/system.d.ts.map +1 -1
  44. package/dist/server/handlers/system.js +2 -2
  45. package/dist/server/schemas/index.cjs +1 -1
  46. package/dist/server/schemas/index.js +1 -1
  47. package/dist/server/schemas/system.d.ts +4 -0
  48. package/dist/server/schemas/system.d.ts.map +1 -1
  49. package/dist/server/server-adapter/index.cjs +1 -1
  50. package/dist/server/server-adapter/index.js +1 -1
  51. package/dist/server/server-adapter/routes/observability.d.ts +4 -0
  52. package/dist/server/server-adapter/routes/observability.d.ts.map +1 -1
  53. package/dist/server/server-adapter/routes/system.d.ts +4 -0
  54. package/dist/server/server-adapter/routes/system.d.ts.map +1 -1
  55. package/dist/{system-DvpPWdIa.cjs → system-BvpFMIJB.cjs} +3 -1
  56. package/dist/system-BvpFMIJB.cjs.map +1 -0
  57. package/dist/{system-BLcPGYXT.js → system-CpzPxRRq.js} +3 -1
  58. package/dist/system-CpzPxRRq.js.map +1 -0
  59. package/package.json +6 -6
  60. package/dist/observability-new-endpoints-outfOdc8.cjs.map +0 -1
  61. package/dist/system-BLcPGYXT.js.map +0 -1
  62. package/dist/system-DvpPWdIa.cjs.map +0 -1
@@ -13,8 +13,9 @@ import { z } from "zod/v4";
13
13
  * `new Mastra({ agentControllers })`) exposes its sessions over HTTP so
14
14
  * non-terminal clients — e.g. a browser-based MastraCode — can create sessions,
15
15
  * send messages, stream events, and drive run-control. Each route resolves its
16
- * target AgentController by id, then operates on a session bound to a
17
- * `resourceId`. Mutating routes use get-or-create resolution so reconnects
16
+ * target AgentController by id, then operates on the session addressed by
17
+ * `sessionId` (which works on the threads and memory of its `resourceId`).
18
+ * Mutating routes use get-or-create resolution so reconnects
18
19
  * resume rather than fork the conversation; read routes only inspect existing
19
20
  * live sessions.
20
21
  */
@@ -62,54 +63,50 @@ function getAgentControllerOrThrow(mastra, controllerId) {
62
63
  return controller;
63
64
  }
64
65
  /**
65
- * Get-or-create a session. Only the create-session route calls this: it is the one request that carries the
66
- * tags and exact thread a conversation starts on.
66
+ * The resource of the session addressed by `sessionId`, without materializing
67
+ * it: the live session's resource, else the resource of the thread sharing the
68
+ * session's id, else `sessionId` itself (the default when a session is created
69
+ * without a `sessionId`).
67
70
  */
68
- async function startSession(controller, resourceId, options, requestContext) {
69
- await controller.init();
70
- const { tags, scope, threadId } = options ?? {};
71
- const id = threadId ?? (scope ? `${resourceId}::${scope}` : resourceId);
72
- return controller.createSession({
73
- resourceId,
74
- id,
75
- ownerId: controller.id,
76
- tags,
77
- scope,
78
- threadId,
79
- requestContext
80
- });
71
+ async function resolveSessionResourceId(controller, sessionId) {
72
+ const live = await controller.getSession(sessionId);
73
+ if (live) return live.identity.getResourceId();
74
+ return (await controller.queryThreadById({ threadId: sessionId }))?.resourceId ?? sessionId;
81
75
  }
82
76
  /**
83
- * Resolve the session every other route acts on: the live one, or a lost one (e.g. after a restart) rebuilt on
84
- * its most recent stored thread. Never starts a conversation, so a write that arrives before the session was
85
- * started fails instead of landing on a thread nobody reads.
77
+ * Resolve the session addressed by `sessionId` that every route other than create acts on: the live one, or a
78
+ * lost one (e.g. after a restart) rebuilt from storage. When a thread with the session's id exists, the session
79
+ * resumes on that thread under the thread's resource (hosts that use `sessionId === threadId` recover their own
80
+ * thread even when many sessions share one resource); otherwise it resumes on `resourceId = sessionId`, the
81
+ * default `POST /sessions` applies when no `sessionId` is sent. Never starts a conversation, so a write that
82
+ * arrives before the session was started fails instead of landing on a thread nobody reads.
86
83
  */
87
- async function getSession(controller, resourceId, options, requestContext) {
84
+ async function getSession(controller, sessionId, requestContext) {
88
85
  await controller.init();
89
- const scope = options?.scope;
90
- const id = scope ? `${resourceId}::${scope}` : resourceId;
86
+ const live = await controller.getSession(sessionId);
87
+ const thread = live ? null : await controller.queryThreadById({ threadId: sessionId });
91
88
  try {
92
89
  return await controller.createSession({
93
- resourceId,
94
- id,
90
+ id: sessionId,
91
+ resourceId: live?.identity.getResourceId() ?? thread?.resourceId ?? sessionId,
95
92
  ownerId: controller.id,
96
- scope,
93
+ threadId: thread ? sessionId : void 0,
97
94
  resumeOnly: true,
98
95
  requestContext
99
96
  });
100
97
  } catch (error) {
101
98
  if (error instanceof Error && error.code === "SESSION_NOT_STARTED") throw new HTTPException(404, {
102
- message: `No session has been started for resource "${resourceId}". Create it with POST /agent-controller/:controllerId/sessions first.`,
99
+ message: `No session "${sessionId}" has been started. Create it with POST /agent-controller/:controllerId/sessions first.`,
103
100
  cause: error
104
101
  });
105
102
  throw error;
106
103
  }
107
104
  }
108
- async function getExistingSession(controller, resourceId, scope, requestContext) {
105
+ async function getExistingSession(controller, sessionId, requestContext) {
109
106
  await controller.init();
110
- const session = await controller.getSessionByResource(resourceId, scope, requestContext);
107
+ const session = await controller.getSession(sessionId, requestContext);
111
108
  if (session) return session;
112
- return getSession(controller, resourceId, { scope }, requestContext);
109
+ return getSession(controller, sessionId, requestContext);
113
110
  }
114
111
  /**
115
112
  * Acknowledges a session operation that keeps running after the response is
@@ -146,22 +143,29 @@ function ackBackgroundSessionWork({ work, session, mastra, operation }) {
146
143
  const controllerIdPathParams = z.object({ controllerId: z.string() });
147
144
  const sessionPathParams = z.object({
148
145
  controllerId: z.string(),
149
- resourceId: z.string()
146
+ sessionId: z.string()
150
147
  });
151
148
  /**
152
- * Optional session scope (mirrors `AgentController.createSession`'s `scope`):
153
- * requests with the same resourceId but different scopes address independent
154
- * sessions (e.g. one per git worktree). Sent as a `sessionScope` query param
155
- * on session routes; named to avoid colliding with the model-switch `scope`.
149
+ * Sessions used to be addressed by `resourceId` plus `sessionScope`. The param is gone: reject it
150
+ * rather than drop it, so an older client's scoped session can't quietly merge into another one.
156
151
  */
157
- const sessionScopeQuerySchema = z.object({ sessionScope: z.string().optional() });
158
- const sessionStateQuerySchema = sessionScopeQuerySchema.extend({ threadId: z.string().optional() });
152
+ const removedSessionScope = z.never({ error: "sessionScope was removed; address the session by sessionId" }).optional();
153
+ const sessionQuerySchema = z.object({ sessionScope: removedSessionScope });
154
+ const sessionStateQuerySchema = sessionQuerySchema.extend({ threadId: z.string().optional() });
159
155
  const createSessionBodySchema = z.object({
160
- resourceId: z.string(),
156
+ /**
157
+ * Whose threads and memory the session works on. Optional when `sessionId` is
158
+ * sent: the session then resumes on the resource it already has (the live
159
+ * session's, or the resource of the thread with the session's id), falling
160
+ * back to the session id.
161
+ */
162
+ resourceId: z.string().optional(),
163
+ /** Address of the session. Defaults to `resourceId`. */
164
+ sessionId: z.string().optional(),
165
+ sessionScope: removedSessionScope,
161
166
  tags: z.record(z.string(), z.string()).optional(),
162
- threadId: z.string().optional(),
163
- sessionScope: z.string().optional()
164
- });
167
+ threadId: z.string().optional()
168
+ }).refine((body) => body.resourceId !== void 0 || body.sessionId !== void 0, { message: "resourceId or sessionId is required" });
165
169
  const MAX_FILE_DATA_LENGTH = 14 * 1024 * 1024;
166
170
  const MAX_TOTAL_FILE_DATA_LENGTH = 28 * 1024 * 1024;
167
171
  /**
@@ -223,7 +227,7 @@ const createThreadBodySchema = z.object({ title: z.string().optional() });
223
227
  const renameThreadBodySchema = z.object({ title: z.string() });
224
228
  const threadPathParams = z.object({
225
229
  controllerId: z.string(),
226
- resourceId: z.string(),
230
+ sessionId: z.string(),
227
231
  threadId: z.string()
228
232
  });
229
233
  const cloneThreadBodySchema = z.object({
@@ -232,14 +236,14 @@ const cloneThreadBodySchema = z.object({
232
236
  });
233
237
  const controllerPaginationNumber = z.coerce.number().int().min(0);
234
238
  const listMessagesQuerySchema = z.object({
239
+ sessionScope: removedSessionScope,
235
240
  /** @deprecated Use page and perPage instead. */
236
241
  limit: controllerPaginationNumber.optional(),
237
242
  page: controllerPaginationNumber.optional(),
238
243
  perPage: z.preprocess((value) => value === "false" ? false : value, z.union([z.literal(false), controllerPaginationNumber])).optional(),
239
244
  orderBy: messageOrderBySchema,
240
245
  include: includeSchema,
241
- filter: filterSchema,
242
- sessionScope: z.string().optional()
246
+ filter: filterSchema
243
247
  }).superRefine((value, ctx) => {
244
248
  if (value.limit === void 0) return;
245
249
  for (const field of [
@@ -260,8 +264,8 @@ const listMessagesQuerySchema = z.object({
260
264
  * only their own threads. Malformed JSON is treated as "no filter".
261
265
  */
262
266
  const listThreadsQuerySchema = z.object({
267
+ sessionScope: removedSessionScope,
263
268
  limit: z.coerce.number().optional(),
264
- sessionScope: z.string().optional(),
265
269
  tags: z.preprocess((value) => {
266
270
  if (typeof value !== "string" || value.length === 0) return void 0;
267
271
  try {
@@ -296,6 +300,7 @@ const sendNotificationBodySchema = z.object({
296
300
  const listAgentControllersResponseSchema = z.object({ agentControllers: z.array(z.object({ id: z.string() })) });
297
301
  const createSessionResponseSchema = z.object({
298
302
  controllerId: z.string(),
303
+ sessionId: z.string(),
299
304
  resourceId: z.string(),
300
305
  threadId: z.string().optional()
301
306
  });
@@ -371,6 +376,7 @@ const taskSnapshotSchema = z.object({
371
376
  });
372
377
  const sessionStateResponseSchema = z.object({
373
378
  controllerId: z.string(),
379
+ sessionId: z.string(),
374
380
  resourceId: z.string(),
375
381
  threadId: z.string().optional(),
376
382
  modeId: z.string(),
@@ -487,25 +493,34 @@ const LIST_AGENT_CONTROLLERS_ROUTE = createRoute({
487
493
  const CREATE_AGENT_CONTROLLER_SESSION_ROUTE = createRoute({
488
494
  method: "POST",
489
495
  path: "/agent-controller/:controllerId/sessions",
496
+ queryParamSchema: sessionQuerySchema,
490
497
  responseType: "json",
491
498
  pathParamSchema: controllerIdPathParams,
492
499
  bodySchema: createSessionBodySchema,
493
500
  responseSchema: createSessionResponseSchema,
494
501
  summary: "Create or resume a controller session",
495
- description: "Creates a session for the given resourceId, or returns the existing one (get-or-create), so reconnects resume the conversation. Every other session route requires a started session and returns 404 until one exists or can be recovered from a stored thread.",
502
+ description: "Creates the session addressed by `sessionId` on the given resourceId, or returns the existing one (get-or-create), so reconnects resume the conversation. Without a `sessionId` the session is addressed by `resourceId`; without a `resourceId` it resumes on the resource it already has. Every other session route requires a started session and returns 404 until one exists or can be recovered from a stored thread.",
496
503
  tags: ["AgentController"],
497
504
  requiresAuth: true,
498
505
  requiresPermission: "agent-controller:execute",
499
- handler: async ({ mastra, controllerId, resourceId, sessionScope, tags, threadId, requestContext }) => {
506
+ handler: async ({ mastra, controllerId, resourceId, sessionId, tags, threadId, requestContext }) => {
500
507
  try {
508
+ const controller = getAgentControllerOrThrow(mastra, controllerId);
509
+ await controller.init();
510
+ const id = sessionId ?? resourceId;
511
+ const session = await controller.createSession({
512
+ id,
513
+ resourceId: resourceId ?? await resolveSessionResourceId(controller, id),
514
+ ownerId: controller.id,
515
+ tags,
516
+ threadId,
517
+ requestContext
518
+ });
501
519
  return {
502
520
  controllerId,
503
- resourceId,
504
- threadId: (await startSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, {
505
- tags,
506
- scope: sessionScope,
507
- threadId
508
- }, requestContext)).thread.getId() ?? void 0
521
+ sessionId: session.identity.getId(),
522
+ resourceId: session.identity.getResourceId(),
523
+ threadId: session.thread.getId() ?? void 0
509
524
  };
510
525
  } catch (error) {
511
526
  return handleError(error, "error creating controller session");
@@ -552,20 +567,20 @@ function toWireEvent(event) {
552
567
  }
553
568
  const STREAM_AGENT_CONTROLLER_SESSION_ROUTE = createRoute({
554
569
  method: "GET",
555
- path: "/agent-controller/:controllerId/sessions/:resourceId/stream",
570
+ path: "/agent-controller/:controllerId/sessions/:sessionId/stream",
571
+ queryParamSchema: sessionQuerySchema,
556
572
  responseType: "stream",
557
573
  streamFormat: "sse",
558
574
  sseFlushOnConnect: true,
559
575
  pathParamSchema: sessionPathParams,
560
- queryParamSchema: sessionScopeQuerySchema,
561
576
  summary: "Stream controller session events",
562
577
  description: "Subscribes to a session’s event bus and streams events to the client over SSE.",
563
578
  tags: ["AgentController", "Streaming"],
564
579
  requiresAuth: true,
565
580
  requiresPermission: "agent-controller:read",
566
- handler: async ({ mastra, controllerId, resourceId, sessionScope, abortSignal, requestContext }) => {
581
+ handler: async ({ mastra, controllerId, sessionId, abortSignal, requestContext }) => {
567
582
  try {
568
- const session = await getExistingSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, sessionScope, requestContext);
583
+ const session = await getExistingSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext);
569
584
  let cleanedUp = false;
570
585
  let heartbeat;
571
586
  let unsubscribe;
@@ -634,10 +649,10 @@ const STREAM_AGENT_CONTROLLER_SESSION_ROUTE = createRoute({
634
649
  });
635
650
  const SEND_AGENT_CONTROLLER_MESSAGE_ROUTE = createRoute({
636
651
  method: "POST",
637
- path: "/agent-controller/:controllerId/sessions/:resourceId/messages",
652
+ path: "/agent-controller/:controllerId/sessions/:sessionId/messages",
653
+ queryParamSchema: sessionQuerySchema,
638
654
  responseType: "json",
639
655
  pathParamSchema: sessionPathParams,
640
- queryParamSchema: sessionScopeQuerySchema,
641
656
  bodySchema: sendMessageBodySchema,
642
657
  responseSchema: ackResponseSchema,
643
658
  summary: "Send a message to a controller session",
@@ -645,9 +660,9 @@ const SEND_AGENT_CONTROLLER_MESSAGE_ROUTE = createRoute({
645
660
  tags: ["AgentController", "Streaming"],
646
661
  requiresAuth: true,
647
662
  requiresPermission: "agent-controller:execute",
648
- handler: async ({ mastra, controllerId, resourceId, sessionScope, message, files, requestContext }) => {
663
+ handler: async ({ mastra, controllerId, sessionId, message, files, requestContext }) => {
649
664
  try {
650
- const session = await getSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, { scope: sessionScope }, requestContext);
665
+ const session = await getSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext);
651
666
  const author = getRequestMessageAuthor(requestContext);
652
667
  ackBackgroundSessionWork({
653
668
  work: session.sendMessage({
@@ -668,19 +683,19 @@ const SEND_AGENT_CONTROLLER_MESSAGE_ROUTE = createRoute({
668
683
  });
669
684
  const ABORT_AGENT_CONTROLLER_SESSION_ROUTE = createRoute({
670
685
  method: "POST",
671
- path: "/agent-controller/:controllerId/sessions/:resourceId/abort",
686
+ path: "/agent-controller/:controllerId/sessions/:sessionId/abort",
687
+ queryParamSchema: sessionQuerySchema,
672
688
  responseType: "json",
673
689
  pathParamSchema: sessionPathParams,
674
- queryParamSchema: sessionScopeQuerySchema,
675
690
  responseSchema: ackResponseSchema,
676
691
  summary: "Abort a controller session run",
677
692
  description: "Aborts the in-flight run for the session, if any.",
678
693
  tags: ["AgentController"],
679
694
  requiresAuth: true,
680
695
  requiresPermission: "agent-controller:execute",
681
- handler: async ({ mastra, controllerId, resourceId, sessionScope, requestContext }) => {
696
+ handler: async ({ mastra, controllerId, sessionId, requestContext }) => {
682
697
  try {
683
- (await getSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, { scope: sessionScope }, requestContext)).abort();
698
+ (await getSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext)).abort();
684
699
  return { ok: true };
685
700
  } catch (error) {
686
701
  return handleError(error, "error aborting controller session");
@@ -689,10 +704,10 @@ const ABORT_AGENT_CONTROLLER_SESSION_ROUTE = createRoute({
689
704
  });
690
705
  const AGENT_CONTROLLER_TOOL_APPROVAL_ROUTE = createRoute({
691
706
  method: "POST",
692
- path: "/agent-controller/:controllerId/sessions/:resourceId/tool-approval",
707
+ path: "/agent-controller/:controllerId/sessions/:sessionId/tool-approval",
708
+ queryParamSchema: sessionQuerySchema,
693
709
  responseType: "json",
694
710
  pathParamSchema: sessionPathParams,
695
- queryParamSchema: sessionScopeQuerySchema,
696
711
  bodySchema: toolApprovalBodySchema,
697
712
  responseSchema: toolCommandAckResponseSchema,
698
713
  summary: "Respond to a controller tool approval",
@@ -700,9 +715,9 @@ const AGENT_CONTROLLER_TOOL_APPROVAL_ROUTE = createRoute({
700
715
  tags: ["AgentController"],
701
716
  requiresAuth: true,
702
717
  requiresPermission: "agent-controller:execute",
703
- handler: async ({ mastra, controllerId, resourceId, sessionScope, toolCallId, approved, alwaysAllowCategory, requestContext }) => {
718
+ handler: async ({ mastra, controllerId, sessionId, toolCallId, approved, alwaysAllowCategory, requestContext }) => {
704
719
  try {
705
- const session = await getSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, { scope: sessionScope }, requestContext);
720
+ const session = await getSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext);
706
721
  if ((toolCallId ? session.approval.isArmed({ toolCallId }) : session.approval.isArmed()) || !toolCallId) {
707
722
  const result = session.respondToToolApproval({
708
723
  toolCallId,
@@ -742,10 +757,10 @@ const AGENT_CONTROLLER_TOOL_APPROVAL_ROUTE = createRoute({
742
757
  });
743
758
  const AGENT_CONTROLLER_TOOL_SUSPENSION_ROUTE = createRoute({
744
759
  method: "POST",
745
- path: "/agent-controller/:controllerId/sessions/:resourceId/tool-suspension",
760
+ path: "/agent-controller/:controllerId/sessions/:sessionId/tool-suspension",
761
+ queryParamSchema: sessionQuerySchema,
746
762
  responseType: "json",
747
763
  pathParamSchema: sessionPathParams,
748
- queryParamSchema: sessionScopeQuerySchema,
749
764
  bodySchema: toolSuspensionBodySchema,
750
765
  responseSchema: toolCommandAckResponseSchema,
751
766
  summary: "Respond to a suspended controller tool",
@@ -753,9 +768,9 @@ const AGENT_CONTROLLER_TOOL_SUSPENSION_ROUTE = createRoute({
753
768
  tags: ["AgentController"],
754
769
  requiresAuth: true,
755
770
  requiresPermission: "agent-controller:execute",
756
- handler: async ({ mastra, controllerId, resourceId, sessionScope, toolCallId, runId, resumeData, requestContext }) => {
771
+ handler: async ({ mastra, controllerId, sessionId, toolCallId, runId, resumeData, requestContext }) => {
757
772
  try {
758
- const session = await getSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, { scope: sessionScope }, requestContext);
773
+ const session = await getSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext);
759
774
  const claim = session.claimToolSuspension(toolCallId, runId);
760
775
  if (!claim.accepted) return {
761
776
  ok: false,
@@ -779,10 +794,10 @@ const AGENT_CONTROLLER_TOOL_SUSPENSION_ROUTE = createRoute({
779
794
  });
780
795
  const STEER_AGENT_CONTROLLER_SESSION_ROUTE = createRoute({
781
796
  method: "POST",
782
- path: "/agent-controller/:controllerId/sessions/:resourceId/steer",
797
+ path: "/agent-controller/:controllerId/sessions/:sessionId/steer",
798
+ queryParamSchema: sessionQuerySchema,
783
799
  responseType: "json",
784
800
  pathParamSchema: sessionPathParams,
785
- queryParamSchema: sessionScopeQuerySchema,
786
801
  bodySchema: steerBodySchema,
787
802
  responseSchema: ackResponseSchema,
788
803
  summary: "Steer the in-flight run",
@@ -790,9 +805,9 @@ const STEER_AGENT_CONTROLLER_SESSION_ROUTE = createRoute({
790
805
  tags: ["AgentController"],
791
806
  requiresAuth: true,
792
807
  requiresPermission: "agent-controller:execute",
793
- handler: async ({ mastra, controllerId, resourceId, sessionScope, message, files, requestContext }) => {
808
+ handler: async ({ mastra, controllerId, sessionId, message, files, requestContext }) => {
794
809
  try {
795
- const session = await getSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, { scope: sessionScope }, requestContext);
810
+ const session = await getSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext);
796
811
  const author = getRequestMessageAuthor(requestContext);
797
812
  ackBackgroundSessionWork({
798
813
  work: session.steer({
@@ -813,10 +828,10 @@ const STEER_AGENT_CONTROLLER_SESSION_ROUTE = createRoute({
813
828
  });
814
829
  const SWITCH_AGENT_CONTROLLER_MODE_ROUTE = createRoute({
815
830
  method: "POST",
816
- path: "/agent-controller/:controllerId/sessions/:resourceId/mode",
831
+ path: "/agent-controller/:controllerId/sessions/:sessionId/mode",
832
+ queryParamSchema: sessionQuerySchema,
817
833
  responseType: "json",
818
834
  pathParamSchema: sessionPathParams,
819
- queryParamSchema: sessionScopeQuerySchema,
820
835
  bodySchema: switchModeBodySchema,
821
836
  responseSchema: ackResponseSchema,
822
837
  summary: "Switch the session mode",
@@ -824,9 +839,9 @@ const SWITCH_AGENT_CONTROLLER_MODE_ROUTE = createRoute({
824
839
  tags: ["AgentController"],
825
840
  requiresAuth: true,
826
841
  requiresPermission: "agent-controller:execute",
827
- handler: async ({ mastra, controllerId, resourceId, sessionScope, modeId, requestContext }) => {
842
+ handler: async ({ mastra, controllerId, sessionId, modeId, requestContext }) => {
828
843
  try {
829
- await (await getSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, { scope: sessionScope }, requestContext)).mode.switch({ modeId });
844
+ await (await getSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext)).mode.switch({ modeId });
830
845
  return { ok: true };
831
846
  } catch (error) {
832
847
  return handleError(error, "error switching controller mode");
@@ -835,10 +850,10 @@ const SWITCH_AGENT_CONTROLLER_MODE_ROUTE = createRoute({
835
850
  });
836
851
  const SWITCH_AGENT_CONTROLLER_MODEL_ROUTE = createRoute({
837
852
  method: "POST",
838
- path: "/agent-controller/:controllerId/sessions/:resourceId/model",
853
+ path: "/agent-controller/:controllerId/sessions/:sessionId/model",
854
+ queryParamSchema: sessionQuerySchema,
839
855
  responseType: "json",
840
856
  pathParamSchema: sessionPathParams,
841
- queryParamSchema: sessionScopeQuerySchema,
842
857
  bodySchema: switchModelBodySchema,
843
858
  responseSchema: ackResponseSchema,
844
859
  summary: "Switch the session model",
@@ -846,9 +861,9 @@ const SWITCH_AGENT_CONTROLLER_MODEL_ROUTE = createRoute({
846
861
  tags: ["AgentController"],
847
862
  requiresAuth: true,
848
863
  requiresPermission: "agent-controller:execute",
849
- handler: async ({ mastra, controllerId, resourceId, sessionScope, modelId, thinkingLevel, requestContext }) => {
864
+ handler: async ({ mastra, controllerId, sessionId, modelId, thinkingLevel, requestContext }) => {
850
865
  try {
851
- await (await getSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, { scope: sessionScope }, requestContext)).model.switch(modelId, { thinkingLevel });
866
+ await (await getSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext)).model.switch(modelId, { thinkingLevel });
852
867
  return { ok: true };
853
868
  } catch (error) {
854
869
  return handleError(error, "error switching controller model");
@@ -857,10 +872,10 @@ const SWITCH_AGENT_CONTROLLER_MODEL_ROUTE = createRoute({
857
872
  });
858
873
  const SWITCH_AGENT_CONTROLLER_THREAD_ROUTE = createRoute({
859
874
  method: "POST",
860
- path: "/agent-controller/:controllerId/sessions/:resourceId/thread",
875
+ path: "/agent-controller/:controllerId/sessions/:sessionId/thread",
876
+ queryParamSchema: sessionQuerySchema,
861
877
  responseType: "json",
862
878
  pathParamSchema: sessionPathParams,
863
- queryParamSchema: sessionScopeQuerySchema,
864
879
  bodySchema: switchThreadBodySchema,
865
880
  responseSchema: ackResponseSchema,
866
881
  summary: "Switch the session thread",
@@ -868,9 +883,9 @@ const SWITCH_AGENT_CONTROLLER_THREAD_ROUTE = createRoute({
868
883
  tags: ["AgentController"],
869
884
  requiresAuth: true,
870
885
  requiresPermission: "agent-controller:execute",
871
- handler: async ({ mastra, controllerId, resourceId, sessionScope, threadId, requestContext }) => {
886
+ handler: async ({ mastra, controllerId, sessionId, threadId, requestContext }) => {
872
887
  try {
873
- const session = await getSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, { scope: sessionScope }, requestContext);
888
+ const session = await getSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext);
874
889
  if (session.thread.getId() !== threadId) await session.thread.switch({
875
890
  threadId,
876
891
  requestContext
@@ -883,22 +898,23 @@ const SWITCH_AGENT_CONTROLLER_THREAD_ROUTE = createRoute({
883
898
  });
884
899
  const TRANSFER_AGENT_CONTROLLER_THREAD_OWNERSHIP_ROUTE = createRoute({
885
900
  method: "POST",
886
- path: "/agent-controller/:controllerId/sessions/:resourceId/threads/:threadId/owner",
901
+ path: "/agent-controller/:controllerId/sessions/:sessionId/threads/:threadId/owner",
902
+ queryParamSchema: sessionQuerySchema,
887
903
  responseType: "json",
888
904
  pathParamSchema: threadPathParams,
889
- queryParamSchema: sessionScopeQuerySchema,
890
905
  responseSchema: transferOwnershipResponseSchema,
891
906
  summary: "Take ownership of a thread",
892
907
  description: "Transfers ownership of the specified thread to the authenticated user from the request context. The thread must belong to the session's resource, and the caller needs memory write access to it. The session's active thread does not change.",
893
908
  tags: ["AgentController", "Threads"],
894
909
  requiresAuth: true,
895
910
  requiresPermission: "agent-controller:execute",
896
- handler: async ({ mastra, controllerId, resourceId, sessionScope, threadId, requestContext }) => {
911
+ handler: async ({ mastra, controllerId, sessionId, threadId, requestContext }) => {
897
912
  try {
898
913
  const ownerId = getRequestMessageAuthor(requestContext)?.id;
899
914
  if (!ownerId) throw new HTTPException(401, { message: "An authenticated user is required to transfer thread ownership" });
900
915
  const controller = getAgentControllerOrThrow(mastra, controllerId);
901
916
  await controller.init();
917
+ const resourceId = await resolveSessionResourceId(controller, sessionId);
902
918
  const thread = await controller.queryThreadById({ threadId });
903
919
  if (!thread || thread.resourceId !== resourceId) throw new HTTPException(404, { message: "Thread not found" });
904
920
  await enforceThreadAccess({
@@ -909,7 +925,7 @@ const TRANSFER_AGENT_CONTROLLER_THREAD_OWNERSHIP_ROUTE = createRoute({
909
925
  effectiveResourceId: resourceId,
910
926
  permission: MastraFGAPermissions.MEMORY_WRITE
911
927
  });
912
- await (await getSession(controller, resourceId, { scope: sessionScope }, requestContext)).thread.transferOwnership({
928
+ await (await getSession(controller, sessionId, requestContext)).thread.transferOwnership({
913
929
  toOwnerId: ownerId,
914
930
  threadId
915
931
  });
@@ -924,7 +940,7 @@ const TRANSFER_AGENT_CONTROLLER_THREAD_OWNERSHIP_ROUTE = createRoute({
924
940
  });
925
941
  const GET_AGENT_CONTROLLER_SESSION_STATE_ROUTE = createRoute({
926
942
  method: "GET",
927
- path: "/agent-controller/:controllerId/sessions/:resourceId",
943
+ path: "/agent-controller/:controllerId/sessions/:sessionId",
928
944
  responseType: "json",
929
945
  pathParamSchema: sessionPathParams,
930
946
  queryParamSchema: sessionStateQuerySchema,
@@ -934,9 +950,10 @@ const GET_AGENT_CONTROLLER_SESSION_STATE_ROUTE = createRoute({
934
950
  tags: ["AgentController"],
935
951
  requiresAuth: true,
936
952
  requiresPermission: "agent-controller:read",
937
- handler: async ({ mastra, controllerId, resourceId, sessionScope, threadId: requestedThreadId, requestContext }) => {
953
+ handler: async ({ mastra, controllerId, sessionId, threadId: requestedThreadId, requestContext }) => {
938
954
  try {
939
- const session = await getExistingSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, sessionScope, requestContext);
955
+ const session = await getExistingSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext);
956
+ const resourceId = session.identity.getResourceId();
940
957
  const ds = session.displayState.get();
941
958
  const threadId = requestedThreadId ?? session.thread.getId() ?? void 0;
942
959
  const storage = mastra.getStorage();
@@ -960,6 +977,7 @@ const GET_AGENT_CONTROLLER_SESSION_STATE_ROUTE = createRoute({
960
977
  const oneOfOptional = (value, allowed) => allowed.includes(value) ? value : void 0;
961
978
  return {
962
979
  controllerId,
980
+ sessionId: session.identity.getId(),
963
981
  resourceId,
964
982
  threadId,
965
983
  modeId: session.mode.get(),
@@ -1049,19 +1067,20 @@ const LIST_AGENT_CONTROLLER_ACTIVE_RUNS_ROUTE = createRoute({
1049
1067
  });
1050
1068
  const LIST_AGENT_CONTROLLER_THREADS_ROUTE = createRoute({
1051
1069
  method: "GET",
1052
- path: "/agent-controller/:controllerId/sessions/:resourceId/threads",
1070
+ path: "/agent-controller/:controllerId/sessions/:sessionId/threads",
1053
1071
  responseType: "json",
1054
1072
  pathParamSchema: sessionPathParams,
1055
1073
  queryParamSchema: listThreadsQuerySchema,
1056
1074
  responseSchema: listThreadsResponseSchema,
1057
1075
  summary: "List session threads",
1058
- description: "Lists the threads for the session’s resource, most-recently-updated first. Pass `limit` to return only the newest N (e.g. for a sidebar). Pass `tags` (a JSON-encoded object) to scope the list to threads matching every tag — e.g. `{ projectPath }` so git worktrees sharing a resourceId each see only their own threads.",
1076
+ description: "Lists every thread of the session’s resource (not only the session’s own threads), most-recently-updated first. Pass `limit` to return only the newest N (e.g. for a sidebar). Pass `tags` (a JSON-encoded object) to scope the list to threads matching every tag — e.g. `{ projectPath }` so git worktrees sharing a resourceId each see only their own threads.",
1059
1077
  tags: ["AgentController"],
1060
1078
  requiresAuth: true,
1061
1079
  requiresPermission: "agent-controller:read",
1062
- handler: async ({ mastra, controllerId, resourceId, limit, tags }) => {
1080
+ handler: async ({ mastra, controllerId, sessionId, limit, tags }) => {
1063
1081
  try {
1064
1082
  const controller = getAgentControllerOrThrow(mastra, controllerId);
1083
+ const resourceId = await resolveSessionResourceId(controller, sessionId);
1065
1084
  const threads = await controller.queryThreads({ resourceId });
1066
1085
  const getTags = (t) => {
1067
1086
  const metadata = t.metadata ?? {};
@@ -1096,10 +1115,10 @@ const LIST_AGENT_CONTROLLER_THREADS_ROUTE = createRoute({
1096
1115
  });
1097
1116
  const SEND_AGENT_CONTROLLER_NOTIFICATION_ROUTE = createRoute({
1098
1117
  method: "POST",
1099
- path: "/agent-controller/:controllerId/sessions/:resourceId/notifications",
1118
+ path: "/agent-controller/:controllerId/sessions/:sessionId/notifications",
1119
+ queryParamSchema: sessionQuerySchema,
1100
1120
  responseType: "json",
1101
1121
  pathParamSchema: sessionPathParams,
1102
- queryParamSchema: sessionScopeQuerySchema,
1103
1122
  bodySchema: sendNotificationBodySchema,
1104
1123
  responseSchema: z.object({
1105
1124
  accepted: z.boolean(),
@@ -1112,9 +1131,9 @@ const SEND_AGENT_CONTROLLER_NOTIFICATION_ROUTE = createRoute({
1112
1131
  tags: ["AgentController"],
1113
1132
  requiresAuth: true,
1114
1133
  requiresPermission: "agent-controller:execute",
1115
- handler: async ({ mastra, controllerId, resourceId, sessionScope, source, kind, summary, priority, payload, sourceId, dedupeKey, coalesceKey, attributes, metadata, requestContext }) => {
1134
+ handler: async ({ mastra, controllerId, sessionId, source, kind, summary, priority, payload, sourceId, dedupeKey, coalesceKey, attributes, metadata, requestContext }) => {
1116
1135
  try {
1117
- const result = await (await getSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, { scope: sessionScope }, requestContext)).sendNotificationSignal({
1136
+ const result = await (await getSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext)).sendNotificationSignal({
1118
1137
  source,
1119
1138
  kind,
1120
1139
  summary,
@@ -1139,10 +1158,10 @@ const SEND_AGENT_CONTROLLER_NOTIFICATION_ROUTE = createRoute({
1139
1158
  });
1140
1159
  const CREATE_AGENT_CONTROLLER_THREAD_ROUTE = createRoute({
1141
1160
  method: "POST",
1142
- path: "/agent-controller/:controllerId/sessions/:resourceId/threads",
1161
+ path: "/agent-controller/:controllerId/sessions/:sessionId/threads",
1162
+ queryParamSchema: sessionQuerySchema,
1143
1163
  responseType: "json",
1144
1164
  pathParamSchema: sessionPathParams,
1145
- queryParamSchema: sessionScopeQuerySchema,
1146
1165
  bodySchema: createThreadBodySchema,
1147
1166
  responseSchema: threadResponseSchema,
1148
1167
  summary: "Create a new thread",
@@ -1150,9 +1169,9 @@ const CREATE_AGENT_CONTROLLER_THREAD_ROUTE = createRoute({
1150
1169
  tags: ["AgentController", "Threads"],
1151
1170
  requiresAuth: true,
1152
1171
  requiresPermission: "agent-controller:execute",
1153
- handler: async ({ mastra, controllerId, resourceId, sessionScope, title, requestContext }) => {
1172
+ handler: async ({ mastra, controllerId, sessionId, title, requestContext }) => {
1154
1173
  try {
1155
- const thread = await (await getSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, { scope: sessionScope }, requestContext)).thread.create({
1174
+ const thread = await (await getSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext)).thread.create({
1156
1175
  title,
1157
1176
  requestContext
1158
1177
  });
@@ -1170,19 +1189,19 @@ const CREATE_AGENT_CONTROLLER_THREAD_ROUTE = createRoute({
1170
1189
  });
1171
1190
  const DELETE_AGENT_CONTROLLER_THREAD_ROUTE = createRoute({
1172
1191
  method: "DELETE",
1173
- path: "/agent-controller/:controllerId/sessions/:resourceId/threads/:threadId",
1192
+ path: "/agent-controller/:controllerId/sessions/:sessionId/threads/:threadId",
1193
+ queryParamSchema: sessionQuerySchema,
1174
1194
  responseType: "json",
1175
1195
  pathParamSchema: threadPathParams,
1176
- queryParamSchema: sessionScopeQuerySchema,
1177
1196
  responseSchema: ackResponseSchema,
1178
1197
  summary: "Delete a thread",
1179
1198
  description: "Deletes a thread. If the deleted thread is the active one, the session is unbound.",
1180
1199
  tags: ["AgentController", "Threads"],
1181
1200
  requiresAuth: true,
1182
1201
  requiresPermission: "agent-controller:execute",
1183
- handler: async ({ mastra, controllerId, resourceId, sessionScope, threadId, requestContext }) => {
1202
+ handler: async ({ mastra, controllerId, sessionId, threadId, requestContext }) => {
1184
1203
  try {
1185
- await (await getSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, { scope: sessionScope }, requestContext)).thread.delete({
1204
+ await (await getSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext)).thread.delete({
1186
1205
  threadId,
1187
1206
  requestContext
1188
1207
  });
@@ -1194,10 +1213,10 @@ const DELETE_AGENT_CONTROLLER_THREAD_ROUTE = createRoute({
1194
1213
  });
1195
1214
  const RENAME_AGENT_CONTROLLER_THREAD_ROUTE = createRoute({
1196
1215
  method: "PUT",
1197
- path: "/agent-controller/:controllerId/sessions/:resourceId/threads/:threadId",
1216
+ path: "/agent-controller/:controllerId/sessions/:sessionId/threads/:threadId",
1217
+ queryParamSchema: sessionQuerySchema,
1198
1218
  responseType: "json",
1199
1219
  pathParamSchema: threadPathParams,
1200
- queryParamSchema: sessionScopeQuerySchema,
1201
1220
  bodySchema: renameThreadBodySchema,
1202
1221
  responseSchema: ackResponseSchema,
1203
1222
  summary: "Rename a thread",
@@ -1205,9 +1224,9 @@ const RENAME_AGENT_CONTROLLER_THREAD_ROUTE = createRoute({
1205
1224
  tags: ["AgentController", "Threads"],
1206
1225
  requiresAuth: true,
1207
1226
  requiresPermission: "agent-controller:execute",
1208
- handler: async ({ mastra, controllerId, resourceId, sessionScope, threadId, title, requestContext }) => {
1227
+ handler: async ({ mastra, controllerId, sessionId, threadId, title, requestContext }) => {
1209
1228
  try {
1210
- const session = await getSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, { scope: sessionScope }, requestContext);
1229
+ const session = await getSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext);
1211
1230
  if (session.thread.getId() !== threadId) await session.thread.switch({
1212
1231
  threadId,
1213
1232
  requestContext
@@ -1221,10 +1240,10 @@ const RENAME_AGENT_CONTROLLER_THREAD_ROUTE = createRoute({
1221
1240
  });
1222
1241
  const CLONE_AGENT_CONTROLLER_THREAD_ROUTE = createRoute({
1223
1242
  method: "POST",
1224
- path: "/agent-controller/:controllerId/sessions/:resourceId/threads/clone",
1243
+ path: "/agent-controller/:controllerId/sessions/:sessionId/threads/clone",
1244
+ queryParamSchema: sessionQuerySchema,
1225
1245
  responseType: "json",
1226
1246
  pathParamSchema: sessionPathParams,
1227
- queryParamSchema: sessionScopeQuerySchema,
1228
1247
  bodySchema: cloneThreadBodySchema,
1229
1248
  responseSchema: threadResponseSchema,
1230
1249
  summary: "Clone a thread",
@@ -1232,9 +1251,9 @@ const CLONE_AGENT_CONTROLLER_THREAD_ROUTE = createRoute({
1232
1251
  tags: ["AgentController", "Threads"],
1233
1252
  requiresAuth: true,
1234
1253
  requiresPermission: "agent-controller:execute",
1235
- handler: async ({ mastra, controllerId, resourceId, sessionScope, sourceThreadId, title, requestContext }) => {
1254
+ handler: async ({ mastra, controllerId, sessionId, sourceThreadId, title, requestContext }) => {
1236
1255
  try {
1237
- const thread = await (await getSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, { scope: sessionScope }, requestContext)).thread.clone({
1256
+ const thread = await (await getSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext)).thread.clone({
1238
1257
  sourceThreadId,
1239
1258
  title,
1240
1259
  requestContext
@@ -1253,7 +1272,7 @@ const CLONE_AGENT_CONTROLLER_THREAD_ROUTE = createRoute({
1253
1272
  });
1254
1273
  const LIST_AGENT_CONTROLLER_THREAD_MESSAGES_ROUTE = createRoute({
1255
1274
  method: "GET",
1256
- path: "/agent-controller/:controllerId/sessions/:resourceId/threads/:threadId/messages",
1275
+ path: "/agent-controller/:controllerId/sessions/:sessionId/threads/:threadId/messages",
1257
1276
  responseType: "json",
1258
1277
  pathParamSchema: threadPathParams,
1259
1278
  queryParamSchema: listMessagesQuerySchema,
@@ -1263,12 +1282,13 @@ const LIST_AGENT_CONTROLLER_THREAD_MESSAGES_ROUTE = createRoute({
1263
1282
  tags: ["AgentController", "Threads"],
1264
1283
  requiresAuth: true,
1265
1284
  requiresPermission: "agent-controller:read",
1266
- handler: async ({ mastra, controllerId, resourceId, threadId, limit, page, perPage, orderBy, include, filter, requestContext }) => {
1285
+ handler: async ({ mastra, controllerId, sessionId, threadId, limit, page, perPage, orderBy, include, filter, requestContext }) => {
1267
1286
  try {
1268
1287
  if (limit !== void 0 && (perPage !== void 0 || orderBy !== void 0 || include !== void 0 || filter !== void 0)) throw new HTTPException(400, { message: "limit can only be combined with page; use perPage instead" });
1269
1288
  const controller = getAgentControllerOrThrow(mastra, controllerId);
1289
+ const resourceId = await resolveSessionResourceId(controller, sessionId);
1270
1290
  const thread = await controller.queryThreadById({ threadId });
1271
- if (!thread || resourceId && thread.resourceId && thread.resourceId !== resourceId) throw new HTTPException(404, { message: "Thread not found" });
1291
+ if (!thread || thread.resourceId && thread.resourceId !== resourceId) throw new HTTPException(404, { message: "Thread not found" });
1272
1292
  await enforceThreadAccess({
1273
1293
  mastra,
1274
1294
  requestContext,
@@ -1315,10 +1335,10 @@ const LIST_AGENT_CONTROLLER_THREAD_MESSAGES_ROUTE = createRoute({
1315
1335
  });
1316
1336
  const FOLLOW_UP_AGENT_CONTROLLER_SESSION_ROUTE = createRoute({
1317
1337
  method: "POST",
1318
- path: "/agent-controller/:controllerId/sessions/:resourceId/follow-up",
1338
+ path: "/agent-controller/:controllerId/sessions/:sessionId/follow-up",
1339
+ queryParamSchema: sessionQuerySchema,
1319
1340
  responseType: "json",
1320
1341
  pathParamSchema: sessionPathParams,
1321
- queryParamSchema: sessionScopeQuerySchema,
1322
1342
  bodySchema: followUpBodySchema,
1323
1343
  responseSchema: ackResponseSchema,
1324
1344
  summary: "Queue a follow-up message",
@@ -1326,9 +1346,9 @@ const FOLLOW_UP_AGENT_CONTROLLER_SESSION_ROUTE = createRoute({
1326
1346
  tags: ["AgentController"],
1327
1347
  requiresAuth: true,
1328
1348
  requiresPermission: "agent-controller:execute",
1329
- handler: async ({ mastra, controllerId, resourceId, sessionScope, message, files, requestContext }) => {
1349
+ handler: async ({ mastra, controllerId, sessionId, message, files, requestContext }) => {
1330
1350
  try {
1331
- const session = await getSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, { scope: sessionScope }, requestContext);
1351
+ const session = await getSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext);
1332
1352
  ackBackgroundSessionWork({
1333
1353
  work: session.followUp({
1334
1354
  content: message,
@@ -1398,20 +1418,20 @@ const GET_AGENT_CONTROLLER_WORKSPACE_STATUS_ROUTE = createRoute({
1398
1418
  });
1399
1419
  const GET_AGENT_CONTROLLER_OM_RECORD_ROUTE = createRoute({
1400
1420
  method: "GET",
1401
- path: "/agent-controller/:controllerId/sessions/:resourceId/om",
1421
+ path: "/agent-controller/:controllerId/sessions/:sessionId/om",
1422
+ queryParamSchema: sessionQuerySchema,
1402
1423
  responseType: "json",
1403
1424
  pathParamSchema: sessionPathParams,
1404
- queryParamSchema: sessionScopeQuerySchema,
1405
1425
  responseSchema: omRecordResponseSchema,
1406
1426
  summary: "Get observational memory record",
1407
1427
  description: "Returns the current observational memory record for the session’s thread/resource.",
1408
1428
  tags: ["AgentController"],
1409
1429
  requiresAuth: true,
1410
1430
  requiresPermission: "agent-controller:read",
1411
- handler: async ({ mastra, controllerId, resourceId, sessionScope, requestContext }) => {
1431
+ handler: async ({ mastra, controllerId, sessionId, requestContext }) => {
1412
1432
  try {
1413
1433
  const controller = getAgentControllerOrThrow(mastra, controllerId);
1414
- const session = await getExistingSession(controller, resourceId, sessionScope, requestContext);
1434
+ const session = await getExistingSession(controller, sessionId, requestContext);
1415
1435
  return { record: await controller.getObservationalMemoryRecord(session) ?? void 0 };
1416
1436
  } catch (error) {
1417
1437
  return handleError(error, "error reading controller OM record");
@@ -1420,10 +1440,10 @@ const GET_AGENT_CONTROLLER_OM_RECORD_ROUTE = createRoute({
1420
1440
  });
1421
1441
  const SET_AGENT_CONTROLLER_RESOURCE_ID_ROUTE = createRoute({
1422
1442
  method: "POST",
1423
- path: "/agent-controller/:controllerId/sessions/:resourceId/resource",
1443
+ path: "/agent-controller/:controllerId/sessions/:sessionId/resource",
1444
+ queryParamSchema: sessionQuerySchema,
1424
1445
  responseType: "json",
1425
1446
  pathParamSchema: sessionPathParams,
1426
- queryParamSchema: sessionScopeQuerySchema,
1427
1447
  bodySchema: z.object({ newResourceId: z.string() }),
1428
1448
  responseSchema: ackResponseSchema,
1429
1449
  summary: "Change the session resource ID",
@@ -1431,10 +1451,10 @@ const SET_AGENT_CONTROLLER_RESOURCE_ID_ROUTE = createRoute({
1431
1451
  tags: ["AgentController"],
1432
1452
  requiresAuth: true,
1433
1453
  requiresPermission: "agent-controller:execute",
1434
- handler: async ({ mastra, controllerId, resourceId, sessionScope, newResourceId, requestContext }) => {
1454
+ handler: async ({ mastra, controllerId, sessionId, newResourceId, requestContext }) => {
1435
1455
  try {
1436
1456
  const controller = getAgentControllerOrThrow(mastra, controllerId);
1437
- const session = await getSession(controller, resourceId, { scope: sessionScope }, requestContext);
1457
+ const session = await getSession(controller, sessionId, requestContext);
1438
1458
  await controller.setResourceId(session, { resourceId: newResourceId });
1439
1459
  return { ok: true };
1440
1460
  } catch (error) {
@@ -1444,20 +1464,20 @@ const SET_AGENT_CONTROLLER_RESOURCE_ID_ROUTE = createRoute({
1444
1464
  });
1445
1465
  const GET_AGENT_CONTROLLER_RESOURCE_IDS_ROUTE = createRoute({
1446
1466
  method: "GET",
1447
- path: "/agent-controller/:controllerId/sessions/:resourceId/resources",
1467
+ path: "/agent-controller/:controllerId/sessions/:sessionId/resources",
1468
+ queryParamSchema: sessionQuerySchema,
1448
1469
  responseType: "json",
1449
1470
  pathParamSchema: sessionPathParams,
1450
- queryParamSchema: sessionScopeQuerySchema,
1451
1471
  responseSchema: z.object({ resourceIds: z.array(z.string()) }),
1452
1472
  summary: "Get known resource IDs",
1453
1473
  description: "Lists the resource IDs known to this session (from threads).",
1454
1474
  tags: ["AgentController"],
1455
1475
  requiresAuth: true,
1456
1476
  requiresPermission: "agent-controller:read",
1457
- handler: async ({ mastra, controllerId, resourceId, sessionScope, requestContext }) => {
1477
+ handler: async ({ mastra, controllerId, sessionId, requestContext }) => {
1458
1478
  try {
1459
1479
  const controller = getAgentControllerOrThrow(mastra, controllerId);
1460
- const session = await getExistingSession(controller, resourceId, sessionScope, requestContext);
1480
+ const session = await getExistingSession(controller, sessionId, requestContext);
1461
1481
  return { resourceIds: await controller.getKnownResourceIds(session) };
1462
1482
  } catch (error) {
1463
1483
  return handleError(error, "error listing controller resource IDs");
@@ -1499,20 +1519,20 @@ function getAgentForSession(controller, session) {
1499
1519
  }
1500
1520
  const GET_AGENT_CONTROLLER_GOAL_ROUTE = createRoute({
1501
1521
  method: "GET",
1502
- path: "/agent-controller/:controllerId/sessions/:resourceId/goal",
1522
+ path: "/agent-controller/:controllerId/sessions/:sessionId/goal",
1523
+ queryParamSchema: sessionQuerySchema,
1503
1524
  responseType: "json",
1504
1525
  pathParamSchema: sessionPathParams,
1505
- queryParamSchema: sessionScopeQuerySchema,
1506
1526
  responseSchema: goalResponseSchema,
1507
1527
  summary: "Get the current goal",
1508
1528
  description: "Returns the active/paused/done goal objective for the session’s thread, if any.",
1509
1529
  tags: ["AgentController", "Goals"],
1510
1530
  requiresAuth: true,
1511
1531
  requiresPermission: "agent-controller:read",
1512
- handler: async ({ mastra, controllerId, resourceId, sessionScope, requestContext }) => {
1532
+ handler: async ({ mastra, controllerId, sessionId, requestContext }) => {
1513
1533
  try {
1514
1534
  const controller = getAgentControllerOrThrow(mastra, controllerId);
1515
- const session = await getExistingSession(controller, resourceId, sessionScope, requestContext);
1535
+ const session = await getExistingSession(controller, sessionId, requestContext);
1516
1536
  const threadId = session.thread.getId();
1517
1537
  if (!threadId) return { goal: void 0 };
1518
1538
  return { goal: await getAgentForSession(controller, session).getObjective({ threadId }) ?? void 0 };
@@ -1523,10 +1543,10 @@ const GET_AGENT_CONTROLLER_GOAL_ROUTE = createRoute({
1523
1543
  });
1524
1544
  const SET_AGENT_CONTROLLER_GOAL_ROUTE = createRoute({
1525
1545
  method: "POST",
1526
- path: "/agent-controller/:controllerId/sessions/:resourceId/goal",
1546
+ path: "/agent-controller/:controllerId/sessions/:sessionId/goal",
1547
+ queryParamSchema: sessionQuerySchema,
1527
1548
  responseType: "json",
1528
1549
  pathParamSchema: sessionPathParams,
1529
- queryParamSchema: sessionScopeQuerySchema,
1530
1550
  bodySchema: setGoalBodySchema,
1531
1551
  responseSchema: goalResponseSchema,
1532
1552
  summary: "Set a goal",
@@ -1534,10 +1554,10 @@ const SET_AGENT_CONTROLLER_GOAL_ROUTE = createRoute({
1534
1554
  tags: ["AgentController", "Goals"],
1535
1555
  requiresAuth: true,
1536
1556
  requiresPermission: "agent-controller:execute",
1537
- handler: async ({ mastra, controllerId, resourceId, sessionScope, objective, judgeModelId, maxRuns, requestContext }) => {
1557
+ handler: async ({ mastra, controllerId, sessionId, objective, judgeModelId, maxRuns, requestContext }) => {
1538
1558
  try {
1539
1559
  const controller = getAgentControllerOrThrow(mastra, controllerId);
1540
- const session = await getSession(controller, resourceId, { scope: sessionScope }, requestContext);
1560
+ const session = await getSession(controller, sessionId, requestContext);
1541
1561
  const threadId = session.thread.getId();
1542
1562
  if (!threadId) throw new HTTPException(400, { message: "session has no active thread" });
1543
1563
  return { goal: await getAgentForSession(controller, session).setObjective(objective, {
@@ -1553,10 +1573,10 @@ const SET_AGENT_CONTROLLER_GOAL_ROUTE = createRoute({
1553
1573
  });
1554
1574
  const UPDATE_AGENT_CONTROLLER_GOAL_ROUTE = createRoute({
1555
1575
  method: "PUT",
1556
- path: "/agent-controller/:controllerId/sessions/:resourceId/goal",
1576
+ path: "/agent-controller/:controllerId/sessions/:sessionId/goal",
1577
+ queryParamSchema: sessionQuerySchema,
1557
1578
  responseType: "json",
1558
1579
  pathParamSchema: sessionPathParams,
1559
- queryParamSchema: sessionScopeQuerySchema,
1560
1580
  bodySchema: updateGoalBodySchema,
1561
1581
  responseSchema: goalResponseSchema,
1562
1582
  summary: "Update goal options",
@@ -1564,10 +1584,10 @@ const UPDATE_AGENT_CONTROLLER_GOAL_ROUTE = createRoute({
1564
1584
  tags: ["AgentController", "Goals"],
1565
1585
  requiresAuth: true,
1566
1586
  requiresPermission: "agent-controller:execute",
1567
- handler: async ({ mastra, controllerId, resourceId, sessionScope, judgeModelId, maxRuns, status, requestContext }) => {
1587
+ handler: async ({ mastra, controllerId, sessionId, judgeModelId, maxRuns, status, requestContext }) => {
1568
1588
  try {
1569
1589
  const controller = getAgentControllerOrThrow(mastra, controllerId);
1570
- const session = await getSession(controller, resourceId, { scope: sessionScope }, requestContext);
1590
+ const session = await getSession(controller, sessionId, requestContext);
1571
1591
  const threadId = session.thread.getId();
1572
1592
  if (!threadId) throw new HTTPException(400, { message: "session has no active thread" });
1573
1593
  return { goal: await getAgentForSession(controller, session).updateObjectiveOptions({
@@ -1583,20 +1603,20 @@ const UPDATE_AGENT_CONTROLLER_GOAL_ROUTE = createRoute({
1583
1603
  });
1584
1604
  const CLEAR_AGENT_CONTROLLER_GOAL_ROUTE = createRoute({
1585
1605
  method: "DELETE",
1586
- path: "/agent-controller/:controllerId/sessions/:resourceId/goal",
1606
+ path: "/agent-controller/:controllerId/sessions/:sessionId/goal",
1607
+ queryParamSchema: sessionQuerySchema,
1587
1608
  responseType: "json",
1588
1609
  pathParamSchema: sessionPathParams,
1589
- queryParamSchema: sessionScopeQuerySchema,
1590
1610
  responseSchema: ackResponseSchema,
1591
1611
  summary: "Clear the goal",
1592
1612
  description: "Removes the active goal from the session’s thread.",
1593
1613
  tags: ["AgentController", "Goals"],
1594
1614
  requiresAuth: true,
1595
1615
  requiresPermission: "agent-controller:execute",
1596
- handler: async ({ mastra, controllerId, resourceId, sessionScope, requestContext }) => {
1616
+ handler: async ({ mastra, controllerId, sessionId, requestContext }) => {
1597
1617
  try {
1598
1618
  const controller = getAgentControllerOrThrow(mastra, controllerId);
1599
- const session = await getSession(controller, resourceId, { scope: sessionScope }, requestContext);
1619
+ const session = await getSession(controller, sessionId, requestContext);
1600
1620
  const threadId = session.thread.getId();
1601
1621
  if (!threadId) throw new HTTPException(400, { message: "session has no active thread" });
1602
1622
  await getAgentForSession(controller, session).clearObjective({ threadId });
@@ -1608,19 +1628,19 @@ const CLEAR_AGENT_CONTROLLER_GOAL_ROUTE = createRoute({
1608
1628
  });
1609
1629
  const GET_AGENT_CONTROLLER_PERMISSIONS_ROUTE = createRoute({
1610
1630
  method: "GET",
1611
- path: "/agent-controller/:controllerId/sessions/:resourceId/permissions",
1631
+ path: "/agent-controller/:controllerId/sessions/:sessionId/permissions",
1632
+ queryParamSchema: sessionQuerySchema,
1612
1633
  responseType: "json",
1613
1634
  pathParamSchema: sessionPathParams,
1614
- queryParamSchema: sessionScopeQuerySchema,
1615
1635
  responseSchema: permissionRulesResponseSchema,
1616
1636
  summary: "Get permission rules",
1617
1637
  description: "Returns the current permission rules (per-category and per-tool policies) for the session.",
1618
1638
  tags: ["AgentController", "Permissions"],
1619
1639
  requiresAuth: true,
1620
1640
  requiresPermission: "agent-controller:read",
1621
- handler: async ({ mastra, controllerId, resourceId, sessionScope, requestContext }) => {
1641
+ handler: async ({ mastra, controllerId, sessionId, requestContext }) => {
1622
1642
  try {
1623
- const rules = (await getExistingSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, sessionScope, requestContext)).permissions.getRules();
1643
+ const rules = (await getExistingSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext)).permissions.getRules();
1624
1644
  return {
1625
1645
  categories: rules.categories,
1626
1646
  tools: rules.tools
@@ -1632,10 +1652,10 @@ const GET_AGENT_CONTROLLER_PERMISSIONS_ROUTE = createRoute({
1632
1652
  });
1633
1653
  const SET_AGENT_CONTROLLER_CATEGORY_PERMISSION_ROUTE = createRoute({
1634
1654
  method: "PUT",
1635
- path: "/agent-controller/:controllerId/sessions/:resourceId/permissions/category",
1655
+ path: "/agent-controller/:controllerId/sessions/:sessionId/permissions/category",
1656
+ queryParamSchema: sessionQuerySchema,
1636
1657
  responseType: "json",
1637
1658
  pathParamSchema: sessionPathParams,
1638
- queryParamSchema: sessionScopeQuerySchema,
1639
1659
  bodySchema: setCategoryPermissionBodySchema,
1640
1660
  responseSchema: ackResponseSchema,
1641
1661
  summary: "Set permission for a tool category",
@@ -1643,9 +1663,9 @@ const SET_AGENT_CONTROLLER_CATEGORY_PERMISSION_ROUTE = createRoute({
1643
1663
  tags: ["AgentController", "Permissions"],
1644
1664
  requiresAuth: true,
1645
1665
  requiresPermission: "agent-controller:execute",
1646
- handler: async ({ mastra, controllerId, resourceId, sessionScope, category, policy, requestContext }) => {
1666
+ handler: async ({ mastra, controllerId, sessionId, category, policy, requestContext }) => {
1647
1667
  try {
1648
- await (await getSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, { scope: sessionScope }, requestContext)).permissions.setForCategory({
1668
+ await (await getSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext)).permissions.setForCategory({
1649
1669
  category,
1650
1670
  policy
1651
1671
  });
@@ -1657,10 +1677,10 @@ const SET_AGENT_CONTROLLER_CATEGORY_PERMISSION_ROUTE = createRoute({
1657
1677
  });
1658
1678
  const SET_AGENT_CONTROLLER_TOOL_PERMISSION_ROUTE = createRoute({
1659
1679
  method: "PUT",
1660
- path: "/agent-controller/:controllerId/sessions/:resourceId/permissions/tool",
1680
+ path: "/agent-controller/:controllerId/sessions/:sessionId/permissions/tool",
1681
+ queryParamSchema: sessionQuerySchema,
1661
1682
  responseType: "json",
1662
1683
  pathParamSchema: sessionPathParams,
1663
- queryParamSchema: sessionScopeQuerySchema,
1664
1684
  bodySchema: setToolPermissionBodySchema,
1665
1685
  responseSchema: ackResponseSchema,
1666
1686
  summary: "Set permission for a specific tool",
@@ -1668,9 +1688,9 @@ const SET_AGENT_CONTROLLER_TOOL_PERMISSION_ROUTE = createRoute({
1668
1688
  tags: ["AgentController", "Permissions"],
1669
1689
  requiresAuth: true,
1670
1690
  requiresPermission: "agent-controller:execute",
1671
- handler: async ({ mastra, controllerId, resourceId, sessionScope, toolName, policy, requestContext }) => {
1691
+ handler: async ({ mastra, controllerId, sessionId, toolName, policy, requestContext }) => {
1672
1692
  try {
1673
- await (await getSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, { scope: sessionScope }, requestContext)).permissions.setForTool({
1693
+ await (await getSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext)).permissions.setForTool({
1674
1694
  toolName,
1675
1695
  policy
1676
1696
  });
@@ -1682,10 +1702,10 @@ const SET_AGENT_CONTROLLER_TOOL_PERMISSION_ROUTE = createRoute({
1682
1702
  });
1683
1703
  const SET_AGENT_CONTROLLER_SESSION_STATE_ROUTE = createRoute({
1684
1704
  method: "PUT",
1685
- path: "/agent-controller/:controllerId/sessions/:resourceId/state",
1705
+ path: "/agent-controller/:controllerId/sessions/:sessionId/state",
1706
+ queryParamSchema: sessionQuerySchema,
1686
1707
  responseType: "json",
1687
1708
  pathParamSchema: sessionPathParams,
1688
- queryParamSchema: sessionScopeQuerySchema,
1689
1709
  bodySchema: z.object({ state: z.record(z.string(), z.unknown()) }),
1690
1710
  responseSchema: ackResponseSchema,
1691
1711
  summary: "Set session state",
@@ -1693,9 +1713,9 @@ const SET_AGENT_CONTROLLER_SESSION_STATE_ROUTE = createRoute({
1693
1713
  tags: ["AgentController"],
1694
1714
  requiresAuth: true,
1695
1715
  requiresPermission: "agent-controller:execute",
1696
- handler: async ({ mastra, controllerId, resourceId, sessionScope, state, requestContext }) => {
1716
+ handler: async ({ mastra, controllerId, sessionId, state, requestContext }) => {
1697
1717
  try {
1698
- await (await getSession(getAgentControllerOrThrow(mastra, controllerId), resourceId, { scope: sessionScope }, requestContext)).state.set(state);
1718
+ await (await getSession(getAgentControllerOrThrow(mastra, controllerId), sessionId, requestContext)).state.set(state);
1699
1719
  return { ok: true };
1700
1720
  } catch (error) {
1701
1721
  return handleError(error, "error setting controller session state");