PAIPAI

composeLifecycle()

Combine run hooks. Optional context compaction.

Lifecycle hooks prepare executions and model requests, select durable context, and coordinate history rewrites. Compose small parts when an agent needs several policies. For example, context compaction uses resolveModelContext and prepareHistoryRewrite.

import { composeLifecycle, createContextCompaction } from "@pai/core";

defineAgent({
  lifecycle: composeLifecycle(
    createContextCompaction({
      threshold: { maxMessages: 40 },
      retain: { maxMessages: 6 },
      summarize: async ({ messages }) =>
        `Earlier turns: ${messages.length} messages.`,
    }),
  ),
});

Import

import { composeLifecycle, createContextCompaction } from "@pai/core";

Signature

function composeLifecycle(
  ...parts: AgentLifecycle[]
): AgentLifecycle;

Parameters

parts: AgentLifecycle[]

Hook objects with optional prepareRun, prepareModelStep, resolveModelContext, and prepareHistoryRewrite callbacks.

Returns

A AgentLifecycle.

Pass as defineAgent({ lifecycle }).

Lifecycle methods

MethodResponsibility
prepareRunPrepare each claimed or resumed execution episode, including owner-fenced run/thread metadata and run defaults.
prepareModelStepPrepare a model request before SDK parsing, or deliberately respond/block before the provider call.
resolveModelContextSelect anchored durable history, including stored compaction summaries, for the next model request.
prepareHistoryRewritePrepare metadata changes that commit atomically with regeneration or visibility changes.

composeLifecycle combines these methods and merges metadata schemas declared by reusable middleware. The runtime owns its model-step loop, checkpoints, tool execution, cancellation, and suspend/resume handling.

Earlier turns' reasoning

Each model request carries every turn's reasoning as it was stored, the way the AI SDK sends a conversation. What earlier turns' reasoning does is the provider's decision: Anthropic's current models keep it in context, and Claude's prompt cache only reads a history sent back as it was. To drop it anyway, return pruned messages from prepareModelStep. Prune only the turns before the latest user message: a model calling tools needs the current turn's reasoning, which the SDK's reasoning: "before-last-message" would remove. pruneMessages drops reasoning text and keeps reasoning files.

import { defineAgent } from "@pai/core";
import { pruneMessages } from "ai";

export const assistantAgent = defineAgent({
  // name, model, instructions, tools…
  lifecycle: {
    prepareModelStep: ({ input }) => {
      const turnStart = input.messages
        .map((message) => message.role)
        .lastIndexOf("user");
      if (turnStart <= 0) return { action: "continue" };
      return {
        action: "continue",
        patch: {
          messages: [
            ...pruneMessages({
              messages: input.messages.slice(0, turnStart),
              reasoning: "all",
            }),
            ...input.messages.slice(turnStart),
          ],
        },
      };
    },
  },
});

createContextCompaction()

Built-in compaction: when the transcript grows past a threshold, retain a tail of messages for the next model step.

function createContextCompaction(options: {
  summarize: (input) => string | Promise<string>;
  threshold?: { maxMessages?: number; maxEstimatedTokens?: number };
  retain?: { maxMessages?: number; maxEstimatedTokens?: number };
  estimateTokens?: (messages) => number;
}): AgentLifecycle;

options: ContextCompactionOptions

summarize: (input) => string | Promise<string>

Summary text for the compacted prefix. Required.

threshold?: { maxMessages?: number; maxEstimatedTokens?: number }

At least one key is required.

Defaults to { maxMessages: 40 }.

maxMessages?: number

maxEstimatedTokens?: number

retain?: { maxMessages?: number; maxEstimatedTokens?: number }

How much recent history to keep.

Defaults to { maxMessages: 6 }.

maxMessages?: number

maxEstimatedTokens?: number

estimateTokens?: (messages) => number

Count tokens for threshold / retain. Messages only.

Learn more

On this page