Lewati halaman ini kecuali Anda mengirim "thinking blocks" (blok pemikiran) kembali ke model dengan "preserved thinking" (pemikiran yang dipertahankan) dan mempertahankan giliran setelah blok "compaction" (pemadatan). "Kept turns" (giliran yang dipertahankan) adalah giliran yang mengikuti blok tersebut: giliran terbaru yang Anda keluarkan dari permintaan compaction, seperti dalam Compaction yang mempertahankan giliran terbaru, atau giliran yang tiba saat ringkasan sedang ditulis, seperti dalam Compaction di latar belakang.
Model dengan pemikiran yang dipertahankan memeriksa blok thinking sebelumnya terhadap percakapan yang menghasilkannya. Ringkasan menggantikan sebagian percakapan tersebut, tetapi pemeriksaan menerima pertukaran itu ketika API yang menulis ringkasannya, sehingga thinking dalam giliran yang dipertahankan dapat tetap valid.
Syarat agar thinking yang dipertahankan tetap valid
Blok thinking dalam giliran yang dipertahankan tetap valid selama semua hal berikut terpenuhi:
- Permintaan compaction berjalan pada model dengan pemikiran yang dipertahankan. Syarat ini mencakup setiap permintaan compaction sejak blok thinking dihasilkan, bukan hanya yang terbaru. Salah satu cara untuk memenuhinya adalah mengirim setiap permintaan compaction ke model yang digunakan oleh percakapan.
- Giliran yang dipertahankan langsung mengikuti pesan yang diringkas, dan Anda mengirimnya tanpa perubahan. Kirim setiap pesan yang dipertahankan persis seperti yang ada dalam riwayat Anda. Jangan melewatkan atau menambahkan pesan di antara pesan terakhir yang diringkas dan pesan pertama yang dipertahankan. Pesan pertama yang dipertahankan juga harus memiliki peran yang berbeda dari pesan terakhir yang diringkas, dan tidak boleh berupa pesan
role: "system"di tengah percakapan. Jika tidak, API akan menggabungkannya ke dalam pesan terakhir yang diringkas. Salah satu cara untuk mendapatkan pesan pertama yang dipertahankan dengan benar adalah melakukan compaction tepat padamessagesdari permintaan yang sudah Anda kirim. Giliran yang dipertahankan kemudian dimulai dengan balasan Haijun terhadap permintaan tersebut.
systemdantoolsyang tidak ditandaidefer_loading: truetidak berubah. Keduanya sama pada permintaan compaction seperti pada permintaan yang menghasilkan thinking yang dipertahankan, dan tetap sama pada permintaan-permintaan berikutnya. Mengubah prompt sistem atau alat menjelaskan cara mengubahnya dengan aman.
Jika suatu syarat tidak terpenuhi, tidak ada yang gagal saat Anda melakukan compaction, dan API tetap menerima blok tersebut pada permintaan berikutnya. Kegagalan muncul pada permintaan berikutnya yang pertama kali mengirim thinking yang dipertahankan di tempat API memberlakukan pemeriksaan: error 400 secara default, atau blok thinking dibuang jika permintaan menetapkan thinking.block_binding.prefix_mismatch_behavior ke "drop_block". Di Message Batches API, item yang tidak menetapkan field tersebut tidak gagal. Di tempat pemeriksaan berlaku secara default, API justru membuang blok tersebut. Apa yang dilakukan API dengan blok yang tidak valid menjelaskan kedua hasil tersebut, dan Kapan API memberlakukan pemeriksaan menyebutkan permintaan mana yang diperiksa.
Melakukan compaction lagi tanpa merusak thinking yang lebih lama
Anda dapat melakukan compaction lagi dan mempertahankan giliran: blok baru mencakup ringkasan lama dan setiap pesan yang mengikutinya dalam permintaan compaction, dan setiap giliran yang Anda keluarkan dari permintaan tersebut menjadi giliran yang dipertahankan dari blok baru.
Syarat pertama dari syarat untuk thinking yang dipertahankan memperhitungkan setiap compaction sejak blok thinking dihasilkan, sehingga giliran yang Anda pertahankan melalui dua compaction mengharuskan keduanya telah berjalan pada model dengan pemikiran yang dipertahankan.
Compaction yang terjadi sebelum blok thinking dihasilkan tidak diperhitungkan terhadap blok tersebut. Thinking yang dihasilkan setelah sebuah blok terpasang akan terikat pada blok tersebut, dan tetap valid melalui compaction berikutnya yang memenuhi syarat.
Mengubah prompt sistem atau alat
Permintaan berikutnya dapat menggunakan system yang berbeda, tools yang berbeda, atau model yang berbeda dari permintaan compaction, dan API tetap menerima blok tersebut. Perubahan seperti itu dapat membuat thinking dalam giliran yang dipertahankan menjadi tidak valid, tetapi tidak memiliki efek lain.
Untuk mengubah system atau tools tanpa membuat thinking yang dipertahankan menjadi tidak valid, lakukan compaction pada seluruh percakapan terlebih dahulu, sehingga tidak ada giliran yang dipertahankan. Kemudian ubah keduanya pada permintaan berikutnya.
Untuk menambahkan instruksi atau mengubah alat yang tersedia tanpa menyentuh system atau tools, tambahkan perubahan tersebut ke messages, seperti yang dijelaskan dalam Melakukan perubahan tanpa mengedit prefiks.
Pesan sistem di tengah percakapan yang berada di dalam giliran yang diringkas juga ikut diringkas, sehingga instruksi teks di dalamnya berhenti berlaku setelah pertukaran. Agar salah satunya tetap berlaku, nyatakan kembali dalam pesan role: "system" tepat setelah giliran user baru pertama yang mengikuti giliran yang dipertahankan. Perubahan alat di dalam giliran tersebut terbawa dengan sendirinya ketika permintaan compaction juga membawa inline-tools-2026-09-15: blok yang dikembalikan mencatat efek bersihnya dalam field tool_changes, jadi kirim kembali blok tersebut tanpa modifikasi. Jika blok tidak memiliki field tool_changes, nyatakan kembali perubahan alat tersebut dengan cara yang sama. Pesan sistem yang ditempatkan di antara blok dan giliran yang dipertahankan akan merusak thinking di dalam giliran tersebut.
Memeriksa bahwa thinking yang dipertahankan tetap valid
Respons compaction tidak menyatakan apakah thinking yang dipertahankan tetap valid. Permintaan pertama setelah pertukaranlah yang menyatakannya. Untuk memeriksanya dalam pengujian Anda:
- Lakukan percakapan singkat dengan thinking diaktifkan. Gunakan model tempat API menjalankan pemeriksaan (lihat Kapan API memberlakukan pemeriksaan), dan gunakan model tersebut untuk setiap langkah, karena model yang tidak dapat membaca blok thinking akan membuangnya tanpa error.
- Lakukan compaction pada giliran yang lebih lama, dan pertahankan setidaknya satu giliran yang berisi blok thinking.
- Kirim permintaan berikutnya, dengan blok terlebih dahulu, lalu giliran yang dipertahankan, lalu pesan
userbaru, dan denganthinking.block_binding.prefix_mismatch_behaviorditetapkan ke"error".
- Baca hasilnya. Respons 200 yang array
input_transformations-nya kosong berarti tidak ada blok thinking yang gagal dalam pemeriksaan atau dibuang. Error 400 yang menyatakan bahwa blok terikat pada percakapan yang berbeda berarti ada yang gagal. Pesan tersebut dimulai dengan path dari blok pertama yang gagal, dan Apa yang dilakukan API dengan blok yang tidak valid menampilkannya secara lengkap.
Field prefix_mismatch_behavior memerlukan header beta thinking-binding-controls-2026-08-01 selain header beta compact-2026-09-04. Menetapkan field tersebut juga mengikutsertakan permintaan ke dalam pemeriksaan pada akun yang pemeriksaannya tidak aktif secara default.
Program berikut menjalankan keempat langkah tersebut. Program ini mencetak berapa banyak blok thinking yang ada dalam giliran yang dipertahankan dan berapa banyak entri yang dimiliki input_transformations; tidak adanya entri berarti thinking yang dipertahankan tetap valid:
from juglow.types.beta import BetaMessageParam, BetaThinkingConfigParam
client = juglow.Juglow()
# Haijun Fable 5.1 adalah model pertama yang memeriksa thinking yang dikirim balik terhadap percakapan.
MODEL = "haijun-fable-5-1"
BETAS = ["compact-2026-09-04", "thinking-binding-controls-2026-08-01"]
SYSTEM = "You help plan a recipe app's release. Keep answers short."
# Dengan "error", blok thinking yang gagal pemeriksaan membuat permintaan gagal dengan kode 400.
THINKING: BetaThinkingConfigParam = {
"type": "adaptive",
"block_binding": {"prefix_mismatch_behavior": "error"},
}
# 1. Lakukan percakapan singkat dengan thinking aktif.
history: list[BetaMessageParam] = [
{"role": "user", "content": "What are the main entities in the app's data model?"}
]
first = client.beta.messages.create(
model=MODEL,
max_tokens=8192,
system=SYSTEM,
betas=BETAS,
thinking=THINKING,
messages=history,
)
history += [
{"role": "assistant", "content": first.content},
{
"role": "user",
"content": "Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?",
},
]
second = client.beta.messages.create(
model=MODEL,
max_tokens=8192,
system=SYSTEM,
betas=BETAS,
thinking=THINKING,
messages=history,
)
history.append({"role": "assistant", "content": second.content})
thinking_blocks = sum(block.type == "thinking" for block in second.content)
print(f"Thinking blocks in the kept turn: {thinking_blocks}")
# 2. Ringkas giliran pertama. Giliran kedua tidak disertakan dalam permintaan.
summary = client.beta.messages.create(
model=MODEL,
max_tokens=4096,
system=SYSTEM,
betas=BETAS,
thinking=THINKING,
messages=history[:2],
compaction={"type": "summarize"},
)
if summary.stop_reason != "compaction":
raise SystemExit(f"No summary: {summary.stop_reason}")
# 3. Letakkan blok di depan giliran yang dipertahankan, lalu ajukan pertanyaan berikutnya.
history = [
{"role": "assistant", "content": summary.content},
*history[2:],
{"role": "user", "content": "Which day should the release go out?"},
]
third = client.beta.messages.create(
model=MODEL,
max_tokens=8192,
system=SYSTEM,
betas=BETAS,
thinking=THINKING,
messages=history,
)
# 4. Respons 200 tanpa blok yang dibuang berarti thinking yang dipertahankan tetap berlaku.
print(f"Dropped thinking blocks: {len(third.input_transformations)}") const client = new Juglow();
// Haijun Fable 5.1 adalah model pertama yang memeriksa thinking yang dikirim balik terhadap percakapan.
const model: Juglow.Model = "haijun-fable-5-1";
const betas: Juglow.Beta.JuglowBeta[] = [
"compact-2026-09-04",
"thinking-binding-controls-2026-08-01"
];
const systemPrompt = "You help plan a recipe app's release. Keep answers short.";
// Dengan "error", blok thinking yang gagal dalam pemeriksaan membuat permintaan gagal dengan kode 400.
const thinking: Juglow.Beta.Messages.BetaThinkingConfigParam = {
type: "adaptive",
block_binding: { prefix_mismatch_behavior: "error" }
};
// 1. Lakukan percakapan singkat dengan thinking aktif.
let history: Juglow.Beta.Messages.BetaMessageParam[] = [
{ role: "user", content: "What are the main entities in the app's data model?" }
];
const first = await client.beta.messages.create({
model,
max_tokens: 8192,
system: systemPrompt,
betas,
thinking,
messages: history
});
history.push(
{ role: "assistant", content: first.content },
{
role: "user",
content:
"Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?"
}
);
const second = await client.beta.messages.create({
model,
max_tokens: 8192,
system: systemPrompt,
betas,
thinking,
messages: history
});
history.push({ role: "assistant", content: second.content });
const thinkingBlocks = second.content.filter((block) => block.type === "thinking").length;
console.log(`Thinking blocks in the kept turn: ${thinkingBlocks}`);
// 2. Ringkas giliran pertama. Giliran kedua tidak disertakan dalam permintaan.
const summary = await client.beta.messages.create({
model,
max_tokens: 4096,
system: systemPrompt,
betas,
thinking,
messages: history.slice(0, 2),
compaction: { type: "summarize" }
});
if (summary.stop_reason !== "compaction") {
throw new Error(`No summary: ${summary.stop_reason}`);
}
// 3. Letakkan blok di depan giliran yang dipertahankan, lalu ajukan pertanyaan berikutnya.
history = [
{ role: "assistant", content: summary.content },
...history.slice(2),
{ role: "user", content: "Which day should the release go out?" }
];
const third = await client.beta.messages.create({
model,
max_tokens: 8192,
system: systemPrompt,
betas,
thinking,
messages: history
});
// 4. Respons 200 tanpa blok yang dibuang berarti thinking yang dipertahankan tetap valid.
console.log(`Dropped thinking blocks: ${third.input_transformations?.length ?? 0}`); using Juglow.Models.Beta;
using Juglow.Models.Beta.Messages;
using Model = Juglow.Models.Messages.Model;
JuglowClient client = new();
// Haijun Fable 5.1 adalah model pertama yang memeriksa thinking yang dikirim kembali terhadap percakapan.
const Model ModelId = Model.HaijunFable5_1;
JuglowBeta[] betas = [JuglowBeta.Compact2026_09_04, JuglowBeta.ThinkingBindingControls2026_08_01];
const string SystemPrompt = "You help plan a recipe app's release. Keep answers short.";
// Dengan "error", blok thinking yang gagal dalam pemeriksaan membuat permintaan gagal dengan kode 400.
BetaThinkingConfigAdaptive thinking = new()
{
BlockBinding = new() { PrefixMismatchBehavior = BetaThinkingPrefixMismatchBehavior.Error },
};
// 1. Lakukan percakapan singkat dengan thinking diaktifkan.
List<BetaMessageParam> history =
[
new() { Role = Role.User, Content = "What are the main entities in the app's data model?" },
];
var first = await client.Beta.Messages.Create(new MessageCreateParams
{
Model = ModelId,
MaxTokens = 8192,
System = SystemPrompt,
Betas = [.. betas],
Thinking = thinking,
Messages = history,
});
history.AddRange(
[
new()
{
Role = Role.Assistant,
Content = first.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList(),
},
new()
{
Role = Role.User,
Content = "Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?",
},
]);
var second = await client.Beta.Messages.Create(new MessageCreateParams
{
Model = ModelId,
MaxTokens = 8192,
System = SystemPrompt,
Betas = [.. betas],
Thinking = thinking,
Messages = history,
});
history.Add(new()
{
Role = Role.Assistant,
Content = second.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList(),
});
var thinkingBlocks = second.Content.Count(block => block.TryPickThinking(out _));
Console.WriteLine($"Thinking blocks in the kept turn: {thinkingBlocks}");
// 2. Ringkas giliran pertama. Giliran kedua tidak disertakan dalam permintaan.
var summary = await client.Beta.Messages.Create(new MessageCreateParams
{
Model = ModelId,
MaxTokens = 4096,
System = SystemPrompt,
Betas = [.. betas],
Thinking = thinking,
Messages = history[..2],
Compaction = new BetaCompactionConfig(), // type defaults to "summarize"
});
if (summary.StopReason != BetaStopReason.Compaction)
{
throw new InvalidOperationException($"No summary: {summary.StopReason?.Raw()}");
}
// 3. Letakkan blok di depan giliran yang dipertahankan, lalu ajukan pertanyaan berikutnya.
history =
[
new()
{
Role = Role.Assistant,
Content = summary.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList(),
},
.. history[2..],
new() { Role = Role.User, Content = "Which day should the release go out?" },
];
var third = await client.Beta.Messages.Create(new MessageCreateParams
{
Model = ModelId,
MaxTokens = 8192,
System = SystemPrompt,
Betas = [.. betas],
Thinking = thinking,
Messages = history,
});
// 4. Respons 200 tanpa blok yang dibuang berarti thinking yang dipertahankan tetap valid.
Console.WriteLine($"Dropped thinking blocks: {third.InputTransformations?.Count ?? 0}"); ctx := context.Background()
client := juglow.NewClient()
// Haijun Fable 5.1 adalah model pertama yang memeriksa thinking yang dikirim balik terhadap percakapan.
const model = juglow.ModelHaijunFable5_1
betas := []juglow.JuglowBeta{
juglow.JuglowBetaCompact2026_09_04,
juglow.JuglowBetaThinkingBindingControls2026_08_01,
}
system := []juglow.BetaTextBlockParam{{Text: "You help plan a recipe app's release. Keep answers short."}}
// Dengan "error", blok thinking yang gagal dalam pemeriksaan membuat permintaan gagal dengan 400.
thinking := juglow.BetaThinkingConfigParamUnion{
OfAdaptive: &juglow.BetaThinkingConfigAdaptiveParam{
BlockBinding: juglow.BetaThinkingBlockBindingParam{
PrefixMismatchBehavior: juglow.BetaThinkingPrefixMismatchBehaviorError,
},
},
}
// 1. Lakukan percakapan singkat dengan thinking aktif.
history := []juglow.BetaMessageParam{
juglow.NewBetaUserMessage(juglow.NewBetaTextBlock("What are the main entities in the app's data model?")),
}
first, err := client.Beta.Messages.New(ctx, juglow.BetaMessageNewParams{
Model: model,
MaxTokens: 8192,
System: system,
Betas: betas,
Thinking: thinking,
Messages: history,
})
if err != nil {
log.Fatal(err)
}
history = append(history,
first.ToParam(),
juglow.NewBetaUserMessage(juglow.NewBetaTextBlock("Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?")),
)
second, err := client.Beta.Messages.New(ctx, juglow.BetaMessageNewParams{
Model: model,
MaxTokens: 8192,
System: system,
Betas: betas,
Thinking: thinking,
Messages: history,
})
if err != nil {
log.Fatal(err)
}
history = append(history, second.ToParam())
thinkingBlocks := 0
for _, block := range second.Content {
if _, ok := block.AsAny().(juglow.BetaThinkingBlock); ok {
thinkingBlocks++
}
}
fmt.Printf("Thinking blocks in the kept turn: %d\n", thinkingBlocks)
// 2. Ringkas giliran pertama. Giliran kedua tidak disertakan dalam permintaan.
summary, err := client.Beta.Messages.New(ctx, juglow.BetaMessageNewParams{
Model: model,
MaxTokens: 4096,
System: system,
Betas: betas,
Thinking: thinking,
Messages: history[:2],
Compaction: juglow.BetaCompactionConfigUnionParam{
OfSummarize: &juglow.BetaSummarizeCompactionParam{},
},
})
if err != nil {
log.Fatal(err)
}
if summary.StopReason != juglow.BetaStopReasonCompaction {
log.Fatalf("No summary: %s", summary.StopReason)
}
// 3. Letakkan blok di depan giliran yang dipertahankan lalu ajukan pertanyaan berikutnya.
history = slices.Concat(
[]juglow.BetaMessageParam{summary.ToParam()},
history[2:],
[]juglow.BetaMessageParam{juglow.NewBetaUserMessage(juglow.NewBetaTextBlock("Which day should the release go out?"))},
)
third, err := client.Beta.Messages.New(ctx, juglow.BetaMessageNewParams{
Model: model,
MaxTokens: 8192,
System: system,
Betas: betas,
Thinking: thinking,
Messages: history,
})
if err != nil {
log.Fatal(err)
}
// 4. Respons 200 tanpa blok yang dibuang berarti thinking yang dipertahankan tetap valid.
fmt.Printf("Dropped thinking blocks: %d\n", len(third.InputTransformations)) import com.juglow.models.beta.JuglowBeta;
import com.juglow.models.beta.messages.BetaCompactionConfig;
import com.juglow.models.beta.messages.BetaContentBlock;
import com.juglow.models.beta.messages.BetaMessageParam;
import com.juglow.models.beta.messages.BetaStopReason;
import com.juglow.models.beta.messages.BetaThinkingBlockBinding;
import com.juglow.models.beta.messages.BetaThinkingConfigAdaptive;
import com.juglow.models.beta.messages.BetaThinkingPrefixMismatchBehavior;
import com.juglow.models.beta.messages.MessageCreateParams;
// Haijun Fable 5.1 adalah model pertama yang memeriksa thinking yang dikirim kembali terhadap percakapan.
static final Model MODEL = Model.HAIJUN_FABLE_5_1;
static final List<JuglowBeta> BETAS = List.of(
JuglowBeta.COMPACT_2026_09_04,
JuglowBeta.THINKING_BINDING_CONTROLS_2026_08_01
);
static final String SYSTEM = "You help plan a recipe app's release. Keep answers short.";
// Dengan "error", blok thinking yang gagal dalam pemeriksaan membuat permintaan gagal dengan kode 400.
static final BetaThinkingConfigAdaptive THINKING = BetaThinkingConfigAdaptive.builder()
.blockBinding(BetaThinkingBlockBinding.builder()
.prefixMismatchBehavior(BetaThinkingPrefixMismatchBehavior.ERROR)
.build())
.build();
void main() {
var client = JuglowOkHttpClient.fromEnv();
// 1. Lakukan percakapan singkat dengan thinking aktif.
var history = new ArrayList<BetaMessageParam>();
history.add(BetaMessageParam.builder()
.role(BetaMessageParam.Role.USER)
.content("What are the main entities in the app's data model?")
.build());
var firstParams = MessageCreateParams.builder()
.model(MODEL)
.maxTokens(8192)
.system(SYSTEM)
.betas(BETAS)
.thinking(THINKING)
.messages(history)
.build();
var first = client.beta().messages().create(firstParams);
history.add(first.toParam());
history.add(BetaMessageParam.builder()
.role(BetaMessageParam.Role.USER)
.content("Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?")
.build());
var secondParams = MessageCreateParams.builder()
.model(MODEL)
.maxTokens(8192)
.system(SYSTEM)
.betas(BETAS)
.thinking(THINKING)
.messages(history)
.build();
var second = client.beta().messages().create(secondParams);
history.add(second.toParam());
long thinkingBlocks = second.content().stream().filter(BetaContentBlock::isThinking).count();
IO.println("Thinking blocks in the kept turn: " + thinkingBlocks);
// 2. Ringkas giliran pertama. Giliran kedua tidak disertakan dalam permintaan.
var firstTurn = history.subList(0, 2);
var summaryParams = MessageCreateParams.builder()
.model(MODEL)
.maxTokens(4096)
.system(SYSTEM)
.betas(BETAS)
.thinking(THINKING)
.messages(firstTurn)
.compaction(BetaCompactionConfig.builder().build()) // type defaults to "summarize"
.build();
var summary = client.beta().messages().create(summaryParams);
if (!summary.stopReason().map(BetaStopReason.COMPACTION::equals).orElse(false)) {
throw new IllegalStateException("No summary: " + summary.stopReason().orElseThrow());
}
// 3. Letakkan blok di depan giliran yang dipertahankan, lalu ajukan pertanyaan berikutnya.
firstTurn.clear();
history.addFirst(summary.toParam());
history.add(BetaMessageParam.builder()
.role(BetaMessageParam.Role.USER)
.content("Which day should the release go out?")
.build());
var thirdParams = MessageCreateParams.builder()
.model(MODEL)
.maxTokens(8192)
.system(SYSTEM)
.betas(BETAS)
.thinking(THINKING)
.messages(history)
.build();
var third = client.beta().messages().create(thirdParams);
// 4. Respons 200 tanpa blok yang dibuang berarti thinking yang dipertahankan tetap valid.
IO.println("Dropped thinking blocks: " + third.inputTransformations().map(List::size).orElse(0));
} use Juglow\Beta\JuglowBeta;
use Juglow\Beta\Messages\BetaCompactionConfig;
use Juglow\Beta\Messages\BetaMessageParam;
use Juglow\Beta\Messages\BetaMessageParam\Role;
use Juglow\Beta\Messages\BetaStopReason;
use Juglow\Beta\Messages\BetaThinkingBlock;
use Juglow\Beta\Messages\BetaThinkingBlockBinding;
use Juglow\Beta\Messages\BetaThinkingConfigAdaptive;
use Juglow\Beta\Messages\BetaThinkingPrefixMismatchBehavior;
$client = new Client();
// Haijun Fable 5.1 adalah model pertama yang memeriksa thinking yang dikirim kembali terhadap percakapan.
const MODEL = Model::HAIJUN_FABLE_5_1;
const BETAS = [JuglowBeta::COMPACT_2026_09_04, JuglowBeta::THINKING_BINDING_CONTROLS_2026_08_01];
const SYSTEM = "You help plan a recipe app's release. Keep answers short.";
// Dengan "error", blok thinking yang gagal dalam pemeriksaan membuat permintaan gagal dengan kode 400.
$thinking = BetaThinkingConfigAdaptive::with(
blockBinding: BetaThinkingBlockBinding::with(
prefixMismatchBehavior: BetaThinkingPrefixMismatchBehavior::ERROR,
),
);
// 1. Lakukan percakapan singkat dengan thinking aktif.
$history = [
BetaMessageParam::with(role: Role::USER, content: "What are the main entities in the app's data model?"),
];
$first = $client->beta->messages->create(
model: MODEL,
maxTokens: 8192,
system: SYSTEM,
betas: BETAS,
thinking: $thinking,
messages: $history,
);
$history[] = BetaMessageParam::with(role: Role::ASSISTANT, content: $first->content);
$history[] = BetaMessageParam::with(
role: Role::USER,
content: 'Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?',
);
$second = $client->beta->messages->create(
model: MODEL,
maxTokens: 8192,
system: SYSTEM,
betas: BETAS,
thinking: $thinking,
messages: $history,
);
$history[] = BetaMessageParam::with(role: Role::ASSISTANT, content: $second->content);
$thinkingBlocks = count(array_filter($second->content, fn ($block) => $block instanceof BetaThinkingBlock));
printf("Thinking blocks in the kept turn: %d\n", $thinkingBlocks);
// 2. Ringkas giliran pertama. Giliran kedua tidak disertakan dalam permintaan.
$summary = $client->beta->messages->create(
model: MODEL,
maxTokens: 4096,
system: SYSTEM,
betas: BETAS,
thinking: $thinking,
messages: array_slice($history, 0, 2),
compaction: new BetaCompactionConfig(), // type defaults to 'summarize'
);
if ($summary->stopReason !== BetaStopReason::COMPACTION->value) {
throw new RuntimeException("No summary: {$summary->stopReason}");
}
// 3. Letakkan blok di depan giliran yang dipertahankan, lalu ajukan pertanyaan berikutnya.
$history = [
BetaMessageParam::with(role: Role::ASSISTANT, content: $summary->content),
...array_slice($history, 2),
BetaMessageParam::with(role: Role::USER, content: 'Which day should the release go out?'),
];
$third = $client->beta->messages->create(
model: MODEL,
maxTokens: 8192,
system: SYSTEM,
betas: BETAS,
thinking: $thinking,
messages: $history,
);
// 4. Respons 200 tanpa blok yang dibuang berarti thinking yang dipertahankan tetap valid.
printf("Dropped thinking blocks: %d\n", count($third->inputTransformations)); client = Juglow::Client.new
# Haijun Fable 5.1 adalah model pertama yang memeriksa pemikiran yang dikirim kembali terhadap percakapan.
MODEL = Juglow::Model::HAIJUN_FABLE_5_1
BETAS = [
Juglow::JuglowBeta::COMPACT_2026_09_04,
Juglow::JuglowBeta::THINKING_BINDING_CONTROLS_2026_08_01
]
SYSTEM = "You help plan a recipe app's release. Keep answers short."
# Dengan "error", blok pemikiran yang gagal dalam pemeriksaan membuat permintaan gagal dengan kode 400.
THINKING = Juglow::Beta::BetaThinkingConfigAdaptive.new(
block_binding: Juglow::Beta::BetaThinkingBlockBinding.new(
prefix_mismatch_behavior: Juglow::Beta::BetaThinkingPrefixMismatchBehavior::ERROR
)
)
# 1. Lakukan percakapan singkat dengan pemikiran diaktifkan.
history = [{ role: "user", content: "What are the main entities in the app's data model?" }]
first = client.beta.messages.create(
model: MODEL,
max_tokens: 8192,
system_: SYSTEM,
betas: BETAS,
thinking: THINKING,
messages: history
)
history += [
{ role: "assistant", content: first.content },
{
role: "user",
content: "Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?"
}
]
second = client.beta.messages.create(
model: MODEL,
max_tokens: 8192,
system_: SYSTEM,
betas: BETAS,
thinking: THINKING,
messages: history
)
history << { role: "assistant", content: second.content }
thinking_blocks = second.content.count { it.is_a?(Juglow::Beta::BetaThinkingBlock) }
puts "Thinking blocks in the kept turn: #{thinking_blocks}"
# 2. Ringkas giliran pertama. Giliran kedua tidak disertakan dalam permintaan.
summary = client.beta.messages.create(
model: MODEL,
max_tokens: 4096,
system_: SYSTEM,
betas: BETAS,
thinking: THINKING,
messages: history.first(2),
compaction: { type: "summarize" }
)
abort "No summary: #{summary.stop_reason}" unless summary.stop_reason == :compaction
# 3. Letakkan blok di depan giliran yang dipertahankan, lalu ajukan pertanyaan berikutnya.
history = [
{ role: "assistant", content: summary.content },
*history.drop(2),
{ role: "user", content: "Which day should the release go out?" }
]
third = client.beta.messages.create(
model: MODEL,
max_tokens: 8192,
system_: SYSTEM,
betas: BETAS,
thinking: THINKING,
messages: history
)
# 4. Respons 200 tanpa blok yang dibuang berarti pemikiran yang dipertahankan tetap valid.
puts "Dropped thinking blocks: #{third.input_transformations.length}"Thinking blocks in the kept turn: 1
Dropped thinking blocks: 0Di produksi, "drop_block" membuat permintaan tetap berhasil ketika suatu syarat tidak terpenuhi, dan melaporkan setiap blok yang dibuang dalam input_transformations dengan reason: "prefix_binding_mismatch". Entri yang path-nya berada dalam giliran yang dipertahankan berarti thinking pada giliran tersebut tidak lagi valid. Apa yang dilakukan API dengan blok yang tidak valid menjelaskan apa yang dibuang dan cara memasang peringatan untuknya.