高级 API 用法

Context Compaction

当对话增长到数千 token 以上时,每次后续调用都会重新发送所有先前的 message,并为它们支付 input token 费用。Context Compaction可以将这些 message 压缩成一个 opaque item,在删除冗长 Tool Output 和往返内容的同时,保留关键状态,包括 system prompt、附件、先前推理和压缩后的轮次记录。

随后将该 compaction item 原样传入下一次请求,模型就会像完整历史仍然存在一样继续对话。

  • 降低 input 成本 — 下一次调用只需为压缩后的 context 付费,而不是原始 message。

  • 降低延迟 — Payload 更小,time-to-first-token 更快。

  • 响应更聚焦 — 更紧凑的 context 让模型专注于当前任务,避免被过时的 Tool Output 和旧轮次干扰。

  • 支持更长对话 — 让持续数小时的 Agent Loop 保持在模型 context window 以内。

何时执行 Compaction

满足以下全部条件时执行 Compaction:

  • 对话已足够长,每次调用的 input_tokens 已对成本或延迟产生影响。

  • 你仍希望模型记住先前轮次(否则直接开始新对话即可)。

  • 当前 window 仍在模型 context limit 内(Compaction 可以缩短对话,但无法挽救已经超出限制的请求)。

一种典型模式是在 Agent Loop 中每 N 轮调用一次 Compaction API,或者在记录显示渲染后的 context 超过为当前 workload 设定的 threshold 时调用。

Compaction API

发送要压缩的对话。Response 包含一个代表完整先前对话的 compaction item;你可以安全地从 Client-side State 中删除原始 message,将 compaction item 作为下一次请求的开头,并在其后追加新的 user turn。

# Step 1 — compact the long conversation
curl -s https://api.x.ai/v1/responses/compact \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $XAI_API_KEY" \
  -d '{
    "model": "grok-4.5",
    "input": [
      {"role": "system", "content": "You are a concise and knowledgeable science tutor."},
      {"role": "user", "content": "What is the Higgs boson and why is it important?"},
      {"role": "assistant", "content": "The Higgs boson is an elementary particle..."},
      {"role": "user", "content": "How does the Higgs mechanism actually work?"},
      {"role": "assistant", "content": "The Higgs mechanism works through spontaneous symmetry breaking..."}
    ]
  }'

# Step 2 — continue the conversation using the compacted output
curl -s https://api.x.ai/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $XAI_API_KEY" \
  -d '{
    "model": "grok-4.5",
    "input": [
      {
        "type": "compaction",
        "id": "cmp_abc123",
        "encrypted_content": "<paste encrypted_content from step 1>"
      },
      {"role": "user", "content": "Based on our earlier conversation, what gives particles their mass?"}
    ]
  }'

xAI SDK 还提供 AsyncClient,其中的 await client.chat.compact_context(...)await chat.sample() 可在 asyncio 下实现相同流程。

Response 结构

REST Endpoint(POST /v1/responses/compact)返回兼容 OpenAI 的 compaction object:

JSON

{
  "id": "cmp_01HZ9P0V8M2YQK3F7C4G6N5R2A",
  "object": "response.compaction",
  "created_at": 1748895600,
  "model": "grok-4.5",
  "output": [
    {
      "type": "compaction",
      "id": "cmp_01HZ9P0V8M2YQK3F7C4G6N5R2A",
      "encrypted_content": "<opaque blob>"
    }
  ],
  "usage": {
    "input_tokens": 12000,
    "input_tokens_details": { "cached_tokens": 0 },
    "output_tokens": 800,
    "output_tokens_details": { "reasoning_tokens": 240 },
    "total_tokens": 12800,
    "dropped_message_count": 45
  }
}
字段说明
id该 Compaction 的稳定 ID(cmp_<uuid>),也会在内部 compaction item 中返回。
object始终为 "response.compaction" 下实现相同流程。
output包含单个 compaction item 的 array。请将其原样传入下一次请求。
output[].type始终为 "compaction" 下实现相同流程。
output[].encrypted_content包含压缩后对话的 opaque blob。
usage.input_tokensCompaction 前对话中的 token 数量。
usage.output_tokens为压缩记录生成的 token 数量。模型在下一次调用中恢复的 blob 大致相当于保留的 system prompt 加上这些 token。
usage.dropped_message_count被纳入 Compaction 的 input message 数量。

xAI SDK 中的 In-place Compaction

对于长时间运行的 Agent Loop,xAI SDK 在 live Chat object 上提供便捷 method:chat.compact()会对 Chat 当前的 message 执行 Compaction,并用 compaction item 替换原 message。之后仍可像以前一样继续调用 chat.sample(),Server 会在下一次请求时恢复压缩后的 prefix。

Python

import os
from xai_sdk import Client
from xai_sdk.chat import system, user

client = Client(api_key=os.environ["XAI_API_KEY"])

# use_encrypted_content=True preserves the model's reasoning content across
# turns, recommended when using reasoning models.
chat = client.chat.create(model="grok-4.5", use_encrypted_content=True)
chat.append(system("You are a helpful assistant. Keep answers brief."))

compact_every = 5
for turn in range(1, 100):
    chat.append(user(input("You: ")))
    response = chat.sample()
    print(f"Grok: {response.content}")
    chat.append(response)

    if turn % compact_every == 0:
        before = len(chat.messages)
        compact = chat.compact()
        print(
            f"[compacted {before}{len(chat.messages)} messages | "
            f"dropped {compact.dropped_message_count} | "
            f"tokens used: {compact.usage.total_tokens}]"
        )

同一 method 也可用于 AsyncClient视为await chat.compact() 下实现相同流程。

限制与注意事项

  • 要压缩的对话必须已经能放入 context。 Compaction 会缩短对话,但无法挽救超出限制的请求。如果对话已经超过 context_length_exceeded,需要先裁剪或拆分,再调用 compact。

  • 每次调用最多执行一次 Compaction。该 endpoint 每个请求只执行一次 Compaction。

  • encrypted_content 是 opaque 的。不要解析、编辑或手动合并多个 blob。始终将完整的 output array(或 CompactContextResponse)原样传回。

  • 可以再次执行 Compaction。可以稍后再次压缩已经压缩过的对话,例如在上一次 Compaction之后对话再次变长时。

  • Compaction 调用的 token 用量。Compaction 本身会使用 token(可在 usage.input_tokens / usage.output_tokens 中查看)。如果频繁执行 Compaction,请选择更小、更快的模型。