Setiap respons Messages API menyertakan field stop_reason yang memberi tahu Anda mengapa Haijun berhenti menghasilkan output. Periksa field ini untuk memutuskan apakah akan menggunakan respons apa adanya, melanjutkan percakapan, mencoba ulang, atau beralih (fallback) ke model lain.
Untuk skema respons lengkap, lihat referensi Messages API.
Referensi cepat
| Nilai | Kapan terjadi | Apa yang harus dilakukan |
|---|---|---|
end_turn | Haijun menyelesaikan responsnya secara alami. | Gunakan respons tersebut. |
max_tokens | Respons mencapai batas max_tokens Anda. | Naikkan max_tokens atau lanjutkan respons. |
stop_sequence | Haijun mengeluarkan salah satu stop_sequences Anda. | Baca stop_sequence untuk melihat mana yang terpicu. |
tool_use | Haijun sedang memanggil alat. | Jalankan alat dan kembalikan hasilnya. Panggilan alat server yang masih belum memiliki blok hasilnya akan selesai dalam respons berikutnya. |
pause_turn | Loop alat server mencapai batas iterasinya. | Kirim kembali konten asisten untuk melanjutkan. |
refusal | Haijun menolak untuk merespons. | Baca stop_details dan coba ulang pada model fallback. |
model_context_window_exceeded | Respons memenuhi jendela konteks model. | Perlakukan respons sebagai terpotong. |
Field stop\_reason
Field stop_reason adalah bagian dari setiap respons Messages API yang berhasil. Tidak seperti error, yang menunjukkan kegagalan dalam memproses permintaan Anda, stop_reason memberi tahu Anda mengapa Haijun menyelesaikan pembuatan responsnya.
{
"id": "msg_01234",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Here's the answer to your question..."
}
],
"stop_reason": "end_turn",
"stop_sequence": null,
"stop_details": null,
"usage": {
"input_tokens": 100,
"output_tokens": 50
}
}Nilai stop reason
end\_turn
Alasan berhenti yang paling umum. Menunjukkan bahwa Haijun menyelesaikan responsnya secara alami.
curl https://haijun.my.id/v1/messages \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "haijun-opus-5-5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Hello!"}]
}' | jq 'if .stop_reason == "end_turn" then (.content[] | select(.type == "text") | .text) else . end' ant messages create \
--model haijun-opus-5-5 \
--max-tokens 1024 \
--message '{role: user, content: "Hello!"}' \
--format json | jq 'if .stop_reason == "end_turn" then (.content[] | select(.type == "text") | .text) else . end' client = juglow.Juglow()
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
)
if response.stop_reason == "end_turn":
# Proses respons lengkap
for block in response.content:
if block.type == "text":
print(block.text) const client = new Juglow();
const response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello!" }]
});
if (response.stop_reason === "end_turn") {
// Proses respons lengkap
const textBlock = response.content.find(
(block): block is Juglow.TextBlock => block.type === "text"
);
console.log(textBlock?.text);
} JuglowClient client = new();
var response = await client.Messages.Create(new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 1024,
Messages = [new() { Role = Role.User, Content = "Hello!" }]
});
if (response.StopReason == "end_turn")
{
// Proses respons lengkap
foreach (var block in response.Content)
{
if (block.TryPickText(out var textBlock))
{
Console.WriteLine(textBlock.Text);
}
}
} client := juglow.NewClient()
response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 1024,
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Hello!")),
},
})
if err != nil {
log.Fatal(err)
}
if response.StopReason == "end_turn" {
// Proses respons lengkap
for _, block := range response.Content {
if textBlock, ok := block.AsAny().(juglow.TextBlock); ok {
fmt.Println(textBlock.Text)
}
}
} JuglowClient client = JuglowOkHttpClient.fromEnv();
Message response = client.messages().create(
MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(1024L)
.addUserMessage("Hello!")
.build()
);
if (response.stopReason().map(StopReason.END_TURN::equals).orElse(false)) {
// Proses respons lengkap
response.content().stream()
.flatMap(block -> block.text().stream())
.forEach(textBlock -> IO.println(textBlock.text()));
} $client = new Client();
$response = $client->messages->create(
maxTokens: 1024,
messages: [['role' => 'user', 'content' => 'Hello!']],
model: 'haijun-opus-5-5',
);
if ($response->stopReason === 'end_turn') {
// Proses respons lengkap
foreach ($response->content as $block) {
if ($block->type === 'text') {
echo $block->text, PHP_EOL;
}
}
} client = Juglow::Client.new
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello!" }]
)
if response.stop_reason == :end_turn
# Proses respons lengkap
response.content.each do |block|
puts block.text if block.type == :text
end
endRespons kosong dengan end_turn
Terkadang Haijun mengembalikan respons kosong (tepat 2–3 token tanpa konten) dengan stop_reason: "end_turn". Ini biasanya terjadi ketika Haijun menafsirkan bahwa giliran asisten telah selesai, terutama setelah hasil alat.
Penyebab umum:
- Menambahkan blok teks tepat setelah hasil alat (Haijun belajar untuk mengharapkan pengguna selalu menyisipkan teks setelah hasil alat, sehingga ia mengakhiri gilirannya untuk mengikuti pola tersebut)
- Mengirim kembali respons Haijun yang sudah selesai tanpa menambahkan apa pun (Haijun sudah menentukan bahwa ia selesai, jadi ia akan tetap selesai)
Cara mencegah respons kosong:
# SALAH: Menambahkan teks langsung setelah tool_result
messages = [
{"role": "user", "content": "Calculate the sum of 1234 and 5678"},
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_123",
"name": "calculator",
"input": {"operation": "add", "a": 1234, "b": 5678},
}
],
},
{
"role": "user",
"content": [
{"type": "tool_result", "tool_use_id": "toolu_123", "content": "6912"},
{
"type": "text",
"text": "Here's the result", # Don't add text after tool_result
},
],
},
]
# BENAR: Kirim hasil alat secara langsung tanpa teks tambahan
messages = [
{"role": "user", "content": "Calculate the sum of 1234 and 5678"},
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_123",
"name": "calculator",
"input": {"operation": "add", "a": 1234, "b": 5678},
}
],
},
{
"role": "user",
"content": [
{"type": "tool_result", "tool_use_id": "toolu_123", "content": "6912"}
],
}, # Just the tool_result, no additional text
] // SALAH: Menambahkan teks langsung setelah tool_result
let messages: Juglow.MessageParam[] = [
{ role: "user", content: "Calculate the sum of 1234 and 5678" },
{
role: "assistant",
content: [
{
type: "tool_use",
id: "toolu_123",
name: "calculator",
input: { operation: "add", a: 1234, b: 5678 }
}
]
},
{
role: "user",
content: [
{ type: "tool_result", tool_use_id: "toolu_123", content: "6912" },
{ type: "text", text: "Here's the result" } // Don't add text after tool_result
]
}
];
// BENAR: Kirim hasil alat secara langsung tanpa teks tambahan
messages = [
{ role: "user", content: "Calculate the sum of 1234 and 5678" },
{
role: "assistant",
content: [
{
type: "tool_use",
id: "toolu_123",
name: "calculator",
input: { operation: "add", a: 1234, b: 5678 }
}
]
},
{
role: "user",
// Hanya tool_result, tanpa teks tambahan
content: [{ type: "tool_result", tool_use_id: "toolu_123", content: "6912" }]
}
]; using System.Text.Json;
using Juglow.Models.Messages;
var input = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(
"""{"operation":"add","a":1234,"b":5678}"""
)!;
// SALAH: Menambahkan teks langsung setelah tool_result
List<MessageParam> messages =
[
new() { Role = Role.User, Content = "Calculate the sum of 1234 and 5678" },
new()
{
Role = Role.Assistant,
Content = new List<ContentBlockParam>
{
new ToolUseBlockParam { ID = "toolu_123", Name = "calculator", Input = input }
}
},
new()
{
Role = Role.User,
Content = new List<ContentBlockParam>
{
new ToolResultBlockParam { ToolUseID = "toolu_123", Content = "6912" },
new TextBlockParam { Text = "Here's the result" } // Don't add text after tool_result
}
}
];
// BENAR: Kirim hasil alat secara langsung tanpa teks tambahan
messages =
[
new() { Role = Role.User, Content = "Calculate the sum of 1234 and 5678" },
new()
{
Role = Role.Assistant,
Content = new List<ContentBlockParam>
{
new ToolUseBlockParam { ID = "toolu_123", Name = "calculator", Input = input }
}
},
new()
{
Role = Role.User,
// Hanya tool_result, tanpa teks tambahan
Content = new List<ContentBlockParam>
{
new ToolResultBlockParam { ToolUseID = "toolu_123", Content = "6912" }
}
}
]; input := map[string]any{"operation": "add", "a": 1234, "b": 5678}
// SALAH: Menambahkan teks langsung setelah tool_result
messages := []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Calculate the sum of 1234 and 5678")),
juglow.NewAssistantMessage(
juglow.NewToolUseBlock("toolu_123", input, "calculator"),
),
juglow.NewUserMessage(
juglow.NewToolResultBlock("toolu_123", "6912", false),
juglow.NewTextBlock("Here's the result"), // Don't add text after tool_result
),
}
// BENAR: Kirim hasil alat secara langsung tanpa teks tambahan
messages = []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Calculate the sum of 1234 and 5678")),
juglow.NewAssistantMessage(
juglow.NewToolUseBlock("toolu_123", input, "calculator"),
),
// Hanya tool_result, tanpa teks tambahan
juglow.NewUserMessage(
juglow.NewToolResultBlock("toolu_123", "6912", false),
),
} ToolUseBlockParam toolUse = ToolUseBlockParam.builder()
.id("toolu_123")
.name("calculator")
.input(ToolUseBlockParam.Input.builder()
.putAdditionalProperty("operation", JsonValue.from("add"))
.putAdditionalProperty("a", JsonValue.from(1234))
.putAdditionalProperty("b", JsonValue.from(5678))
.build())
.build();
// SALAH: Menambahkan teks langsung setelah tool_result
List<MessageParam> messages = List.of(
MessageParam.builder().role(MessageParam.Role.USER)
.content("Calculate the sum of 1234 and 5678").build(),
MessageParam.builder().role(MessageParam.Role.ASSISTANT)
.contentOfBlockParams(List.of(ContentBlockParam.ofToolUse(toolUse))).build(),
MessageParam.builder().role(MessageParam.Role.USER)
.contentOfBlockParams(List.of(
ContentBlockParam.ofToolResult(
ToolResultBlockParam.builder().toolUseId("toolu_123").content("6912").build()),
// Jangan tambahkan teks setelah tool_result
ContentBlockParam.ofText(TextBlockParam.builder().text("Here's the result").build())
)).build()
);
// BENAR: Kirim hasil alat secara langsung tanpa teks tambahan
messages = List.of(
MessageParam.builder().role(MessageParam.Role.USER)
.content("Calculate the sum of 1234 and 5678").build(),
MessageParam.builder().role(MessageParam.Role.ASSISTANT)
.contentOfBlockParams(List.of(ContentBlockParam.ofToolUse(toolUse))).build(),
// Hanya tool_result, tanpa teks tambahan
MessageParam.builder().role(MessageParam.Role.USER)
.contentOfBlockParams(List.of(
ContentBlockParam.ofToolResult(
ToolResultBlockParam.builder().toolUseId("toolu_123").content("6912").build())
)).build()
); // SALAH: Menambahkan teks langsung setelah tool_result
$messages = [
['role' => 'user', 'content' => 'Calculate the sum of 1234 and 5678'],
[
'role' => 'assistant',
'content' => [
[
'type' => 'tool_use',
'id' => 'toolu_123',
'name' => 'calculator',
'input' => ['operation' => 'add', 'a' => 1234, 'b' => 5678],
],
],
],
[
'role' => 'user',
'content' => [
['type' => 'tool_result', 'tool_use_id' => 'toolu_123', 'content' => '6912'],
// Jangan tambahkan teks setelah tool_result
['type' => 'text', 'text' => "Here's the result"],
],
],
];
// BENAR: Kirim hasil alat secara langsung tanpa teks tambahan
$messages = [
['role' => 'user', 'content' => 'Calculate the sum of 1234 and 5678'],
[
'role' => 'assistant',
'content' => [
[
'type' => 'tool_use',
'id' => 'toolu_123',
'name' => 'calculator',
'input' => ['operation' => 'add', 'a' => 1234, 'b' => 5678],
],
],
],
[
'role' => 'user',
// Hanya tool_result, tanpa teks tambahan
'content' => [
['type' => 'tool_result', 'tool_use_id' => 'toolu_123', 'content' => '6912'],
],
],
]; # SALAH: Menambahkan teks langsung setelah tool_result
messages = [
{ role: "user", content: "Calculate the sum of 1234 and 5678" },
{
role: "assistant",
content: [
{
type: "tool_use",
id: "toolu_123",
name: "calculator",
input: { operation: "add", a: 1234, b: 5678 }
}
]
},
{
role: "user",
content: [
{ type: "tool_result", tool_use_id: "toolu_123", content: "6912" },
# Jangan tambahkan teks setelah tool_result
{ type: "text", text: "Here's the result" }
]
}
]
# BENAR: Kirim hasil alat secara langsung tanpa teks tambahan
messages = [
{ role: "user", content: "Calculate the sum of 1234 and 5678" },
{
role: "assistant",
content: [
{
type: "tool_use",
id: "toolu_123",
name: "calculator",
input: { operation: "add", a: 1234, b: 5678 }
}
]
},
{
role: "user",
# Hanya tool_result, tanpa teks tambahan
content: [
{ type: "tool_result", tool_use_id: "toolu_123", content: "6912" }
]
}
]Jika Anda masih mendapatkan respons kosong setelah memperbaiki struktur pesan, tambahkan prompt lanjutan dalam pesan pengguna baru alih-alih mencoba ulang dengan respons kosong tersebut:
def handle_empty_response(client, messages):
response = client.messages.create(
model="haijun-opus-5-5", max_tokens=1024, messages=messages
)
# Periksa apakah respons kosong
if response.stop_reason == "end_turn" and not response.content:
# SALAH: Jangan hanya mencoba ulang dengan respons kosong
# Ini tidak akan berhasil karena Haijun sudah memutuskan bahwa ia selesai
# BENAR: Tambahkan prompt lanjutan dalam pesan pengguna BARU
messages.append({"role": "user", "content": "Please continue"})
response = client.messages.create(
model="haijun-opus-5-5", max_tokens=1024, messages=messages
)
return response async function handleEmptyResponse(
client: Juglow,
messages: Juglow.MessageParam[]
): Promise<Juglow.Message> {
let response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 1024,
messages
});
// Periksa apakah respons kosong
if (response.stop_reason === "end_turn" && response.content.length === 0) {
// SALAH: Jangan hanya mencoba ulang dengan respons yang kosong
// Ini tidak akan berhasil karena Haijun sudah memutuskan bahwa ia selesai
// BENAR: Tambahkan prompt lanjutan dalam pesan pengguna BARU
messages.push({ role: "user", content: "Please continue" });
response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 1024,
messages
});
}
return response;
} static async Task<Message> HandleEmptyResponse(JuglowClient client, List<MessageParam> messages)
{
var response = await client.Messages.Create(new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 1024,
Messages = messages
});
// Periksa apakah respons kosong
if (response.StopReason == "end_turn" && response.Content.Count == 0)
{
// BENAR: Tambahkan prompt lanjutan dalam pesan pengguna BARU
messages.Add(new() { Role = Role.User, Content = "Please continue" });
response = await client.Messages.Create(new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 1024,
Messages = messages
});
}
return response;
} func handleEmptyResponse(client juglow.Client, messages []juglow.MessageParam) (*juglow.Message, error) {
response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 1024,
Messages: messages,
})
if err != nil {
return nil, err
}
// Periksa apakah respons kosong
if response.StopReason == "end_turn" && len(response.Content) == 0 {
// BENAR: Tambahkan prompt lanjutan dalam pesan pengguna BARU
messages = append(messages, juglow.NewUserMessage(juglow.NewTextBlock("Please continue")))
response, err = client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 1024,
Messages: messages,
})
if err != nil {
return nil, err
}
}
return response, nil
} static Message handleEmptyResponse(JuglowClient client, List<MessageParam> messages) {
Message response = client.messages().create(
MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(1024L)
.messages(messages)
.build()
);
// Periksa apakah respons kosong
boolean isEndTurn = response.stopReason().map(StopReason.END_TURN::equals).orElse(false);
if (isEndTurn && response.content().isEmpty()) {
// BENAR: Tambahkan prompt lanjutan dalam pesan pengguna BARU
List<MessageParam> extended = new ArrayList<>(messages);
extended.add(MessageParam.builder()
.role(MessageParam.Role.USER)
.content("Please continue")
.build());
response = client.messages().create(
MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(1024L)
.messages(extended)
.build()
);
}
return response;
} function handle_empty_response(Client $client, array $messages)
{
$response = $client->messages->create(
maxTokens: 1024,
messages: $messages,
model: 'haijun-opus-5-5',
);
// Periksa apakah respons kosong
if ($response->stopReason === 'end_turn' && count($response->content) === 0) {
// BENAR: Tambahkan prompt lanjutan dalam pesan pengguna BARU
$messages[] = ['role' => 'user', 'content' => 'Please continue'];
$response = $client->messages->create(
maxTokens: 1024,
messages: $messages,
model: 'haijun-opus-5-5',
);
}
return $response;
} def handle_empty_response(client, messages)
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 1024,
messages: messages
)
# Periksa apakah respons kosong
if response.stop_reason == :end_turn && response.content.empty?
# BENAR: Tambahkan prompt lanjutan dalam pesan pengguna BARU
messages << { role: "user", content: "Please continue" }
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 1024,
messages: messages
)
end
response
endPraktik terbaik:
- Jangan pernah menambahkan blok teks tepat setelah hasil alat: Ini mengajarkan Haijun untuk mengharapkan input pengguna setelah setiap penggunaan alat.
- Jangan mencoba ulang respons kosong tanpa modifikasi: Mengirim kembali respons kosong tidak akan membantu.
- Gunakan prompt lanjutan sebagai upaya terakhir: Hanya jika perbaikan ini tidak menyelesaikan masalah.
max\_tokens
Haijun berhenti karena mencapai batas max_tokens yang ditentukan dalam permintaan Anda.
curl https://haijun.my.id/v1/messages \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "haijun-opus-5-5",
"max_tokens": 10,
"messages": [{"role": "user", "content": "Explain quantum physics"}]
}' | jq '.stop_reason' ant messages create \
--model haijun-opus-5-5 \
--max-tokens 10 \
--message '{role: user, content: "Explain quantum physics"}' \
--format json | jq '.stop_reason' client = juglow.Juglow()
# Permintaan dengan token terbatas
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=10,
messages=[{"role": "user", "content": "Explain quantum physics"}],
)
if response.stop_reason == "max_tokens":
# Respons terpotong
print("Response was cut off at token limit")
# Pertimbangkan untuk membuat permintaan lain agar dapat melanjutkan const client = new Juglow();
// Permintaan dengan token terbatas
const response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 10,
messages: [{ role: "user", content: "Explain quantum physics" }]
});
if (response.stop_reason === "max_tokens") {
// Respons terpotong
console.log("Response was cut off at token limit");
// Pertimbangkan untuk membuat permintaan lain guna melanjutkan
} JuglowClient client = new();
// Permintaan dengan token terbatas
var response = await client.Messages.Create(new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 10,
Messages = [new() { Role = Role.User, Content = "Explain quantum physics" }]
});
if (response.StopReason == "max_tokens")
{
// Respons terpotong
Console.WriteLine("Response was cut off at token limit");
// Pertimbangkan untuk membuat permintaan lain guna melanjutkan
} client := juglow.NewClient()
// Permintaan dengan token terbatas
response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 10,
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Explain quantum physics")),
},
})
if err != nil {
log.Fatal(err)
}
if response.StopReason == "max_tokens" {
// Respons terpotong
fmt.Println("Response was cut off at token limit")
// Pertimbangkan untuk membuat permintaan lain guna melanjutkan
} JuglowClient client = JuglowOkHttpClient.fromEnv();
// Permintaan dengan token terbatas
Message response = client.messages().create(
MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(10L)
.addUserMessage("Explain quantum physics")
.build()
);
if (response.stopReason().map(StopReason.MAX_TOKENS::equals).orElse(false)) {
// Respons terpotong
IO.println("Response was cut off at token limit");
// Pertimbangkan untuk membuat permintaan lain guna melanjutkan
} $client = new Client();
// Permintaan dengan token terbatas
$response = $client->messages->create(
maxTokens: 10,
messages: [['role' => 'user', 'content' => 'Explain quantum physics']],
model: 'haijun-opus-5-5',
);
if ($response->stopReason === 'max_tokens') {
// Respons terpotong
echo 'Response was cut off at token limit', PHP_EOL;
// Pertimbangkan untuk membuat permintaan lain guna melanjutkan
} client = Juglow::Client.new
# Permintaan dengan jumlah token terbatas
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 10,
messages: [{ role: "user", content: "Explain quantum physics" }]
)
if response.stop_reason == :max_tokens
# Respons terpotong
puts "Response was cut off at token limit"
# Pertimbangkan untuk mengirim permintaan lain guna melanjutkan
endBlok penggunaan alat yang tidak lengkap
Jika respons Haijun terpotong karena mencapai batas max_tokens, dan respons yang terpotong tersebut berisi blok penggunaan alat yang tidak lengkap, Anda perlu mencoba ulang permintaan dengan nilai max_tokens yang lebih tinggi untuk mendapatkan penggunaan alat secara lengkap.
RESPONSE=$(ant messages create --max-tokens 1024 --format jsonl <<'YAML'
model: haijun-opus-5-5
tools:
- name: get_weather
description: Get the current weather in a given location
input_schema:
type: object
properties:
location:
type: string
required:
- location
messages:
- role: user
content: What is the weather in San Francisco?
YAML
)
# Periksa apakah respons terpotong di tengah penggunaan alat
STOP_REASON=$(jq -r '.stop_reason' <<<"$RESPONSE")
LAST_TYPE=$(jq -r '.content[-1].type' <<<"$RESPONSE")
if [ "$STOP_REASON" = "max_tokens" ] && [ "$LAST_TYPE" = "tool_use" ]; then
# Coba lagi dengan max_tokens yang lebih tinggi
ant messages create --max-tokens 4096 <<'YAML'
model: haijun-opus-5-5
tools:
- name: get_weather
description: Get the current weather in a given location
input_schema:
type: object
properties:
location:
type: string
required:
- location
messages:
- role: user
content: What is the weather in San Francisco?
YAML
fi # Periksa apakah respons terpotong saat penggunaan alat
if response.stop_reason == "max_tokens":
# Periksa apakah blok konten terakhir adalah tool_use yang tidak lengkap
last_block = response.content[-1]
if last_block.type == "tool_use":
# Kirim permintaan dengan max_tokens yang lebih tinggi
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=4096, # Increased limit
messages=messages,
tools=tools,
) // Periksa apakah respons terpotong selama penggunaan alat
if (response.stop_reason === "max_tokens") {
// Periksa apakah blok konten terakhir adalah tool_use yang tidak lengkap
const lastBlock = response.content[response.content.length - 1];
if (lastBlock.type === "tool_use") {
// Kirim permintaan dengan max_tokens yang lebih tinggi
response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096, // Increased limit
messages: messages,
tools: tools
});
}
} using System.Linq;
using Juglow;
using Juglow.Models.Messages;
JuglowClient client = new();
var parameters = new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 1024,
Messages = messages,
Tools = tools
};
var response = await client.Messages.Create(parameters);
if (response.StopReason == "max_tokens")
{
var lastBlock = response.Content.Last();
if (lastBlock.TryPickToolUse(out _))
{
response = await client.Messages.Create(parameters with { MaxTokens = 4096 });
}
} response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 1024,
Messages: messages,
Tools: tools,
})
if err != nil {
log.Fatal(err)
}
if response.StopReason == "max_tokens" {
lastBlock := response.Content[len(response.Content)-1]
switch lastBlock.AsAny().(type) {
case juglow.ToolUseBlock:
response, err = client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 4096,
Messages: messages,
Tools: tools,
})
if err != nil {
log.Fatal(err)
}
}
} // Periksa apakah respons terpotong selama penggunaan alat
if (response.stopReason().isPresent() && response.stopReason().get().equals(StopReason.MAX_TOKENS)) {
ContentBlock lastBlock = response.content().get(response.content().size() - 1);
if (lastBlock.toolUse().isPresent()) {
// Kirim permintaan dengan max_tokens yang lebih tinggi
response = client.messages().create(
MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L) // Increased limit
.messages(messages)
.tools(tools)
.build()
);
}
} $response = $client->messages->create(
maxTokens: 1024,
messages: $messages,
model: 'haijun-opus-5-5',
tools: $tools,
);
if ($response->stopReason === 'max_tokens') {
$lastBlock = end($response->content);
if ($lastBlock->type === 'tool_use') {
$response = $client->messages->create(
maxTokens: 4096,
messages: $messages,
model: 'haijun-opus-5-5',
tools: $tools,
);
}
} response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 1024,
messages: messages,
tools: tools
)
if response.stop_reason == :max_tokens
last_block = response.content.last
if last_block.type == :tool_use
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
messages: messages,
tools: tools
)
end
endstop\_sequence
Haijun menemukan salah satu stop sequence kustom Anda.
curl https://haijun.my.id/v1/messages \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "haijun-opus-5-5",
"max_tokens": 1024,
"stop_sequences": ["END", "STOP"],
"messages": [{"role": "user", "content": "Generate text until you say END"}]
}' | jq '{stop_reason, stop_sequence}' ant messages create \
--model haijun-opus-5-5 \
--max-tokens 1024 \
--stop-sequence END --stop-sequence STOP \
--message '{role: user, content: "Generate text until you say END"}' \
--format json | jq '{stop_reason, stop_sequence}' client = juglow.Juglow()
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=1024,
stop_sequences=["END", "STOP"],
messages=[{"role": "user", "content": "Generate text until you say END"}],
)
if response.stop_reason == "stop_sequence":
print(f"Stopped at sequence: {response.stop_sequence}") const client = new Juglow();
const response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 1024,
stop_sequences: ["END", "STOP"],
messages: [{ role: "user", content: "Generate text until you say END" }]
});
if (response.stop_reason === "stop_sequence") {
console.log(`Stopped at sequence: ${response.stop_sequence}`);
} JuglowClient client = new();
var response = await client.Messages.Create(new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 1024,
StopSequences = ["END", "STOP"],
Messages = [new() { Role = Role.User, Content = "Generate text until you say END" }]
});
if (response.StopReason == "stop_sequence")
{
Console.WriteLine($"Stopped at sequence: {response.StopSequence}");
} client := juglow.NewClient()
response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 1024,
StopSequences: []string{"END", "STOP"},
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Generate text until you say END")),
},
})
if err != nil {
log.Fatal(err)
}
if response.StopReason == "stop_sequence" {
fmt.Printf("Stopped at sequence: %s\n", response.StopSequence)
} JuglowClient client = JuglowOkHttpClient.fromEnv();
Message response = client.messages().create(
MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(1024L)
.addStopSequence("END")
.addStopSequence("STOP")
.addUserMessage("Generate text until you say END")
.build()
);
if (response.stopReason().map(StopReason.STOP_SEQUENCE::equals).orElse(false)) {
IO.println("Stopped at sequence: " + response.stopSequence().orElse(""));
} $client = new Client();
$response = $client->messages->create(
maxTokens: 1024,
messages: [['role' => 'user', 'content' => 'Generate text until you say END']],
model: 'haijun-opus-5-5',
stopSequences: ['END', 'STOP'],
);
if ($response->stopReason === 'stop_sequence') {
echo "Stopped at sequence: {$response->stopSequence}", PHP_EOL;
} client = Juglow::Client.new
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 1024,
stop_sequences: ["END", "STOP"],
messages: [{ role: "user", content: "Generate text until you say END" }]
)
if response.stop_reason == :stop_sequence
puts "Stopped at sequence: #{response.stop_sequence}"
endtool\_use
Haijun sedang memanggil alat dan mengharapkan Anda menjalankannya.
Note: Untuk sebagian besar implementasi "tool use" (penggunaan alat), gunakan tool runner, yang secara otomatis menangani eksekusi alat, pemformatan hasil, dan pengelolaan percakapan.
curl https://haijun.my.id/v1/messages \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "haijun-opus-5-5",
"max_tokens": 1024,
"tools": [{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {"location": {"type": "string", "description": "City and state"}},
"required": ["location"]
}
}],
"messages": [{"role": "user", "content": "What is the weather in San Francisco?"}]
}' | jq '.stop_reason, (.content[] | select(.type == "tool_use"))' ant messages create --format json <<'YAML' | jq '.stop_reason, (.content[] | select(.type == "tool_use"))'
model: haijun-opus-5-5
max_tokens: 1024
messages:
- role: user
content: What is the weather in San Francisco?
tools:
- name: get_weather
description: Get the current weather in a given location
input_schema:
type: object
properties:
location: {type: string, description: City and state}
required: [location]
YAML client = juglow.Juglow()
weather_tool = {
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City and state"},
},
"required": ["location"],
},
}
def execute_tool(name, tool_input):
"""Execute a tool and return the result."""
return f"Weather in {tool_input.get('location', 'unknown')}: 72°F"
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=1024,
tools=[weather_tool],
messages=[{"role": "user", "content": "What is the weather in San Francisco?"}],
)
if response.stop_reason == "tool_use":
# Ekstrak dan jalankan alat
for block in response.content:
if block.type == "tool_use":
result = execute_tool(block.name, block.input)
# Kembalikan hasil ke Haijun untuk respons akhir const client = new Juglow();
const weatherTool: Juglow.Tool = {
name: "get_weather",
description: "Get the current weather in a given location",
input_schema: {
type: "object",
properties: {
location: { type: "string", description: "City and state" }
},
required: ["location"]
}
};
function executeTool(name: string, input: Record<string, string>): string {
return `Weather in ${input.location ?? "unknown"}: 72°F`;
}
const response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 1024,
tools: [weatherTool],
messages: [{ role: "user", content: "What is the weather in San Francisco?" }]
});
if (response.stop_reason === "tool_use") {
// Ekstrak dan jalankan alat
for (const block of response.content) {
if (block.type === "tool_use") {
const result = executeTool(block.name, block.input as Record<string, string>);
// Kembalikan hasil ke Haijun untuk respons akhir
}
}
} JuglowClient client = new();
var weatherTool = new Tool
{
Name = "get_weather",
Description = "Get the current weather in a given location",
InputSchema = new InputSchema
{
Properties = new Dictionary<string, JsonElement>
{
["location"] = JsonSerializer.SerializeToElement(
new { type = "string", description = "City and state" }
),
},
Required = ["location"]
}
};
var response = await client.Messages.Create(new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 1024,
Tools = [weatherTool],
Messages = [new() { Role = Role.User, Content = "What is the weather in San Francisco?" }]
});
if (response.StopReason == "tool_use")
{
// Ekstrak dan jalankan alat
foreach (var block in response.Content)
{
if (block.TryPickToolUse(out var toolUse))
{
// Jalankan toolUse.Name dengan toolUse.Input dan kembalikan hasilnya ke Haijun
}
}
} client := juglow.NewClient()
weatherTool := juglow.ToolParam{
Name: "get_weather",
Description: juglow.String("Get the current weather in a given location"),
InputSchema: juglow.ToolInputSchemaParam{
Properties: map[string]any{
"location": map[string]string{"type": "string", "description": "City and state"},
},
Required: []string{"location"},
},
}
response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 1024,
Tools: []juglow.ToolUnionParam{{OfTool: &weatherTool}},
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("What is the weather in San Francisco?")),
},
})
if err != nil {
log.Fatal(err)
}
if response.StopReason == "tool_use" {
// Ekstrak dan jalankan alat
for _, block := range response.Content {
if toolUse, ok := block.AsAny().(juglow.ToolUseBlock); ok {
fmt.Println(toolUse.Name, toolUse.Input)
// Kembalikan hasil ke Haijun untuk respons akhir
}
}
} void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
Tool weatherTool = Tool.builder()
.name("get_weather")
.description("Get the current weather in a given location")
.inputSchema(Tool.InputSchema.builder()
.properties(JsonValue.from(Map.of(
"location", Map.of("type", "string", "description", "City and state")
)))
.putAdditionalProperty("required", JsonValue.from(List.of("location")))
.build())
.build();
Message response = client.messages().create(
MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(1024L)
.addTool(weatherTool)
.addUserMessage("What is the weather in San Francisco?")
.build()
);
if (response.stopReason().map(StopReason.TOOL_USE::equals).orElse(false)) {
// Ekstrak dan jalankan alat
for (ContentBlock block : response.content()) {
block.toolUse().ifPresent(toolUse -> {
// Jalankan toolUse.name() dengan toolUse.input() lalu kembalikan hasilnya ke Haijun
});
}
} $client = new Client();
$weatherTool = [
'name' => 'get_weather',
'description' => 'Get the current weather in a given location',
'input_schema' => [
'type' => 'object',
'properties' => [
'location' => ['type' => 'string', 'description' => 'City and state'],
],
'required' => ['location'],
],
];
$response = $client->messages->create(
maxTokens: 1024,
messages: [['role' => 'user', 'content' => 'What is the weather in San Francisco?']],
model: 'haijun-opus-5-5',
tools: [$weatherTool],
);
if ($response->stopReason === 'tool_use') {
// Ekstrak dan jalankan alat
foreach ($response->content as $block) {
if ($block->type === 'tool_use') {
// Jalankan $block->name dengan $block->input dan kembalikan hasilnya ke Haijun
}
}
} client = Juglow::Client.new
weather_tool = {
name: "get_weather",
description: "Get the current weather in a given location",
input_schema: {
type: "object",
properties: {
location: { type: "string", description: "City and state" }
},
required: ["location"]
}
}
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 1024,
tools: [weather_tool],
messages: [{ role: "user", content: "What is the weather in San Francisco?" }]
)
if response.stop_reason == :tool_use
# Ekstrak dan jalankan alat
response.content.each do |block|
next unless block.type == :tool_use
# Jalankan block.name dengan block.input dan kembalikan hasilnya ke Haijun
end
endRespons tool_use juga dapat berisi blok server_tool_use yang id-nya tidak memiliki blok hasil yang cocok. Panggilan alat server tersebut belum selesai, dan respons ini tidak membawa hasilnya. Dalam kasus umum, Haijun memanggil alat server dan salah satu alat klien Anda dalam kelompok panggilan alat paralel yang sama: API kembali tanpa menjalankan alat server sehingga Anda dapat menjalankan alat klien terlebih dahulu. Tidak ada penanda lain untuk status ini; deteksi dengan memeriksa id setiap blok server_tool_use atau mcp_tool_use untuk mencari blok hasil yang cocok.
Note: Dengan pemanggilan alat terprogram, bentuk respons yang sama memiliki arti yang berbeda. Blok
tool_useklien berasal dari kode yang sedang berjalan di alatcode_execution, bukan dari Haijun secara langsung, dan fieldcaller-nya menyebutkan blokcode_executionyang memanggilnya. Kode tersebut sudah mulai berjalan: ia dijeda menunggu bloktool_resultAnda, dan mengirimkannya akan melanjutkan eksekusi alih-alih memulai alat yang ditangguhkan. Blok hasil milik blokcode_executionitu sendiri tiba setelah kode selesai, yang dapat memerlukan lebih dari satu putaran hasil alat. Pesan pengguna lanjutannya sendiri sama dalam kedua kasus; dengan pemanggilan alat terprogram, kirimkan juga kembaliiddari fieldcontainerrespons, seperti yang ditunjukkan halaman tersebut.
{
"stop_reason": "tool_use",
"content": [
{
"type": "server_tool_use",
"id": "srvtoolu_01HxbWnMRmbWyMfUtJKC45rA",
"name": "web_search",
"input": { "query": "example article" }
},
{
"type": "tool_use",
"id": "toolu_01PjgRJLbXrXEMZwDNYLnBqk",
"name": "run_command",
"input": { "command": "uname -a" }
}
]
}Kelanjutannya adalah pesan pengguna berisi blok tool_result, satu untuk setiap blok tool_use dalam respons (lihat Menangani panggilan alat), dengan dua aturan tambahan: pesan tersebut tidak boleh berisi apa pun selain blok tool_result, dan permintaan harus mempertahankan array tools yang sama. Permintaan lanjutan yang tidak lagi mendefinisikan alat server yang sedang menunggu akan gagal dengan 400 yang pesannya diakhiri `but no web_search tool was provided. API melampirkan hasil Anda ke giliran asisten yang masih terbuka, menjalankan alat server yang ditangguhkan (untuk eksekusi kode yang dijeda, melanjutkannya), dan meneruskan giliran tersebut. Untuk alat server yang dipanggil Haijun secara langsung, content respons berikutnya dimulai dengan blok hasil yang menjawab id server_tool_use` dari respons sebelumnya.
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01PjgRJLbXrXEMZwDNYLnBqk",
"content": "Linux demo-host 6.8.0-52-generic x86_64 GNU/Linux"
}
]
}Menambahkan apa pun setelah blok tool_result dalam pesan pengguna tersebut, seperti teks, akan mengakhiri giliran asisten; untuk alat server yang dipanggil Haijun secara langsung, permintaan kemudian gagal dengan 400 invalid_request_error yang menyebutkan alat server yang belum terselesaikan:
`web_search` tool use with id `srvtoolu_01HxbWnMRmbWyMfUtJKC45rA` was found without a corresponding `web_search_tool_result` blockMenghilangkan tool_result, atau menempatkannya setelah konten lain, akan gagal lebih awal dengan error standar tool_use ids were found without tool_result blocks immediately after. Untuk memberi Haijun input tambahan, kirimkan sebagai pesan pengguna terpisah setelah giliran selesai.
pause\_turn
Dikembalikan ketika loop sampling sisi server mencapai batas iterasinya saat mengeksekusi alat server seperti pencarian web. Batas default adalah 10 iterasi per permintaan.
Ketika ini terjadi, respons mungkin berisi blok server_tool_use tanpa blok hasil yang sesuai. Agar Haijun dapat menyelesaikan pemrosesan, lanjutkan percakapan dengan mengirim kembali respons apa adanya. Respons yang membiarkan blok tool_use klien menunggu Anda tidak pernah memiliki stop_reason berupa pause_turn: ketika Haijun berhenti untuk memanggil alat Anda, stop_reason-nya adalah tool_use, dan Anda melanjutkannya dengan mengirim blok tool_result klien alih-alih respons itu sendiri.
# SDK menangani kelanjutan secara langsung. Dengan cURL, periksa stop_reason
# pada respons lalu kirim ulang POST dengan konten assistant ditambahkan.
curl https://haijun.my.id/v1/messages \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "haijun-opus-5-5",
"max_tokens": 4096,
"tools": [{"type": "web_search_20250305", "name": "web_search"}],
"messages": [{"role": "user", "content": "Search for latest AI news"}]
}' | jq '{stop_reason, content}' # Periksa stop_reason; jika nilainya pause_turn, jalankan ulang dengan respons
# asisten ditambahkan ke --message.
ant messages create --format json <<'YAML' | jq '{stop_reason, content}'
model: haijun-opus-5-5
max_tokens: 4096
tools:
- {type: web_search_20250305, name: web_search}
messages:
- {role: user, content: "Search for latest AI news"}
YAML response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=4096,
tools=[{"type": "web_search_20250305", "name": "web_search"}],
messages=[{"role": "user", "content": "Search for latest AI news"}],
)
if response.stop_reason == "pause_turn":
# Lanjutkan percakapan dengan mengirimkan kembali respons tersebut
messages = [
{"role": "user", "content": "Search for latest AI news"},
{"role": "assistant", "content": response.content},
]
continuation = client.messages.create(
model="haijun-opus-5-5",
max_tokens=4096,
messages=messages,
tools=[{"type": "web_search_20250305", "name": "web_search"}],
) const response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096,
tools: [{ type: "web_search_20250305", name: "web_search" }],
messages: [{ role: "user", content: "Search for latest AI news" }]
});
if (response.stop_reason === "pause_turn") {
// Lanjutkan percakapan dengan mengirimkan kembali respons tersebut
const continuation = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096,
tools: [{ type: "web_search_20250305", name: "web_search" }],
messages: [
{ role: "user", content: "Search for latest AI news" },
{ role: "assistant", content: response.content }
]
});
} List<ToolUnion> tools = [new ToolUnion(new WebSearchTool20250305())];
MessageParam userMessage = new() { Role = Role.User, Content = "Search for latest AI news" };
var response = await client.Messages.Create(new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 4096,
Tools = tools,
Messages = [userMessage]
});
if (response.StopReason == "pause_turn")
{
// Lanjutkan percakapan dengan mengirimkan kembali respons tersebut
var continuation = await client.Messages.Create(new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 4096,
Tools = tools,
Messages =
[
userMessage,
new()
{
Role = Role.Assistant,
Content = response.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
}
]
});
} tools := []juglow.ToolUnionParam{
{OfWebSearchTool20250305: &juglow.WebSearchTool20250305Param{}},
}
userMessage := juglow.NewUserMessage(juglow.NewTextBlock("Search for latest AI news"))
response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 4096,
Tools: tools,
Messages: []juglow.MessageParam{userMessage},
})
if err != nil {
log.Fatal(err)
}
if response.StopReason == "pause_turn" {
// Lanjutkan percakapan dengan mengirimkan kembali respons tersebut
var contentParams []juglow.ContentBlockParamUnion
for _, block := range response.Content {
contentParams = append(contentParams, block.ToParam())
}
continuation, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 4096,
Tools: tools,
Messages: []juglow.MessageParam{userMessage, juglow.NewAssistantMessage(contentParams...)},
})
if err != nil {
log.Fatal(err)
}
_ = continuation
} Message response = client.messages().create(
MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L)
.addTool(WebSearchTool20250305.builder().build())
.addUserMessage("Search for latest AI news")
.build()
);
if (response.stopReason().map(StopReason.PAUSE_TURN::equals).orElse(false)) {
// Lanjutkan percakapan dengan mengirimkan kembali respons tersebut
Message continuation = client.messages().create(
MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L)
.addTool(WebSearchTool20250305.builder().build())
.addUserMessage("Search for latest AI news")
.addMessage(response)
.build()
);
} $tools = [['type' => 'web_search_20250305', 'name' => 'web_search']];
$userMessage = ['role' => 'user', 'content' => 'Search for latest AI news'];
$response = $client->messages->create(
maxTokens: 4096,
messages: [$userMessage],
model: 'haijun-opus-5-5',
tools: $tools,
);
if ($response->stopReason === 'pause_turn') {
// Lanjutkan percakapan dengan mengirimkan kembali respons tersebut
$continuation = $client->messages->create(
maxTokens: 4096,
messages: [
$userMessage,
['role' => 'assistant', 'content' => $response->content],
],
model: 'haijun-opus-5-5',
tools: $tools,
);
} tools = [{ type: "web_search_20250305", name: "web_search" }]
user_message = { role: "user", content: "Search for latest AI news" }
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
tools: tools,
messages: [user_message]
)
if response.stop_reason == :pause_turn
# Lanjutkan percakapan dengan mengirimkan kembali respons tersebut
continuation = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
tools: tools,
messages: [user_message, { role: "assistant", content: response.content }]
)
endNote: Aplikasi Anda harus menangani
pause_turndalam setiap loop agen yang menggunakan alat server. Tambahkan respons asisten ke array messages Anda dan buat permintaan API lain agar Haijun dapat melanjutkan.
refusal
Haijun menolak untuk menghasilkan respons. Pengklasifikasi keamanan mengembalikan alasan berhenti ini sebagai respons HTTP 200 normal, bukan error.
curl https://haijun.my.id/v1/messages \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "haijun-opus-5-5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "[Unsafe request]"}]
}' | jq '{stop_reason, stop_details}' ant messages create \
--model haijun-opus-5-5 \
--max-tokens 1024 \
--message '{role: user, content: "[Unsafe request]"}' \
--format json | jq '{stop_reason, stop_details}' client = juglow.Juglow()
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "[Unsafe request]"}],
)
if response.stop_reason == "refusal":
# Haijun menolak untuk merespons
print("Haijun was unable to process this request")
# Pertimbangkan untuk menyusun ulang atau mengubah permintaan const client = new Juglow();
const response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 1024,
messages: [{ role: "user", content: "[Unsafe request]" }]
});
if (response.stop_reason === "refusal") {
// Haijun menolak untuk merespons
console.log("Haijun was unable to process this request");
// Pertimbangkan untuk menyusun ulang atau mengubah permintaan
} JuglowClient client = new();
var response = await client.Messages.Create(new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 1024,
Messages = [new() { Role = Role.User, Content = "[Unsafe request]" }]
});
if (response.StopReason == "refusal")
{
// Haijun menolak untuk merespons
Console.WriteLine("Haijun was unable to process this request");
// Pertimbangkan untuk menyusun ulang atau mengubah permintaan
} client := juglow.NewClient()
response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 1024,
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("[Unsafe request]")),
},
})
if err != nil {
log.Fatal(err)
}
if response.StopReason == "refusal" {
// Haijun menolak untuk merespons
fmt.Println("Haijun was unable to process this request")
// Pertimbangkan untuk menyusun ulang atau mengubah permintaan
} JuglowClient client = JuglowOkHttpClient.fromEnv();
Message response = client.messages().create(
MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(1024L)
.addUserMessage("[Unsafe request]")
.build()
);
if (response.stopReason().map(StopReason.REFUSAL::equals).orElse(false)) {
// Haijun menolak untuk merespons
IO.println("Haijun was unable to process this request");
// Pertimbangkan untuk menyusun ulang atau mengubah permintaan
} $client = new Client();
$response = $client->messages->create(
maxTokens: 1024,
messages: [['role' => 'user', 'content' => '[Unsafe request]']],
model: 'haijun-opus-5-5',
);
if ($response->stopReason === 'refusal') {
// Haijun menolak untuk merespons
echo 'Haijun was unable to process this request', PHP_EOL;
// Pertimbangkan untuk menyusun ulang atau mengubah permintaan
} client = Juglow::Client.new
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 1024,
messages: [{ role: "user", content: "[Unsafe request]" }]
)
if response.stop_reason == :refusal
# Haijun menolak untuk merespons
puts "Haijun was unable to process this request"
# Pertimbangkan untuk menyusun ulang atau mengubah permintaan
endTip: Jika Anda sering menemui alasan berhenti
refusalsaat menggunakan Haijun Sonnet 4.5 atau Haijun Opus 4.1 (yang terakhir telah dipensiunkan, kecuali di Bedrock dan Google Cloud), Anda dapat mencoba memperbarui panggilan API Anda untuk menggunakan Haiku 4.5 (haijun-haiku-4-5-20251001), yang memiliki batasan penggunaan berbeda. Pelajari lebih lanjut tentang memahami filter keamanan API Sonnet 4.5.
Pada penolakan, objek stop_details mengidentifikasi kategori kebijakan yang memicunya. Kategori-kategori tersebut dan bentuk respons penolakan lengkap dibahas di Penolakan dan fallback. stop_details bernilai null untuk semua alasan berhenti selain refusal.
Permintaan yang ditolak pada Haijun Fable 5.1, Haijun Fable 5, Haijun Opus 5.5, atau Haijun Opus 5 biasanya dapat dilayani dengan mencoba ulang pada model Haijun lain. Penolakan dan fallback menunjukkan cara menyiapkan percobaan ulang tersebut, baik di sisi server maupun di klien Anda. Jika Anda membangun sendiri percobaan ulang dari Haijun Fable 5.1, Haijun Fable 5, Haijun Opus 5.5, atau Haijun Opus 5, kredit fallback menjelaskan cara menghindari membayar biaya cache prompt dua kali.
model\_context\_window\_exceeded
Haijun berhenti karena mencapai batas "context window" (jendela konteks) model. Ini memungkinkan Anda meminta token maksimum yang mungkin tanpa mengetahui ukuran input yang tepat.
Note: Alasan berhenti ini saat ini hanya memiliki tipe di namespace
betapada SDK, sehingga contoh-contoh berikut memanggilclient.beta.messages(csharp, go:client.Beta.Messages; java:client.beta().messages(); php:$client->beta->messages) dan menggunakan tipe berawalanBeta. Pada Sonnet 4.5 dan model yang lebih baru, API mengembalikan nilai ini tanpa header beta. Untuk model yang lebih lama, tambahkan header betamodel-context-window-exceeded-2025-08-26untuk mengaktifkannya.
curl https://haijun.my.id/v1/messages \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "haijun-opus-5-5",
"max_tokens": 20000,
"messages": [{"role": "user", "content": "Large input that uses most of context window..."}]
}' | jq '.stop_reason' ant messages create \
--model haijun-opus-5-5 \
--max-tokens 20000 \
--message '{role: user, content: "Large input that uses most of context window..."}' \
--format json | jq '.stop_reason' # Permintaan dengan token maksimum untuk mendapatkan hasil sebanyak mungkin
response = client.beta.messages.create(
model="haijun-opus-5-5",
max_tokens=20000, # Python SDK requires streaming for max_tokens above ~21k
messages=[
{"role": "user", "content": "Large input that uses most of context window..."}
],
)
if response.stop_reason == "model_context_window_exceeded":
# Respons mencapai batas jendela konteks sebelum max_tokens
print("Response reached model's context window limit")
# Respons tetap valid tetapi dibatasi oleh jendela konteks // Permintaan dengan token maksimum untuk mendapatkan hasil sebanyak mungkin
const response = await client.beta.messages.create({
model: "haijun-opus-5-5",
max_tokens: 20000,
messages: [{ role: "user", content: "Large input that uses most of context window..." }]
});
if (response.stop_reason === "model_context_window_exceeded") {
// Respons mencapai batas jendela konteks sebelum max_tokens
console.log("Response reached model's context window limit");
// Respons tetap valid tetapi dibatasi oleh jendela konteks
} using Juglow.Models.Beta.Messages;
using Model = Juglow.Models.Messages.Model;
// Permintaan dengan token maksimum untuk mendapatkan hasil sebanyak mungkin
var response = await client.Beta.Messages.Create(new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 20000,
Messages = [new() { Role = Role.User, Content = "Large input that uses most of context window..." }]
});
if (response.StopReason?.Value() == BetaStopReason.ModelContextWindowExceeded)
{
// Respons mencapai batas jendela konteks sebelum max_tokens
Console.WriteLine("Response reached model's context window limit");
// Respons tetap valid tetapi dibatasi oleh jendela konteks
} // Permintaan dengan token maksimum untuk mendapatkan hasil sebanyak mungkin
response, err := client.Beta.Messages.New(context.TODO(), juglow.BetaMessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 20000,
Messages: []juglow.BetaMessageParam{
juglow.NewBetaUserMessage(juglow.NewBetaTextBlock("Large input that uses most of context window...")),
},
})
if err != nil {
log.Fatal(err)
}
if response.StopReason == juglow.BetaStopReasonModelContextWindowExceeded {
// Respons mencapai batas jendela konteks sebelum max_tokens
fmt.Println("Response reached model's context window limit")
// Respons tetap valid tetapi dibatasi oleh jendela konteks
} import com.juglow.models.beta.messages.BetaMessage;
import com.juglow.models.beta.messages.BetaStopReason;
import com.juglow.models.beta.messages.MessageCreateParams;
// Permintaan dengan token maksimum untuk mendapatkan hasil sebanyak mungkin
BetaMessage response = client.beta().messages().create(
MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(20000L)
.addUserMessage("Large input that uses most of context window...")
.build()
);
if (response.stopReason().map(BetaStopReason.MODEL_CONTEXT_WINDOW_EXCEEDED::equals).orElse(false)) {
// Respons mencapai batas jendela konteks sebelum max_tokens
IO.println("Response reached model's context window limit");
// Respons tetap valid tetapi dibatasi oleh jendela konteks
} // Permintaan dengan token maksimum untuk mendapatkan hasil sebanyak mungkin
$response = $client->beta->messages->create(
maxTokens: 20000,
messages: [['role' => 'user', 'content' => 'Large input that uses most of context window...']],
model: 'haijun-opus-5-5',
);
if ($response->stopReason === 'model_context_window_exceeded') {
// Respons mencapai batas jendela konteks sebelum max_tokens
echo 'Response reached model\'s context window limit', PHP_EOL;
// Respons tetap valid tetapi dibatasi oleh jendela konteks
} # Permintaan dengan token maksimum untuk mendapatkan hasil sebanyak mungkin
response = client.beta.messages.create(
model: "haijun-opus-5-5",
max_tokens: 20000,
messages: [{ role: "user", content: "Large input that uses most of context window..." }]
)
if response.stop_reason == :model_context_window_exceeded
# Respons mencapai batas jendela konteks sebelum max_tokens
puts "Response reached model's context window limit"
# Respons tetap valid tetapi dibatasi oleh jendela konteks
endPraktik terbaik untuk menangani alasan berhenti
Selalu periksa stop\_reason
Biasakan untuk memeriksa stop_reason dalam logika penanganan respons Anda:
def handle_response(response):
match response.stop_reason:
case "tool_use":
return handle_tool_use(response)
case "max_tokens":
return handle_truncation(response)
case "model_context_window_exceeded":
return handle_context_limit(response)
case "pause_turn":
return handle_pause(response)
case "refusal":
return handle_refusal(response)
case _:
# Tangani end_turn dan kasus lainnya
return next(
(block.text for block in response.content if block.type == "text"),
"",
) function handleResponse(response: Juglow.Beta.BetaMessage): string {
switch (response.stop_reason) {
case "tool_use":
return handleToolUse(response);
case "max_tokens":
return handleTruncation(response);
case "model_context_window_exceeded":
return handleContextLimit(response);
case "pause_turn":
return handlePause(response);
case "refusal":
return handleRefusal(response);
default: {
// Tangani end_turn dan kasus lainnya
const textBlock = response.content.find(
(block): block is Juglow.Beta.BetaTextBlock => block.type === "text"
);
return textBlock?.text ?? "";
}
}
} static string HandleResponse(BetaMessage response)
{
return response.StopReason?.Value() switch
{
BetaStopReason.ToolUse => HandleToolUse(response),
BetaStopReason.MaxTokens => HandleTruncation(response),
BetaStopReason.ModelContextWindowExceeded => HandleContextLimit(response),
BetaStopReason.PauseTurn => HandlePause(response),
BetaStopReason.Refusal => HandleRefusal(response),
// Tangani end_turn dan kasus lainnya
_ => response.Content.Select(b => b.Value).OfType<BetaTextBlock>().FirstOrDefault()?.Text ?? "",
};
} func handleResponse(response *juglow.BetaMessage) string {
switch response.StopReason {
case juglow.BetaStopReasonToolUse:
return handleToolUse(response)
case juglow.BetaStopReasonMaxTokens:
return handleTruncation(response)
case juglow.BetaStopReasonModelContextWindowExceeded:
return handleContextLimit(response)
case juglow.BetaStopReasonPauseTurn:
return handlePause(response)
case juglow.BetaStopReasonRefusal:
return handleRefusal(response)
default:
// Tangani end_turn dan kasus lainnya
for _, block := range response.Content {
if textBlock, ok := block.AsAny().(juglow.BetaTextBlock); ok {
return textBlock.Text
}
}
return ""
}
} static String handleResponse(BetaMessage response) {
BetaStopReason reason = response.stopReason().orElse(BetaStopReason.END_TURN);
if (reason.equals(BetaStopReason.TOOL_USE)) {
return handleToolUse(response);
} else if (reason.equals(BetaStopReason.MAX_TOKENS)) {
return handleTruncation(response);
} else if (reason.equals(BetaStopReason.MODEL_CONTEXT_WINDOW_EXCEEDED)) {
return handleContextLimit(response);
} else if (reason.equals(BetaStopReason.PAUSE_TURN)) {
return handlePause(response);
} else if (reason.equals(BetaStopReason.REFUSAL)) {
return handleRefusal(response);
}
// Tangani end_turn dan kasus lainnya
return response.content().stream()
.filter(BetaContentBlock::isText)
.findFirst()
.map(block -> block.asText().text())
.orElse("");
} function handle_response($response): string
{
return match ($response->stopReason) {
'tool_use' => handle_tool_use($response),
'max_tokens' => handle_truncation($response),
'model_context_window_exceeded' => handle_context_limit($response),
'pause_turn' => handle_pause($response),
'refusal' => handle_refusal($response),
// Tangani end_turn dan kasus lainnya
default => array_find($response->content, static fn ($block): bool => $block->type === 'text')?->text ?? '',
};
} def handle_response(response)
case response.stop_reason
when :tool_use then handle_tool_use(response)
when :max_tokens then handle_truncation(response)
when :model_context_window_exceeded then handle_context_limit(response)
when :pause_turn then handle_pause(response)
when :refusal then handle_refusal(response)
else
# Tangani end_turn dan kasus lainnya
response.content.find { it.type == :text }&.text
end
endTangani respons terpotong dengan baik
Ketika respons terpotong karena batas token atau jendela konteks, tambahkan pemberitahuan agar pembaca tahu bahwa output tidak lengkap. Untuk melanjutkan pembuatan dari titik respons terhenti, lihat Memastikan respons lengkap.
def handle_truncated_response(response):
text = next((block.text for block in response.content if block.type == "text"), "")
if response.stop_reason in ["max_tokens", "model_context_window_exceeded"]:
if response.stop_reason == "max_tokens":
note = "[Response truncated due to max_tokens limit]"
else:
note = "[Response truncated due to context window limit]"
return f"{text}\n\n{note}"
return text function handleTruncatedResponse(response: Juglow.Beta.BetaMessage): string {
const textBlock = response.content.find(
(block): block is Juglow.Beta.BetaTextBlock => block.type === "text"
);
const text = textBlock?.text ?? "";
if (
response.stop_reason === "max_tokens" ||
response.stop_reason === "model_context_window_exceeded"
) {
const note =
response.stop_reason === "max_tokens"
? "[Response truncated due to max_tokens limit]"
: "[Response truncated due to context window limit]";
return `${text}\n\n${note}`;
}
return text;
} static string HandleTruncatedResponse(BetaMessage response)
{
var text = response.Content.Select(b => b.Value).OfType<BetaTextBlock>().FirstOrDefault()?.Text ?? "";
var reason = response.StopReason?.Value();
if (reason is BetaStopReason.MaxTokens or BetaStopReason.ModelContextWindowExceeded)
{
var note = reason == BetaStopReason.MaxTokens
? "[Response truncated due to max_tokens limit]"
: "[Response truncated due to context window limit]";
return $"{text}\n\n{note}";
}
return text;
} func handleTruncatedResponse(response *juglow.BetaMessage) string {
text := ""
for _, block := range response.Content {
if textBlock, ok := block.AsAny().(juglow.BetaTextBlock); ok {
text = textBlock.Text
break
}
}
if response.StopReason == juglow.BetaStopReasonMaxTokens ||
response.StopReason == juglow.BetaStopReasonModelContextWindowExceeded {
note := "[Response truncated due to context window limit]"
if response.StopReason == juglow.BetaStopReasonMaxTokens {
note = "[Response truncated due to max_tokens limit]"
}
return text + "\n\n" + note
}
return text
} static String handleTruncatedResponse(BetaMessage response) {
String text = response.content().stream()
.filter(BetaContentBlock::isText)
.findFirst()
.map(block -> block.asText().text())
.orElse("");
BetaStopReason reason = response.stopReason().orElse(BetaStopReason.END_TURN);
if (reason.equals(BetaStopReason.MAX_TOKENS)
|| reason.equals(BetaStopReason.MODEL_CONTEXT_WINDOW_EXCEEDED)) {
String note = reason.equals(BetaStopReason.MAX_TOKENS)
? "[Response truncated due to max_tokens limit]"
: "[Response truncated due to context window limit]";
return text + "\n\n" + note;
}
return text;
} function handle_truncated_response($response): string
{
$text = array_find($response->content, static fn ($block): bool => $block->type === 'text')?->text ?? '';
if (in_array($response->stopReason, ['max_tokens', 'model_context_window_exceeded'], true)) {
$note = $response->stopReason === 'max_tokens'
? '[Response truncated due to max_tokens limit]'
: '[Response truncated due to context window limit]';
return "{$text}\n\n{$note}";
}
return $text;
} def handle_truncated_response(response)
text = response.content.find { it.type == :text }&.text
if [:max_tokens, :model_context_window_exceeded].include?(response.stop_reason)
note = if response.stop_reason == :max_tokens
"[Response truncated due to max_tokens limit]"
else
"[Response truncated due to context window limit]"
end
return "#{text}\n\n#{note}"
end
text
endImplementasikan logika percobaan ulang untuk pause\_turn
Saat menggunakan alat server, API dapat mengembalikan pause_turn jika loop sampling sisi server mencapai batas iterasinya (default 10). Tangani ini dengan melanjutkan percakapan:
def handle_server_tool_conversation(client, user_query, tools, max_continuations=5):
"""
Handle server tool conversations that may require multiple continuations.
The server runs a sampling loop when executing server tools. If the loop
reaches its iteration limit, the API returns pause_turn. Continue the
conversation by sending the response back to let Haijun finish.
"""
messages = [{"role": "user", "content": user_query}]
for _ in range(max_continuations):
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=4096,
messages=messages,
tools=tools,
)
if response.stop_reason != "pause_turn":
# Haijun selesai memproses - kembalikan respons akhir
return response
# pause_turn: ganti seluruh daftar pesan agar peran tetap bergantian
messages = [
{"role": "user", "content": user_query},
{"role": "assistant", "content": response.content},
]
# Batas maksimum kelanjutan tercapai - kembalikan respons terakhir
return response async function handleServerToolConversation(
client: Juglow,
userQuery: string,
tools: Juglow.ToolUnion[],
maxContinuations = 5
): Promise<Juglow.Message> {
let messages: Juglow.MessageParam[] = [{ role: "user", content: userQuery }];
let response: Juglow.Message;
for (let i = 0; i < maxContinuations; i++) {
response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096,
messages,
tools
});
if (response.stop_reason !== "pause_turn") {
// Haijun selesai memproses - kembalikan respons akhir
return response;
}
// pause_turn: ganti seluruh daftar pesan agar peran tetap bergantian
messages = [
{ role: "user", content: userQuery },
{ role: "assistant", content: response.content }
];
}
// Batas maksimum kelanjutan tercapai - kembalikan respons terakhir
return response!;
} static async Task<Message> HandleServerToolConversation(
JuglowClient client,
string userQuery,
List<ToolUnion> tools,
int maxContinuations = 5)
{
List<MessageParam> messages = [new() { Role = Role.User, Content = userQuery }];
Message response = null!;
for (var i = 0; i < maxContinuations; i++)
{
response = await client.Messages.Create(new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 4096,
Messages = messages,
Tools = tools
});
if (response.StopReason != "pause_turn")
{
// Haijun selesai memproses - kembalikan respons akhir
return response;
}
// pause_turn: ganti seluruh daftar pesan agar peran tetap bergantian
messages =
[
new() { Role = Role.User, Content = userQuery },
new()
{
Role = Role.Assistant,
Content = response.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
}
];
}
// Batas maksimum kelanjutan tercapai - kembalikan respons terakhir
return response;
} func handleServerToolConversation(
client juglow.Client,
userQuery string,
tools []juglow.ToolUnionParam,
maxContinuations int,
) (*juglow.Message, error) {
messages := []juglow.MessageParam{juglow.NewUserMessage(juglow.NewTextBlock(userQuery))}
var response *juglow.Message
var err error
for range maxContinuations {
response, err = client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 4096,
Messages: messages,
Tools: tools,
})
if err != nil {
return nil, err
}
if response.StopReason != "pause_turn" {
// Haijun selesai memproses - kembalikan respons akhir
return response, nil
}
// pause_turn: ganti seluruh daftar pesan agar peran tetap bergantian
var contentParams []juglow.ContentBlockParamUnion
for _, block := range response.Content {
contentParams = append(contentParams, block.ToParam())
}
messages = []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock(userQuery)),
juglow.NewAssistantMessage(contentParams...),
}
}
// Batas maksimum kelanjutan tercapai - kembalikan respons terakhir
return response, nil
} static Message handleServerToolConversation(
JuglowClient client,
String userQuery,
List<Tool> tools,
int maxContinuations
) {
Message response = null;
for (int i = 0; i < maxContinuations; i++) {
// Bangun ulang params di setiap iterasi agar pesan tidak menumpuk
MessageCreateParams.Builder params = MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L)
.addUserMessage(userQuery);
tools.forEach(params::addTool);
if (response != null) {
params.addMessage(response);
}
response = client.messages().create(params.build());
if (!response.stopReason().map(StopReason.PAUSE_TURN::equals).orElse(false)) {
// Haijun selesai memproses - kembalikan respons akhir
return response;
}
// pause_turn: ulangi loop dan kirim kembali responsnya
}
// Batas maksimum kelanjutan tercapai - kembalikan respons terakhir
return response;
} function handle_server_tool_conversation(
Client $client,
string $userQuery,
array $tools,
int $maxContinuations = 5
) {
$messages = [['role' => 'user', 'content' => $userQuery]];
$response = null;
for ($i = 0; $i < $maxContinuations; $i++) {
$response = $client->messages->create(
maxTokens: 4096,
messages: $messages,
model: 'haijun-opus-5-5',
tools: $tools,
);
if ($response->stopReason !== 'pause_turn') {
// Haijun selesai memproses - kembalikan respons akhir
return $response;
}
// pause_turn: ganti seluruh daftar pesan agar peran tetap bergantian
$messages = [
['role' => 'user', 'content' => $userQuery],
['role' => 'assistant', 'content' => $response->content],
];
}
// Batas maksimum kelanjutan tercapai - kembalikan respons terakhir
return $response;
} def handle_server_tool_conversation(client, user_query, tools, max_continuations: 5)
messages = [{ role: "user", content: user_query }]
response = nil
max_continuations.times do
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
messages: messages,
tools: tools
)
# Haijun selesai memproses - kembalikan respons akhir
return response unless response.stop_reason == :pause_turn
# pause_turn: ganti seluruh daftar pesan agar peran tetap bergantian
messages = [
{ role: "user", content: user_query },
{ role: "assistant", content: response.content }
]
end
# Batas maksimum kelanjutan tercapai - kembalikan respons terakhir
response
endAlasan berhenti vs. error
Penting untuk membedakan antara nilai stop_reason dan error yang sebenarnya:
Alasan berhenti (respons berhasil)
- Bagian dari body respons
- Menunjukkan mengapa pembuatan berhenti secara normal
- Respons berisi konten yang valid
Error (permintaan gagal)
- Kode status HTTP 4xx atau 5xx
- Menunjukkan kegagalan pemrosesan permintaan
- Respons berisi detail error
# cURL keluar dengan kode non-nol pada error HTTP jika memakai --fail-with-body; periksa
# $? untuk error dan stop_reason untuk respons yang berhasil.
curl --fail-with-body -sS https://haijun.my.id/v1/messages \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "haijun-opus-5-5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Hello!"}]
}' | jq '.stop_reason' # CLI keluar dengan kode non-nol saat terjadi error API; stop_reason muncul jika berhasil.
ant messages create \
--model haijun-opus-5-5 \
--max-tokens 1024 \
--message '{role: user, content: "Hello!"}' \
--format json | jq '.stop_reason' client = juglow.Juglow()
try:
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
)
# Tangani respons yang berhasil dengan stop_reason
if response.stop_reason == "max_tokens":
print("Response was truncated")
except juglow.APIStatusError as e:
# Tangani error yang sebenarnya
match e.status_code:
case 429:
print("Rate limit exceeded")
case 500:
print("Server error") const client = new Juglow();
try {
const response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello!" }]
});
// Tangani respons yang berhasil dengan stop_reason
if (response.stop_reason === "max_tokens") {
console.log("Response was truncated");
}
} catch (err) {
// Tangani error yang sebenarnya
if (err instanceof Juglow.APIError) {
switch (err.status) {
case 429:
console.log("Rate limit exceeded");
break;
case 500:
console.log("Server error");
break;
}
} else {
throw err;
}
} JuglowClient client = new();
try
{
var response = await client.Messages.Create(new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 1024,
Messages = [new() { Role = Role.User, Content = "Hello!" }]
});
// Tangani respons yang berhasil dengan stop_reason
if (response.StopReason == "max_tokens")
{
Console.WriteLine("Response was truncated");
}
}
catch (JuglowRateLimitException)
{
// Tangani error yang sebenarnya
Console.WriteLine("Rate limit exceeded");
}
catch (Juglow5xxException)
{
Console.WriteLine("Server error");
} client := juglow.NewClient()
response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 1024,
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Hello!")),
},
})
if err != nil {
// Tangani error yang sebenarnya
var apiErr *juglow.Error
if errors.As(err, &apiErr) {
switch apiErr.StatusCode {
case 429:
fmt.Println("Rate limit exceeded")
case 500:
fmt.Println("Server error")
}
}
log.Fatal(err)
}
// Tangani respons sukses dengan stop_reason
if response.StopReason == "max_tokens" {
fmt.Println("Response was truncated")
} JuglowClient client = JuglowOkHttpClient.fromEnv();
try {
Message response = client.messages().create(
MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(1024L)
.addUserMessage("Hello!")
.build()
);
// Tangani respons yang berhasil dengan stop_reason
if (response.stopReason().map(StopReason.MAX_TOKENS::equals).orElse(false)) {
IO.println("Response was truncated");
}
} catch (RateLimitException e) {
// Tangani error yang sebenarnya
IO.println("Rate limit exceeded");
} catch (JuglowServiceException e) {
if (e.statusCode() == 500) {
IO.println("Server error");
}
} $client = new Client();
try {
$response = $client->messages->create(
maxTokens: 1024,
messages: [['role' => 'user', 'content' => 'Hello!']],
model: 'haijun-opus-5-5',
);
// Tangani respons yang berhasil dengan stop_reason
if ($response->stopReason === 'max_tokens') {
echo 'Response was truncated', PHP_EOL;
}
} catch (RateLimitException $e) {
// Tangani error yang sebenarnya
echo 'Rate limit exceeded', PHP_EOL;
} catch (InternalServerException $e) {
echo 'Server error', PHP_EOL;
} client = Juglow::Client.new
begin
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello!" }]
)
# Tangani respons yang berhasil dengan stop_reason
if response.stop_reason == :max_tokens
puts "Response was truncated"
end
rescue Juglow::Errors::RateLimitError
# Tangani error yang sebenarnya
puts "Rate limit exceeded"
rescue Juglow::Errors::APIStatusError => e
puts "Server error" if e.status == 500
endPertimbangan streaming
Saat menggunakan streaming, stop_reason:
- Bernilai
nulldalam eventmessage_startawal
- Disediakan dalam event
message_delta
- Tidak disediakan dalam event lainnya
# Event message_delta dalam stream SSE membawa stop_reason.
curl --no-buffer https://haijun.my.id/v1/messages \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "haijun-opus-5-5",
"max_tokens": 1024,
"stream": true,
"messages": [{"role": "user", "content": "Hello!"}]
}' # stop_reason muncul di event message_delta.
ant messages create --stream --format jsonl \
--model haijun-opus-5-5 \
--max-tokens 1024 \
--message '{role: user, content: "Hello!"}' |
jq -c 'select(.type == "message_delta") | .delta.stop_reason' client = juglow.Juglow()
with client.messages.stream(
model="haijun-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
) as stream:
for event in stream:
if event.type == "message_delta":
stop_reason = event.delta.stop_reason
if stop_reason:
print(f"Stream ended with: {stop_reason}") const client = new Juglow();
const stream = client.messages.stream({
model: "haijun-opus-5-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello!" }]
});
for await (const event of stream) {
if (event.type === "message_delta" && event.delta.stop_reason) {
console.log(`Stream ended with: ${event.delta.stop_reason}`);
}
} JuglowClient client = new();
var parameters = new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 1024,
Messages = [new() { Role = Role.User, Content = "Hello!" }]
};
await foreach (var streamEvent in client.Messages.CreateStreaming(parameters))
{
switch (streamEvent.Value)
{
case RawMessageDeltaEvent deltaEvent when deltaEvent.Delta.StopReason is not null:
Console.WriteLine($"Stream ended with: {deltaEvent.Delta.StopReason}");
break;
}
} client := juglow.NewClient()
stream := client.Messages.NewStreaming(context.TODO(), juglow.MessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 1024,
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Hello!")),
},
})
// Akumulasikan event ke dalam Message akhir, yang membawa stop_reason.
message := juglow.Message{}
for stream.Next() {
if err := message.Accumulate(stream.Current()); err != nil {
log.Fatal(err)
}
}
if err := stream.Err(); err != nil {
log.Fatal(err)
}
if message.StopReason != "" {
fmt.Printf("Stream ended with: %s\n", message.StopReason)
} JuglowClient client = JuglowOkHttpClient.fromEnv();
MessageCreateParams params = MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(1024L)
.addUserMessage("Hello!")
.build();
// Kumpulkan event ke dalam Message akhir, yang memuat stop_reason.
MessageAccumulator accumulator = MessageAccumulator.create();
try (StreamResponse<RawMessageStreamEvent> streamResponse =
client.messages().createStreaming(params)) {
streamResponse.stream().forEach(accumulator::accumulate);
}
accumulator.message().stopReason().ifPresent(stopReason ->
IO.println("Stream ended with: " + stopReason)
); $client = new Client();
$stream = $client->messages->createStream(
maxTokens: 1024,
messages: [['role' => 'user', 'content' => 'Hello!']],
model: 'haijun-opus-5-5',
);
foreach ($stream as $event) {
if ($event instanceof \Juglow\Messages\RawMessageDeltaEvent && $event->delta->stopReason !== null) {
echo "Stream ended with: {$event->delta->stopReason}", PHP_EOL;
}
} client = Juglow::Client.new
stream = client.messages.stream(
model: "haijun-opus-5-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello!" }]
)
stream.each do |event|
next unless event.type == :message_delta
stop_reason = event.delta.stop_reason
puts "Stream ended with: #{stop_reason}" if stop_reason
endPola umum
Menangani alur kerja penggunaan alat
Tip: Lebih sederhana dengan tool runner: Contoh berikut menunjukkan penanganan alat secara manual. Untuk sebagian besar kasus penggunaan, tool runner secara otomatis menangani eksekusi alat dengan kode yang jauh lebih sedikit.
def complete_tool_workflow(client, user_query, tools):
messages = [{"role": "user", "content": user_query}]
while True:
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=1024,
messages=messages,
tools=tools,
)
if response.stop_reason == "tool_use":
# Jalankan alat dan lanjutkan
tool_results = execute_tools(response.content)
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})
else:
# Respons akhir
return response async function completeToolWorkflow(
client: Juglow,
userQuery: string,
tools: Juglow.ToolUnion[]
): Promise<Juglow.Message> {
const messages: Juglow.MessageParam[] = [{ role: "user", content: userQuery }];
while (true) {
const response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 1024,
messages,
tools
});
if (response.stop_reason === "tool_use") {
// Jalankan alat dan lanjutkan
const toolResults = executeTools(response.content);
messages.push({ role: "assistant", content: response.content });
messages.push({ role: "user", content: toolResults });
} else {
// Respons akhir
return response;
}
}
} static async Task<Message> CompleteToolWorkflow(
JuglowClient client,
string userQuery,
List<ToolUnion> tools)
{
List<MessageParam> messages = [new() { Role = Role.User, Content = userQuery }];
while (true)
{
var response = await client.Messages.Create(new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 1024,
Messages = messages,
Tools = tools
});
if (response.StopReason == "tool_use")
{
// Jalankan alat dan lanjutkan
var toolResults = ExecuteTools(response.Content);
messages.Add(new()
{
Role = Role.Assistant,
Content = response.Content.Select(block => new ContentBlockParam(block.Json)).ToList()
});
messages.Add(new() { Role = Role.User, Content = toolResults });
}
else
{
// Respons akhir
return response;
}
}
} func completeToolWorkflow(
client juglow.Client,
userQuery string,
tools []juglow.ToolUnionParam,
) (*juglow.Message, error) {
messages := []juglow.MessageParam{juglow.NewUserMessage(juglow.NewTextBlock(userQuery))}
for {
response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 1024,
Messages: messages,
Tools: tools,
})
if err != nil {
return nil, err
}
if response.StopReason != "tool_use" {
// Respons akhir
return response, nil
}
// Jalankan alat dan lanjutkan
toolResults := executeTools(response.Content)
var contentParams []juglow.ContentBlockParamUnion
for _, block := range response.Content {
contentParams = append(contentParams, block.ToParam())
}
messages = append(messages, juglow.NewAssistantMessage(contentParams...))
messages = append(messages, juglow.NewUserMessage(toolResults...))
}
} static Message completeToolWorkflow(
JuglowClient client,
String userQuery,
List<Tool> tools
) {
List<MessageParam> messages = new ArrayList<>();
messages.add(MessageParam.builder().role(MessageParam.Role.USER).content(userQuery).build());
while (true) {
MessageCreateParams.Builder params = MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(1024L)
.messages(messages);
tools.forEach(params::addTool);
Message response = client.messages().create(params.build());
if (!response.stopReason().map(StopReason.TOOL_USE::equals).orElse(false)) {
// Respons akhir
return response;
}
// Jalankan alat dan lanjutkan
List<ToolResultBlockParam> toolResults = executeTools(response.content());
messages.add(response.toParam());
messages.add(MessageParam.builder()
.role(MessageParam.Role.USER)
.contentOfBlockParams(toolResults.stream().map(ContentBlockParam::ofToolResult).toList())
.build());
}
} function complete_tool_workflow(Client $client, string $userQuery, array $tools)
{
$messages = [['role' => 'user', 'content' => $userQuery]];
while (true) {
$response = $client->messages->create(
maxTokens: 1024,
messages: $messages,
model: 'haijun-opus-5-5',
tools: $tools,
);
if ($response->stopReason !== 'tool_use') {
// Respons akhir
return $response;
}
// Jalankan alat dan lanjutkan
$toolResults = execute_tools($response->content);
$messages[] = ['role' => 'assistant', 'content' => $response->content];
$messages[] = ['role' => 'user', 'content' => $toolResults];
}
} def complete_tool_workflow(client, user_query, tools)
messages = [{ role: "user", content: user_query }]
loop do
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 1024,
messages: messages,
tools: tools
)
# Respons akhir
return response unless response.stop_reason == :tool_use
# Jalankan alat dan lanjutkan
tool_results = execute_tools(response.content)
messages << { role: "assistant", content: response.content }
messages << { role: "user", content: tool_results }
end
endMemastikan respons lengkap
def get_complete_response(client, prompt, max_attempts=3):
messages = [{"role": "user", "content": prompt}]
full_response = ""
for _ in range(max_attempts):
response = client.messages.create(
model="haijun-opus-5-5", messages=messages, max_tokens=4096
)
full_response += next(
(block.text for block in response.content if block.type == "text"), ""
)
if response.stop_reason != "max_tokens":
break
# Lanjutkan dari titik terakhir berhenti
messages = [
{"role": "user", "content": prompt},
{"role": "assistant", "content": full_response},
{"role": "user", "content": "Please continue from where you left off."},
]
return full_response async function getCompleteResponse(
client: Juglow,
prompt: string,
maxAttempts = 3
): Promise<string> {
let messages: Juglow.MessageParam[] = [{ role: "user", content: prompt }];
let fullResponse = "";
for (let i = 0; i < maxAttempts; i++) {
const response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096,
messages
});
const textBlock = response.content.find(
(block): block is Juglow.TextBlock => block.type === "text"
);
fullResponse += textBlock?.text ?? "";
if (response.stop_reason !== "max_tokens") {
break;
}
// Lanjutkan dari titik terakhir yang ditinggalkan
messages = [
{ role: "user", content: prompt },
{ role: "assistant", content: fullResponse },
{ role: "user", content: "Please continue from where you left off." }
];
}
return fullResponse;
} static async Task<string> GetCompleteResponse(JuglowClient client, string prompt, int maxAttempts = 3)
{
List<MessageParam> messages = [new() { Role = Role.User, Content = prompt }];
var fullResponse = "";
for (var i = 0; i < maxAttempts; i++)
{
var response = await client.Messages.Create(new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 4096,
Messages = messages
});
foreach (var block in response.Content)
{
if (block.TryPickText(out var textBlock))
{
fullResponse += textBlock.Text;
break;
}
}
if (response.StopReason != "max_tokens")
{
break;
}
// Lanjutkan dari titik terakhir yang ditinggalkan
messages =
[
new() { Role = Role.User, Content = prompt },
new() { Role = Role.Assistant, Content = fullResponse },
new() { Role = Role.User, Content = "Please continue from where you left off." }
];
}
return fullResponse;
} func getCompleteResponse(client juglow.Client, prompt string, maxAttempts int) (string, error) {
messages := []juglow.MessageParam{juglow.NewUserMessage(juglow.NewTextBlock(prompt))}
fullResponse := ""
for range maxAttempts {
response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 4096,
Messages: messages,
})
if err != nil {
return "", err
}
for _, block := range response.Content {
if textBlock, ok := block.AsAny().(juglow.TextBlock); ok {
fullResponse += textBlock.Text
break
}
}
if response.StopReason != "max_tokens" {
break
}
// Lanjutkan dari titik terakhir yang ditinggalkan
messages = []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock(prompt)),
juglow.NewAssistantMessage(juglow.NewTextBlock(fullResponse)),
juglow.NewUserMessage(juglow.NewTextBlock("Please continue from where you left off.")),
}
}
return fullResponse, nil
} static String getCompleteResponse(JuglowClient client, String prompt, int maxAttempts) {
List<MessageParam> messages = List.of(
MessageParam.builder().role(MessageParam.Role.USER).content(prompt).build()
);
StringBuilder fullResponse = new StringBuilder();
for (int i = 0; i < maxAttempts; i++) {
Message response = client.messages().create(
MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L)
.messages(messages)
.build()
);
response.content().stream()
.filter(ContentBlock::isText)
.findFirst()
.ifPresent(block -> fullResponse.append(block.asText().text()));
if (!response.stopReason().map(StopReason.MAX_TOKENS::equals).orElse(false)) {
break;
}
// Lanjutkan dari titik terakhir yang ditinggalkan
messages = List.of(
MessageParam.builder().role(MessageParam.Role.USER).content(prompt).build(),
MessageParam.builder().role(MessageParam.Role.ASSISTANT).content(fullResponse.toString()).build(),
MessageParam.builder().role(MessageParam.Role.USER).content("Please continue from where you left off.").build()
);
}
return fullResponse.toString();
} function get_complete_response(Client $client, string $prompt, int $maxAttempts = 3): string
{
$messages = [['role' => 'user', 'content' => $prompt]];
$fullResponse = '';
for ($i = 0; $i < $maxAttempts; $i++) {
$response = $client->messages->create(
maxTokens: 4096,
messages: $messages,
model: 'haijun-opus-5-5',
);
$fullResponse .= array_find($response->content, static fn ($block): bool => $block->type === 'text')?->text ?? '';
if ($response->stopReason !== 'max_tokens') {
break;
}
// Lanjutkan dari titik terakhir yang ditinggalkan
$messages = [
['role' => 'user', 'content' => $prompt],
['role' => 'assistant', 'content' => $fullResponse],
['role' => 'user', 'content' => 'Please continue from where you left off.'],
];
}
return $fullResponse;
} def get_complete_response(client, prompt, max_attempts: 3)
messages = [{ role: "user", content: prompt }]
full_response = +""
max_attempts.times do
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
messages: messages
)
full_response << response.content.find { it.type == :text }&.text.to_s
break unless response.stop_reason == :max_tokens
# Lanjutkan dari titik terakhir berhenti
messages = [
{ role: "user", content: prompt },
{ role: "assistant", content: full_response },
{ role: "user", content: "Please continue from where you left off." }
]
end
full_response
endMendapatkan token maksimum tanpa mengetahui ukuran input
Dengan alasan berhenti model_context_window_exceeded, Anda dapat meminta token maksimum yang mungkin tanpa menghitung ukuran input:
def get_max_possible_tokens(client, prompt):
"""
Get as many tokens as possible within the model's context window
without needing to calculate input token count
"""
response = client.beta.messages.create(
model="haijun-opus-5-5",
messages=[{"role": "user", "content": prompt}],
max_tokens=20000, # Python SDK requires streaming for max_tokens above ~21k
)
match response.stop_reason:
case "model_context_window_exceeded":
# Mendapat token maksimum yang dimungkinkan sesuai ukuran input
print(
f"Generated {response.usage.output_tokens} tokens (context limit reached)"
)
case "max_tokens":
# Mendapat token tepat sebanyak yang diminta
print(
f"Generated {response.usage.output_tokens} tokens (max_tokens reached)"
)
case _:
# Penyelesaian alami
print(
f"Generated {response.usage.output_tokens} tokens (natural completion)"
)
return next((block.text for block in response.content if block.type == "text"), "") async function getMaxPossibleTokens(client: Juglow, prompt: string): Promise<string> {
const response = await client.beta.messages.create({
model: "haijun-opus-5-5",
max_tokens: 20000,
messages: [{ role: "user", content: prompt }]
});
const tokens = response.usage.output_tokens;
switch (response.stop_reason) {
case "model_context_window_exceeded":
// Mendapatkan token maksimum yang dimungkinkan berdasarkan ukuran input
console.log(`Generated ${tokens} tokens (context limit reached)`);
break;
case "max_tokens":
// Mendapatkan token tepat sebanyak yang diminta
console.log(`Generated ${tokens} tokens (max_tokens reached)`);
break;
default:
// Penyelesaian alami
console.log(`Generated ${tokens} tokens (natural completion)`);
}
const textBlock = response.content.find(
(block): block is Juglow.Beta.BetaTextBlock => block.type === "text"
);
return textBlock?.text ?? "";
} using Juglow.Models.Beta.Messages;
using Model = Juglow.Models.Messages.Model;
static async Task<string> GetMaxPossibleTokens(JuglowClient client, string prompt)
{
var response = await client.Beta.Messages.Create(new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 20000,
Messages = [new() { Role = Role.User, Content = prompt }]
});
var tokens = response.Usage.OutputTokens;
var reason = response.StopReason?.Value();
if (reason == BetaStopReason.ModelContextWindowExceeded)
{
// Mendapatkan jumlah token maksimum yang dimungkinkan berdasarkan ukuran input
Console.WriteLine($"Generated {tokens} tokens (context limit reached)");
}
else if (reason == BetaStopReason.MaxTokens)
{
// Mendapatkan jumlah token persis seperti yang diminta
Console.WriteLine($"Generated {tokens} tokens (max_tokens reached)");
}
else
{
// Penyelesaian alami
Console.WriteLine($"Generated {tokens} tokens (natural completion)");
}
return response.Content.Select(b => b.Value).OfType<BetaTextBlock>().FirstOrDefault()?.Text ?? "";
} func getMaxPossibleTokens(client juglow.Client, prompt string) (string, error) {
response, err := client.Beta.Messages.New(context.TODO(), juglow.BetaMessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 20000,
Messages: []juglow.BetaMessageParam{
juglow.NewBetaUserMessage(juglow.NewBetaTextBlock(prompt)),
},
})
if err != nil {
return "", err
}
tokens := response.Usage.OutputTokens
switch response.StopReason {
case juglow.BetaStopReasonModelContextWindowExceeded:
// Mendapat token maksimum yang dimungkinkan berdasarkan ukuran input
fmt.Printf("Generated %d tokens (context limit reached)\n", tokens)
case juglow.BetaStopReasonMaxTokens:
// Mendapat token tepat sebanyak yang diminta
fmt.Printf("Generated %d tokens (max_tokens reached)\n", tokens)
default:
// Penyelesaian alami
fmt.Printf("Generated %d tokens (natural completion)\n", tokens)
}
for _, block := range response.Content {
if textBlock, ok := block.AsAny().(juglow.BetaTextBlock); ok {
return textBlock.Text, nil
}
}
return "", nil
} import com.juglow.models.beta.messages.BetaContentBlock;
import com.juglow.models.beta.messages.BetaMessage;
import com.juglow.models.beta.messages.BetaStopReason;
import com.juglow.models.beta.messages.MessageCreateParams;
static String getMaxPossibleTokens(JuglowClient client, String prompt) {
BetaMessage response = client.beta().messages().create(
MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(20000L)
.addUserMessage(prompt)
.build()
);
long tokens = response.usage().outputTokens();
BetaStopReason reason = response.stopReason().orElse(BetaStopReason.END_TURN);
if (reason.equals(BetaStopReason.MODEL_CONTEXT_WINDOW_EXCEEDED)) {
// Mendapatkan token maksimum yang dimungkinkan berdasarkan ukuran input
IO.println("Generated " + tokens + " tokens (context limit reached)");
} else if (reason.equals(BetaStopReason.MAX_TOKENS)) {
// Mendapatkan token tepat sebanyak yang diminta
IO.println("Generated " + tokens + " tokens (max_tokens reached)");
} else {
// Penyelesaian alami
IO.println("Generated " + tokens + " tokens (natural completion)");
}
return response.content().stream()
.filter(BetaContentBlock::isText)
.findFirst()
.map(block -> block.asText().text())
.orElse("");
} function get_max_possible_tokens(Client $client, string $prompt): string
{
$response = $client->beta->messages->create(
maxTokens: 20000,
messages: [['role' => 'user', 'content' => $prompt]],
model: 'haijun-opus-5-5',
);
$tokens = $response->usage->outputTokens;
echo match ($response->stopReason) {
// Mendapat token maksimum yang dimungkinkan sesuai ukuran input
'model_context_window_exceeded' => "Generated {$tokens} tokens (context limit reached)",
// Mendapat token tepat sesuai jumlah yang diminta
'max_tokens' => "Generated {$tokens} tokens (max_tokens reached)",
// Penyelesaian alami
default => "Generated {$tokens} tokens (natural completion)",
}, PHP_EOL;
return array_find($response->content, static fn ($block): bool => $block->type === 'text')?->text ?? '';
} def get_max_possible_tokens(client, prompt)
response = client.beta.messages.create(
model: "haijun-opus-5-5",
max_tokens: 20000,
messages: [{ role: "user", content: prompt }]
)
tokens = response.usage.output_tokens
case response.stop_reason
when :model_context_window_exceeded
# Mendapat token maksimum yang dimungkinkan sesuai ukuran input
puts "Generated #{tokens} tokens (context limit reached)"
when :max_tokens
# Mendapat token tepat sebanyak yang diminta
puts "Generated #{tokens} tokens (max_tokens reached)"
else
# Penyelesaian alami
puts "Generated #{tokens} tokens (natural completion)"
end
response.content.find { it.type == :text }.text
endLangkah selanjutnya
Coba ulang permintaan yang ditolak pada model fallback, di sisi server atau di klien Anda.
Biarkan SDK mengelola loop tool_use, pemformatan hasil, dan percobaan ulang untuk Anda.
Baca stop_reason dari event message_delta saat streaming.
Tangani error HTTP 4xx dan 5xx, yang berbeda dari alasan berhenti.