Compaction
Pluggable transcript compaction — MessageCompactor, monologue swap, and agent.monologue.compacted.
Compaction reduces monologue transcript size before LLM inference. When compaction changes the message list, the processor swaps to a fresh monologue conversation and repoints the forum participant stint.
Interface
import type { InferenceMessage, MessageCompactor } from "@yoke/sdk";
const compaction: MessageCompactor = async (messages: InferenceMessage[]) => {
if (messages.length <= 20) return messages;
return messages.slice(-10);
};
const agentStack = defineAgentStack({ compaction });
defineProcessorActor({
configSchema: processorConfigSchema,
stateSchema: processorStateSchema,
compaction: agentStack.compaction,
});MessageCompactor receives and returns InferenceMessage[] — the same shape as ctx.llm.infer input.
Preserve body.meta (especially sourceActorId) on user messages so hydration can reuse external shadow actors ingestion created.
Flow
monologue message posted
│
▼
processor reads transcript → InferenceMessage[]
│
▼
compaction(messages) [optional]
│
├─ unchanged ──► ctx.llm.infer(messages)
│
└─ changed ──► create new monologue
hydrate with compacted messages
update forum participant.metadata.monologueId
emit agent.monologue.compacted (egress updates routing)
ctx.llm.infer(compacted)
│
▼
post type: "reply" to active monologueStorage updates on swap
| Location | What changes |
|---|---|
participants.metadata.monologueId | Forum stint repointed to new monologue |
Processor ctx.state | monologueId, agentParticipantId |
| Ingestion | Resolves monologue from participant metadata; resets external-actor cache |
Egress ctx.state.joins | Updated via agent.monologue.compacted event |
Canonical monologue id lives in Postgres participants.metadata.monologueId — one monologue per forum stint.
Helpers
| Export | Purpose |
|---|---|
defineAgentStack | Typed holder for compaction and tools |
inferenceMessagesEqual | Compare before/after compaction |
swapMonologueAfterCompaction | Create monologue, hydrate, update participant |
hydrateMonologueWithMessages | Post compacted inference messages |
collectExternalActors | Gather shadow actors before swap |
resolveMonologueStint | Read active monologue from forum participant metadata |
Example compactor
Example compactor in your package:
const agentStack = defineAgentStack({
compaction: async (messages) => {
if (messages.length <= 15) return messages;
// Keep system context + recent tail
return [messages[0], ...messages.slice(-8)];
},
});When to compact
| Scenario | Strategy |
|---|---|
| Context window pressure | Truncate/summarize old turns |
| Long support threads | Keep last N messages + summary line |
| Tool-heavy sessions | Drop intermediate tool rounds, keep finals |
Compaction runs before each infer call when configured. If the compactor returns an identical list (inferenceMessagesEqual), no swap occurs.
Events
| Event | When |
|---|---|
agent.monologue.compacted | After swap — egress updates forumId → monologueId routing |