What happened
After auto-compaction, opencode-mem's session.compacted handler injects the restored memory context via:
// dist/index.js, session.compacted handler
await ctx.client.session.prompt({
path: { id: sessionID },
body: {
parts: [{ id: `prt-compaction-${Date.now()}`, type: "text", text: memoryContext }],
noReply: true,
},
});
This call never sets agent in body, even though SessionPromptData.body (from @opencode-ai/sdk) has an optional agent?: string field. When it's omitted, OpenCode's server defaults the resulting message to a stock fallback agent (observed as general-purpose) instead of inheriting the session's actual current agent.
Impact
Any orchestrated session running a custom primary agent (e.g. a superpowers-style orchestrator, or any custom agent with mode: "primary") permanently loses its agent identity the moment auto-compaction fires — the session silently and irreversibly downgrades to general-purpose for the rest of its life. This happened consistently (checked 4/4 affected sessions in our history) immediately after every session.compacted event that had memories to restore.
This is easy to miss because nothing errors — the session just quietly starts behaving as a different, less-specialized agent (wrong system prompt, wrong tool permissions, no delegation discipline if the original agent was an orchestrator) with no visible warning.
Suggested fix
Before injecting the compaction memory, resolve the session's current agent (e.g. via ctx.client.session.messages({ path: { id: sessionID } }), taking the most recent non-compaction assistant message's agent/mode field) and pass it through explicitly:
const priorMessages = await ctx.client.session.messages({ path: { id: sessionID } });
const lastAssistant = [...priorMessages].reverse().find(
(m) => m?.info?.role === "assistant" && m.info.mode !== "compaction"
);
const currentAgent = lastAssistant?.info?.agent ?? lastAssistant?.info?.mode;
await ctx.client.session.prompt({
path: { id: sessionID },
body: {
parts: [{ id: `prt-compaction-${Date.now()}`, type: "text", text: memoryContext }],
noReply: true,
...(currentAgent ? { agent: currentAgent } : {}),
},
});
I've applied this exact patch locally (against the cached dist/index.js) and it resolves the issue for our setup — happy to open a PR with it if useful, though I wasn't 100% sure of the precise shape of the message-list response in the currently published SDK version, so please double-check the info.agent/info.mode field access against the real payload.
Environment
What happened
After auto-compaction,
opencode-mem'ssession.compactedhandler injects the restored memory context via:This call never sets
agentinbody, even thoughSessionPromptData.body(from@opencode-ai/sdk) has an optionalagent?: stringfield. When it's omitted, OpenCode's server defaults the resulting message to a stock fallback agent (observed asgeneral-purpose) instead of inheriting the session's actual current agent.Impact
Any orchestrated session running a custom primary agent (e.g. a
superpowers-style orchestrator, or any custom agent withmode: "primary") permanently loses its agent identity the moment auto-compaction fires — the session silently and irreversibly downgrades togeneral-purposefor the rest of its life. This happened consistently (checked 4/4 affected sessions in our history) immediately after everysession.compactedevent that had memories to restore.This is easy to miss because nothing errors — the session just quietly starts behaving as a different, less-specialized agent (wrong system prompt, wrong tool permissions, no delegation discipline if the original agent was an orchestrator) with no visible warning.
Suggested fix
Before injecting the compaction memory, resolve the session's current agent (e.g. via
ctx.client.session.messages({ path: { id: sessionID } }), taking the most recent non-compaction assistant message'sagent/modefield) and pass it through explicitly:I've applied this exact patch locally (against the cached
dist/index.js) and it resolves the issue for our setup — happy to open a PR with it if useful, though I wasn't 100% sure of the precise shape of the message-list response in the currently published SDK version, so please double-check theinfo.agent/info.modefield access against the real payload.Environment