fix: Disable all shared reminders for subagents (#1073)

Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
Devansh Jain
2026-02-20 16:24:36 -08:00
committed by GitHub
parent 1e024c34f9
commit 6efcbd806f
5 changed files with 61 additions and 5 deletions

View File

@@ -1343,7 +1343,7 @@ ${SYSTEM_REMINDER_CLOSE}
const lastRunAt = (agent as { last_run_completion?: string })
.last_run_completion;
const { parts: sharedReminderParts } = await buildSharedReminderParts({
mode: "headless-one-shot",
mode: isSubagent ? "subagent" : "headless-one-shot",
agent: {
id: agent.id,
name: agent.name,
@@ -2256,6 +2256,7 @@ async function runBidirectionalMode(
let currentAbortController: AbortController | null = null;
const reminderContextTracker = createContextTracker();
const sharedReminderState = createSharedReminderState();
const isSubagent = process.env.LETTA_CODE_AGENT_ROLE === "subagent";
// Resolve pending approvals for this conversation before retrying user input.
const resolveAllPendingApprovals = async () => {
@@ -2793,7 +2794,7 @@ async function runBidirectionalMode(
const lastRunAt = (agent as { last_run_completion?: string })
.last_run_completion;
const { parts: sharedReminderParts } = await buildSharedReminderParts({
mode: "headless-bidirectional",
mode: isSubagent ? "subagent" : "headless-bidirectional",
agent: {
id: agent.id,
name: agent.name,

View File

@@ -1,7 +1,8 @@
export type SharedReminderMode =
| "interactive"
| "headless-one-shot"
| "headless-bidirectional";
| "headless-bidirectional"
| "subagent";
export type SharedReminderId =
| "session-context"

View File

@@ -9,7 +9,7 @@ describe("headless shared reminder wiring", () => {
);
const source = readFileSync(headlessPath, "utf-8");
expect(source).toContain('mode: "headless-one-shot"');
expect(source).toContain('isSubagent ? "subagent" : "headless-one-shot"');
expect(source).toContain(
"sessionContextReminderEnabled: systemInfoReminderEnabled",
);
@@ -21,7 +21,9 @@ describe("headless shared reminder wiring", () => {
);
const source = readFileSync(headlessPath, "utf-8");
expect(source).toContain('mode: "headless-bidirectional"');
expect(source).toContain(
'isSubagent ? "subagent" : "headless-bidirectional"',
);
expect(source).toContain("resolvePlanModeReminder: async () => {");
expect(source).toContain("const { PLAN_MODE_REMINDER } = await import");
});
@@ -36,6 +38,21 @@ describe("headless shared reminder wiring", () => {
expect(source).toContain("reminderContextTracker");
});
test("subagent mode is wired via LETTA_CODE_AGENT_ROLE check", () => {
const headlessPath = fileURLToPath(
new URL("../../headless.ts", import.meta.url),
);
const source = readFileSync(headlessPath, "utf-8");
expect(source).toContain(
'process.env.LETTA_CODE_AGENT_ROLE === "subagent"',
);
expect(source).toContain('isSubagent ? "subagent" : "headless-one-shot"');
expect(source).toContain(
'isSubagent ? "subagent" : "headless-bidirectional"',
);
});
test("one-shot approval drain uses shared stream processor", () => {
const headlessPath = fileURLToPath(
new URL("../../headless.ts", import.meta.url),

View File

@@ -30,6 +30,13 @@ describe("shared reminder catalog", () => {
}
});
test("subagent mode has no reminders", () => {
const subagentReminders = SHARED_REMINDER_CATALOG.filter((entry) =>
entry.modes.includes("subagent"),
);
expect(subagentReminders).toEqual([]);
});
test("command and toolset reminders are interactive-only", () => {
const commandReminder = SHARED_REMINDER_CATALOG.find(
(entry) => entry.id === "command-io",

View File

@@ -88,4 +88,34 @@ describe("shared reminder parity", () => {
reminderIdsForMode("headless-bidirectional"),
);
});
test("subagent mode produces no reminders", async () => {
for (const reminderId of SHARED_REMINDER_IDS) {
providerMap[reminderId] = async () => reminderId;
}
const reflectionSettings: ReflectionSettings = {
trigger: "off",
behavior: "reminder",
stepCount: 25,
};
const subagent = await buildSharedReminderParts({
agent: {
id: "agent-1",
name: "Agent 1",
description: "test",
lastRunAt: null,
},
sessionContextReminderEnabled: true,
reflectionSettings,
skillSources: [] as SkillSource[],
resolvePlanModeReminder: () => "plan",
mode: "subagent",
state: createSharedReminderState(),
});
expect(subagent.appliedReminderIds).toEqual([]);
expect(subagent.parts).toEqual([]);
});
});