agentskit.js
Recipes

Token budget compiler

Declare a token budget, let AgentsKit trim messages and summarize history to fit.

Context windows are finite. Long chats, tool-heavy runs, and big system prompts blow past the limit; the usual response is a random slice of the last N messages and a prayer. compileBudget replaces the prayer with a declared budget and three well-defined trimming strategies.

Install

Built into @agentskit/core — nothing extra to install.

Quick start

import { compileBudget } from '@agentskit/core'

const compiled = await compileBudget({
  budget: 16_000,
  reserveForOutput: 1_000,
  systemPrompt: 'You are a helpful assistant.',
  messages: history,
  tools: availableTools,
})

if (!compiled.fits) {
  console.warn('Still over budget:', compiled.tokens)
}

// Pass compiled.messages + compiled.systemPrompt to your adapter.

Strategies

StrategyBehaviorGood for
drop-oldest (default)Remove oldest turns until it fitsPlain chat, no memory of early turns needed
sliding-windowKeep only the most recent N turnsAgents that care about recency, not history
summarizeDrop oldest, then fold them into a single summary messageLong-running agents that need some memory of the past
await compileBudget({
  budget: 8_000,
  messages,
  strategy: 'summarize',
  summarizer: async dropped => ({
    id: 'summary',
    role: 'system',
    content: `Summary of ${dropped.length} earlier turns: ...`,
    status: 'complete',
    createdAt: new Date(),
  }),
})

Token counter

Defaults to a zero-dependency approximate counter (chars / 4). Swap in a real tokenizer — tiktoken, provider-specific, your own — via the counter option:

import type { TokenCounter } from '@agentskit/core'

const tiktokenCounter: TokenCounter = {
  name: 'tiktoken',
  async count(messages) { /* ... */ },
}

await compileBudget({ budget: 10_000, messages, counter: tiktokenCounter })

Result shape

{
  messages: Message[],        // trimmed (or augmented with summary)
  systemPrompt?: string,      // unchanged
  tokens: {
    system: number,
    messages: number,
    tools: number,
    total: number,
    budget: number,           // budget - reserveForOutput
  },
  dropped: Message[],
  fits: boolean,
  strategy: 'drop-oldest' | 'sliding-window' | 'summarize',
}

keepRecent protects the last N turns even if the budget can't accommodate them — fits: false signals that case so you can alert rather than silently truncate.

See also

✎ Edit this page on GitHub·Found a problem? Open an issue →·How to contribute →

On this page