Agent Tracks memperluas kemampuan Haijun melalui folder terorganisir yang berisi instruksi, skrip, dan sumber daya. Panduan ini menunjukkan cara menggunakan Tracks bawaan maupun Tracks kustom dengan Haijun API.
Note: Untuk referensi API lengkap termasuk skema permintaan/respons dan semua parameter, lihat: * Referensi API Manajemen Track - Operasi CRUD untuk Tracks * Referensi API Versi Track - Manajemen versi
Note: Untuk mempelajari bagaimana "zero data retention" (retensi data nol), atau ZDR, berlaku untuk fitur ini, lihat API dan retensi data.
Tautan cepat
Pelajari cara menggunakan Agent Tracks untuk membuat dokumen dengan Haijun API dalam waktu kurang dari 10 menit.
Pelajari cara menulis Tracks yang efektif yang dapat ditemukan dan digunakan Haijun dengan sukses.
Ikhtisar
Note: Untuk pembahasan mendetail tentang arsitektur dan penerapan nyata Agent Tracks, baca postingan blog engineering: Equipping agents for the real world with Agent Tracks.
Tracks terintegrasi dengan Messages API melalui alat eksekusi kode. Baik menggunakan Tracks bawaan yang dikelola oleh Juglow maupun Tracks kustom yang Anda unggah, bentuk integrasinya identik: keduanya memerlukan eksekusi kode dan menggunakan struktur container yang sama.
Menggunakan Tracks
Tracks terintegrasi secara identik di Messages API terlepas dari sumbernya. Anda menentukan Tracks dalam parameter container dengan skill_id, type, dan version opsional, dan Tracks tersebut berjalan di lingkungan eksekusi kode.
Anda dapat menggunakan Tracks dari dua sumber:
| Aspek | Tracks Juglow | Tracks Kustom |
|---|---|---|
| Nilai type | juglow | custom |
| ID Track | Nama pendek: pptx, xlsx, docx, pdf | Dihasilkan otomatis: skill_01AbCdEfGhIjKlMnOpQrStUv |
| Format versi | Berbasis tanggal: 20251013 atau latest | ID versi: skver_01AbCdEfGhIjKlMnOpQrStUv atau latest |
| Manajemen | Bawaan dan dipelihara oleh Juglow | Unggah dan kelola melalui Tracks API |
| Ketersediaan | Tersedia untuk semua pengguna | Privat untuk workspace Anda |
Kedua sumber track dikembalikan oleh endpoint List Tracks (gunakan parameter source untuk memfilter). Bentuk integrasi dan lingkungan eksekusinya identik. Satu-satunya perbedaan adalah dari mana Tracks berasal dan bagaimana Tracks tersebut dikelola.
Prasyarat
Untuk menggunakan Tracks, Anda memerlukan:
- Kunci API Haijun dari Haijun Console
- Alat eksekusi kode diaktifkan dalam permintaan Anda
Tracks memerlukan alat eksekusi kode, jadi gunakan model dari daftar kompatibilitas model alat tersebut.
Menggunakan Tracks dalam Messages
Parameter container
Tracks ditentukan menggunakan parameter container di Messages API. Anda dapat menyertakan hingga 20 Tracks untuk setiap permintaan.
Strukturnya identik untuk Tracks Juglow maupun Tracks kustom. Tentukan type dan skill_id yang wajib, dan secara opsional sertakan version untuk mengunci ke versi tertentu:
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,
"container": {
"tracks": [
{
"type": "juglow",
"skill_id": "pptx",
"version": "latest"
}
]
},
"messages": [{
"role": "user",
"content": "Create a presentation about renewable energy"
}],
"tools": [{
"type": "code_execution_20250825",
"name": "code_execution"
}]
}' ant messages create <<'YAML'
model: haijun-opus-5-5
max_tokens: 4096
container:
tracks:
- type: juglow
skill_id: pptx
version: latest
messages:
- role: user
content: Create a presentation about renewable energy
tools:
- type: code_execution_20250825
name: code_execution
YAML client = juglow.Juglow()
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=4096,
container={
"tracks": [{"type": "juglow", "skill_id": "pptx", "version": "latest"}]
},
messages=[
{"role": "user", "content": "Create a presentation about renewable energy"}
],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
) const client = new Juglow();
const response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [
{
type: "juglow",
skill_id: "pptx",
version: "latest"
}
]
},
messages: [
{
role: "user",
content: "Create a presentation about renewable energy"
}
],
tools: [
{
type: "code_execution_20250825",
name: "code_execution"
}
]
}); JuglowClient client = new();
var parameters = new MessageCreateParams
{
Model = "haijun-opus-5-5",
MaxTokens = 4096,
Container = new ContainerParams
{
Tracks =
[
new SkillParams
{
Type = SkillParamsType.Juglow,
SkillID = "pptx",
Version = "latest",
},
],
},
Messages = [new() { Role = Role.User, Content = "Create a presentation about renewable energy" }],
Tools = [new CodeExecutionTool20250825()],
};
var message = await client.Messages.Create(parameters);
Console.WriteLine(message); client := juglow.NewClient()
response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: "haijun-opus-5-5",
MaxTokens: 4096,
Container: juglow.MessageCreateParamsContainerUnion{
OfContainers: &juglow.ContainerParams{
Tracks: []juglow.SkillParams{
{
Type: juglow.SkillParamsTypeJuglow,
SkillID: "pptx",
Version: juglow.String("latest"),
},
},
},
},
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Create a presentation about renewable energy")),
},
Tools: []juglow.ToolUnionParam{
{OfCodeExecutionTool20250825: &juglow.CodeExecutionTool20250825Param{}},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(response) import com.juglow.models.messages.ContainerParams;
import com.juglow.models.messages.SkillParams;
import com.juglow.models.messages.CodeExecutionTool20250825;
// ...
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
MessageCreateParams params = MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L)
.container(ContainerParams.builder()
.addSkill(SkillParams.builder()
.type(SkillParams.Type.JUGLOW)
.skillId("pptx")
.version("latest")
.build())
.build())
.addUserMessage("Create a presentation about renewable energy")
.addTool(CodeExecutionTool20250825.builder().build())
.build();
Message response = client.messages().create(params);
System.out.println(response);
} $client = new Client();
$message = $client->messages->create(
maxTokens: 4096,
messages: [
['role' => 'user', 'content' => 'Create a presentation about renewable energy']
],
model: 'haijun-opus-5-5',
container: [
'tracks' => [
[
'type' => 'juglow',
'skillID' => 'pptx',
'version' => 'latest'
]
]
],
tools: [
['type' => 'code_execution_20250825', 'name' => 'code_execution']
]
);
echo $message; client = Juglow::Client.new
message = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [
{
type: "juglow",
skill_id: "pptx",
version: "latest"
}
]
},
messages: [
{ role: "user", content: "Create a presentation about renewable energy" }
],
tools: [
{ type: "code_execution_20250825", name: "code_execution" }
]
)
puts messageMengunduh file yang dihasilkan
Ketika Tracks membuat dokumen (Excel, PowerPoint, PDF, Word), Tracks mengembalikan atribut file_id dalam respons. Anda harus menggunakan Files API untuk mengunduh file-file ini.
Cara kerjanya:
- Tracks membuat file selama eksekusi kode.
- Respons menyertakan
file_iduntuk setiap file yang dibuat, di dalam blok hasil alat eksekusi kode (lihat Format respons).
- Gunakan Files API untuk mengunduh konten file yang sebenarnya.
- Simpan secara lokal atau proses sesuai kebutuhan.
Untuk menyediakan file input yang akan dikerjakan oleh Tracks, unggah file tersebut dengan Files API dan referensikan dalam permintaan Anda dengan blok container upload.
Contoh: membuat dan mengunduh file Excel
# Langkah 1: Gunakan Track untuk membuat file
RESPONSE=$(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,
"container": {
"tracks": [
{"type": "juglow", "skill_id": "xlsx", "version": "latest"}
]
},
"messages": [{
"role": "user",
"content": "Create an Excel file with a simple budget spreadsheet"
}],
"tools": [{
"type": "code_execution_20250825",
"name": "code_execution"
}]
}')
# Langkah 2: Ekstrak file_id dari respons (menggunakan jq)
FILE_ID=$(echo "$RESPONSE" | jq -r '.content[] | select(.type=="bash_code_execution_tool_result") | .content | select(.type=="bash_code_execution_result") | .content[] | select(.file_id) | .file_id')
# Langkah 3: Dapatkan nama file dari metadata
FILENAME=$(curl "https://haijun.my.id/v1/files/$FILE_ID" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" | jq -r '.filename')
# Langkah 4: Unduh file menggunakan Files API
curl "https://haijun.my.id/v1/files/$FILE_ID/content" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
--output "$FILENAME"
echo "Downloaded: $FILENAME" # Langkah 1: Gunakan Track xlsx untuk membuat file
# Langkah 2: Ekstrak file_id dari respons dengan --transform (path GJSON)
FILE_ID=$(ant messages create \
--transform 'content.#.content.content.#.file_id|@flatten|0' \
--raw-output <<'YAML'
model: haijun-opus-5-5
max_tokens: 4096
container:
tracks:
- type: juglow
skill_id: xlsx
version: latest
messages:
- role: user
content: Create an Excel file with a simple budget spreadsheet
tools:
- type: code_execution_20250825
name: code_execution
YAML
)
# Langkah 3: Dapatkan nama file dari metadata file
FILENAME=$(ant files retrieve-metadata \
--file-id "$FILE_ID" \
--transform filename \
--raw-output)
# Langkah 4: Unduh file menggunakan Files API
ant files download --file-id "$FILE_ID" --output "$FILENAME" > /dev/null
printf 'Downloaded: %s\n' "$FILENAME" client = juglow.Juglow()
# Langkah 1: Gunakan Track untuk membuat file
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=4096,
container={
"tracks": [{"type": "juglow", "skill_id": "xlsx", "version": "latest"}]
},
messages=[
{
"role": "user",
"content": "Create an Excel file with a simple budget spreadsheet",
}
],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
# Langkah 2: Ekstrak ID file dari respons
def extract_file_ids(response):
file_ids = []
for item in response.content:
if item.type == "bash_code_execution_tool_result":
content_item = item.content
if content_item.type == "bash_code_execution_result":
# setiap item konten adalah blok bash_code_execution_output yang membawa file_id
for file in content_item.content:
file_ids.append(file.file_id)
return file_ids
# Langkah 3: Unduh file menggunakan Files API
for file_id in extract_file_ids(response):
file_metadata = client.files.retrieve_metadata(file_id=file_id)
file_content = client.files.download(file_id=file_id)
# Langkah 4: Simpan ke disk
file_content.write_to_file(file_metadata.filename)
print(f"Downloaded: {file_metadata.filename}") import { writeFile } from "node:fs/promises";
const client = new Juglow();
// Langkah 1: Gunakan Track untuk membuat file
const response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [{ type: "juglow", skill_id: "xlsx", version: "latest" }]
},
messages: [
{
role: "user",
content: "Create an Excel file with a simple budget spreadsheet"
}
],
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
});
// Langkah 2: Ekstrak ID file dari respons
const fileIds: string[] = [];
for (const block of response.content) {
if (
block.type === "bash_code_execution_tool_result" &&
block.content.type === "bash_code_execution_result"
) {
for (const outputBlock of block.content.content) {
fileIds.push(outputBlock.file_id);
}
}
}
// Langkah 3: Unduh setiap file dan simpan ke disk
for (const fileId of fileIds) {
const fileMetadata = await client.files.retrieveMetadata(fileId);
const fileResponse = await client.files.download(fileId);
await writeFile(fileMetadata.filename, Buffer.from(await fileResponse.arrayBuffer()));
console.log(`Downloaded: ${fileMetadata.filename}`);
} JuglowClient client = new();
// Langkah 1: Gunakan Track untuk membuat file
var parameters = new MessageCreateParams
{
Model = "haijun-opus-5-5",
MaxTokens = 4096,
Container = new ContainerParams
{
Tracks =
[
new SkillParams
{
Type = SkillParamsType.Juglow,
SkillID = "xlsx",
Version = "latest",
},
],
},
Messages = [new() { Role = Role.User, Content = "Create an Excel file with a simple budget spreadsheet" }],
Tools = [new CodeExecutionTool20250825()],
};
var response = await client.Messages.Create(parameters);
// Langkah 2: Ekstrak ID file dari respons
List<string> fileIds = [];
foreach (var block in response.Content)
{
if (block.TryPickBashCodeExecutionToolResult(out var toolResult)
&& toolResult.Content.TryPickBashCodeExecutionResultBlock(out var result))
{
foreach (var output in result.Content)
{
fileIds.Add(output.FileID);
}
}
}
// Langkah 3: Unduh setiap file dan simpan ke disk
foreach (var fileId in fileIds)
{
var fileMetadata = await client.Files.RetrieveMetadata(fileId);
using var download = await client.Files.Download(fileId);
using var downloadStream = await download.ReadAsStream();
using var outputFile = File.Create(fileMetadata.Filename);
await downloadStream.CopyToAsync(outputFile);
Console.WriteLine($"Downloaded: {fileMetadata.Filename}");
} func main() {
client := juglow.NewClient()
// Langkah 1: Gunakan Track untuk membuat file
response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: "haijun-opus-5-5",
MaxTokens: 4096,
Container: juglow.MessageCreateParamsContainerUnion{
OfContainers: &juglow.ContainerParams{
Tracks: []juglow.SkillParams{
{
Type: juglow.SkillParamsTypeJuglow,
SkillID: "xlsx",
Version: juglow.String("latest"),
},
},
},
},
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Create an Excel file with a simple budget spreadsheet")),
},
Tools: []juglow.ToolUnionParam{
{OfCodeExecutionTool20250825: &juglow.CodeExecutionTool20250825Param{}},
},
})
if err != nil {
log.Fatal(err)
}
// Langkah 2: Ekstrak ID file dari respons
fileIDs := extractFileIDs(response)
// Langkah 3: Unduh file menggunakan Files API
for _, fileID := range fileIDs {
fileMetadata, err := client.Files.GetMetadata(context.TODO(), fileID, juglow.FileGetMetadataParams{})
if err != nil {
log.Fatal(err)
}
fileContent, err := client.Files.Download(context.TODO(), fileID, juglow.FileDownloadParams{})
if err != nil {
log.Fatal(err)
}
// Langkah 4: Simpan ke disk
out, err := os.Create(fileMetadata.Filename)
if err != nil {
log.Fatal(err)
}
if _, err := io.Copy(out, fileContent.Body); err != nil {
log.Fatal(err)
}
out.Close()
fileContent.Body.Close()
fmt.Printf("Downloaded: %s\n", fileMetadata.Filename)
}
}
func extractFileIDs(response *juglow.Message) []string {
var fileIDs []string
for _, item := range response.Content {
switch v := item.AsAny().(type) {
case juglow.BashCodeExecutionToolResultBlock:
if v.Content.Type == "bash_code_execution_result" {
for _, output := range v.Content.Content {
fileIDs = append(fileIDs, output.FileID)
}
}
}
}
return fileIDs
} import com.juglow.models.messages.ContainerParams;
import com.juglow.models.messages.SkillParams;
import com.juglow.models.messages.CodeExecutionTool20250825;
import com.juglow.models.messages.ContentBlock;
import com.juglow.models.files.FileMetadata;
import com.juglow.core.http.HttpResponse;
// ...
void main() throws Exception {
JuglowClient client = JuglowOkHttpClient.fromEnv();
// Langkah 1: Gunakan Track untuk membuat file
MessageCreateParams params = MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L)
.container(ContainerParams.builder()
.addSkill(SkillParams.builder()
.type(SkillParams.Type.JUGLOW)
.skillId("xlsx")
.version("latest")
.build())
.build())
.addUserMessage("Create an Excel file with a simple budget spreadsheet")
.addTool(CodeExecutionTool20250825.builder().build())
.build();
Message response = client.messages().create(params);
// Langkah 2: Ekstrak ID file dari respons
List<String> fileIds = new ArrayList<>();
for (ContentBlock block : response.content()) {
if (block.isBashCodeExecutionToolResult()) {
var content = block.asBashCodeExecutionToolResult().content();
if (content.isBashCodeExecutionResultBlock()) {
for (var outputBlock : content.asBashCodeExecutionResultBlock().content()) {
fileIds.add(outputBlock.fileId());
}
}
}
}
// Langkah 3: Unduh file menggunakan Files API
for (String fileId : fileIds) {
FileMetadata fileMetadata = client.files().retrieveMetadata(fileId);
HttpResponse fileContent = client.files().download(fileId);
// Langkah 4: Simpan ke disk
try (InputStream is = fileContent.body();
FileOutputStream fos = new FileOutputStream(fileMetadata.filename())) {
is.transferTo(fos);
}
System.out.println("Downloaded: " + fileMetadata.filename());
}
} $client = new Client();
// Langkah 1: Gunakan Track untuk membuat file
$response = $client->messages->create(
maxTokens: 4096,
messages: [
['role' => 'user', 'content' => 'Create an Excel file with a simple budget spreadsheet']
],
model: 'haijun-opus-5-5',
container: [
'tracks' => [
['type' => 'juglow', 'skillID' => 'xlsx', 'version' => 'latest']
]
],
tools: [
['type' => 'code_execution_20250825', 'name' => 'code_execution']
]
);
// Langkah 2: Ekstrak ID file dari respons
function extractFileIds($response) {
$fileIds = [];
foreach ($response->content as $item) {
if ($item->type === 'bash_code_execution_tool_result') {
$contentItem = $item->content;
if ($contentItem->type === 'bash_code_execution_result') {
foreach ($contentItem->content as $file) {
$fileIds[] = $file->fileID;
}
}
}
}
return $fileIds;
}
// Langkah 3: Unduh file menggunakan Files API
foreach (extractFileIds($response) as $fileId) {
$fileMetadata = $client->files->retrieveMetadata($fileId);
$fileContent = $client->files->download($fileId);
// Langkah 4: Simpan ke disk
file_put_contents($fileMetadata->filename, $fileContent);
echo "Downloaded: {$fileMetadata->filename}\n";
} client = Juglow::Client.new
# Langkah 1: Gunakan Track untuk membuat file
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [{ type: "juglow", skill_id: "xlsx", version: "latest" }]
},
messages: [
{
role: "user",
content: "Create an Excel file with a simple budget spreadsheet"
}
],
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
)
# Langkah 2: Ekstrak ID file dari respons
def extract_file_ids(response)
file_ids = []
response.content.each do |item|
if item.type == :bash_code_execution_tool_result
content_item = item.content
if content_item.type == :bash_code_execution_result
content_item.content.each do |file|
file_ids << file.file_id
end
end
end
end
file_ids
end
# Langkah 3: Unduh file menggunakan Files API
extract_file_ids(response).each do |file_id|
file_metadata = client.files.retrieve_metadata(file_id)
file_content = client.files.download(file_id)
# Langkah 4: Simpan ke disk
File.binwrite(file_metadata.filename, file_content.read)
puts "Downloaded: #{file_metadata.filename}"
endOperasi Files API tambahan:
# Dapatkan metadata file
curl "https://haijun.my.id/v1/files/$FILE_ID" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01"
# Daftar semua file
curl "https://haijun.my.id/v1/files" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01"
# Hapus file
curl -X DELETE "https://haijun.my.id/v1/files/$FILE_ID" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" # Dapatkan metadata file
ant files retrieve-metadata \
--file-id "$FILE_ID" \
--transform '{filename,size_bytes}' \
--format yaml
# Daftar semua file
ant files list --transform '{filename,created_at}' --format yaml
# Hapus file
ant files delete --file-id "$FILE_ID" >/dev/null client = juglow.Juglow()
file_id = "file_011CNha8iCJcU1wXNR6q4V8w"
# Dapatkan metadata file
file_info = client.files.retrieve_metadata(file_id=file_id)
print(f"Filename: {file_info.filename}, Size: {file_info.size_bytes} bytes")
# Daftar semua file
for file in client.files.list():
print(f"{file.filename} - {file.created_at}")
# Hapus file
client.files.delete(file_id=file_id) const client = new Juglow();
const fileId = "file_011CNha8iCJcU1wXNR6q4V8w";
// Ambil metadata file
const fileInfo = await client.files.retrieveMetadata(fileId);
console.log(`Filename: ${fileInfo.filename}, Size: ${fileInfo.size_bytes} bytes`);
// Daftar semua file
for await (const file of client.files.list()) {
console.log(`${file.filename} - ${file.created_at}`);
}
// Hapus file
await client.files.delete(fileId); JuglowClient client = new();
var fileId = "file_011CNha8iCJcU1wXNR6q4V8w";
// Dapatkan metadata file
var fileInfo = await client.Files.RetrieveMetadata(fileId);
Console.WriteLine($"Filename: {fileInfo.Filename}, Size: {fileInfo.SizeBytes} bytes");
// Daftar file
await foreach (var file in (await client.Files.List()).Paginate())
{
Console.WriteLine($"{file.Filename} - {file.CreatedAt}");
}
// Hapus file
await client.Files.Delete(fileId); client := juglow.NewClient()
fileID := "file_011CNha8iCJcU1wXNR6q4V8w"
// Dapatkan metadata file
fileInfo, err := client.Files.GetMetadata(context.TODO(), fileID, juglow.FileGetMetadataParams{})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Filename: %s, Size: %d bytes\n", fileInfo.Filename, fileInfo.SizeBytes)
// Tampilkan daftar semua file
files := client.Files.ListAutoPaging(context.TODO(), juglow.FileListParams{})
for files.Next() {
file := files.Current()
fmt.Printf("%s - %s\n", file.Filename, file.CreatedAt)
}
if files.Err() != nil {
log.Fatal(files.Err())
}
// Hapus file
_, err = client.Files.Delete(context.TODO(), fileID, juglow.FileDeleteParams{})
if err != nil {
log.Fatal(err)
} import com.juglow.models.files.FileMetadata;
import com.juglow.models.files.FileListPage;
// ...
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
String fileId = "file_011CNha8iCJcU1wXNR6q4V8w";
// Dapatkan metadata file
FileMetadata fileInfo = client.files().retrieveMetadata(fileId);
System.out.println("Filename: " + fileInfo.filename() + ", Size: " + fileInfo.sizeBytes() + " bytes");
// Daftar file (halaman pertama)
FileListPage files = client.files().list();
for (var file : files.data()) {
System.out.println(file.filename() + " - " + file.createdAt());
}
// Hapus file
client.files().delete(fileId);
} $client = new Client();
$fileId = 'file_011CNha8iCJcU1wXNR6q4V8w';
// Ambil metadata file
$fileInfo = $client->files->retrieveMetadata($fileId);
echo "Filename: {$fileInfo->filename}, Size: {$fileInfo->sizeBytes} bytes\n";
// Daftar file (halaman pertama)
foreach ($client->files->list()->getItems() as $file) {
echo "{$file->filename} - {$file->createdAt->format(DATE_ATOM)}\n";
}
// Hapus file
$client->files->delete($fileId); client = Juglow::Client.new
file_id = "file_011CNha8iCJcU1wXNR6q4V8w"
# Dapatkan metadata file
file_info = client.files.retrieve_metadata(file_id)
puts "Filename: #{file_info.filename}, Size: #{file_info.size_bytes} bytes"
# Daftar semua file
client.files.list.auto_paging_each do |file|
puts "#{file.filename} - #{file.created_at}"
end
# Hapus file
client.files.delete(file_id)Note: Untuk detail lengkap, lihat Files API.
Percakapan multi-giliran
Objek container pada respons membawa id container dan timestamp expires_at (lihat Penggunaan ulang container untuk detail masa berlaku). Gunakan kembali container yang sama di beberapa pesan dengan menentukan ID container:
# Penggunaan ulang container multi-turn kurang cocok untuk perintah shell
# sekali jalan; salah satu opsi SDK akan lebih sesuai. Ambil
# container.id dari respons pertama, lalu teruskan di permintaan berikutnya sebagai
# "container": {"id": "...", "tracks": [...]} beserta riwayat percakapan. # Permintaan pertama membuat container
CONTAINER_ID=$(ant messages create \
--transform container.id \
--raw-output <<'YAML'
model: haijun-opus-5-5
max_tokens: 4096
container:
tracks:
- {type: juglow, skill_id: xlsx, version: latest}
messages:
- role: user
content: Create a sample sales dataset and analyze it
tools:
- {type: code_execution_20250825, name: code_execution}
YAML
)
# Lanjutkan percakapan dengan container yang sama
ant messages create <<YAML
model: haijun-opus-5-5
max_tokens: 4096
container:
id: $CONTAINER_ID # Reuse container
tracks:
- {type: juglow, skill_id: xlsx, version: latest}
messages:
- role: user
content: Create a sample sales dataset and analyze it
- role: assistant
content: [] # the assistant's text from the first response
- role: user
content: What was the total revenue?
tools:
- {type: code_execution_20250825, name: code_execution}
YAML client = juglow.Juglow()
# Permintaan pertama membuat container
response1 = client.messages.create(
model="haijun-opus-5-5",
max_tokens=4096,
container={
"tracks": [{"type": "juglow", "skill_id": "xlsx", "version": "latest"}]
},
messages=[
{"role": "user", "content": "Create a sample sales dataset and analyze it"}
],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
# Lanjutkan percakapan dengan container yang sama
messages = [
{"role": "user", "content": "Create a sample sales dataset and analyze it"},
{
# Teruskan teks asisten; container.id membawa status eksekusi
"role": "assistant",
"content": "\n".join(
block.text for block in response1.content if block.type == "text"
),
},
{"role": "user", "content": "What was the total revenue?"},
]
response2 = client.messages.create(
model="haijun-opus-5-5",
max_tokens=4096,
container={
"id": response1.container.id, # Reuse container
"tracks": [{"type": "juglow", "skill_id": "xlsx", "version": "latest"}],
},
messages=messages,
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
) const client = new Juglow();
// Permintaan pertama membuat container
const response1 = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [{ type: "juglow", skill_id: "xlsx", version: "latest" }]
},
messages: [{ role: "user", content: "Create a sample sales dataset and analyze it" }],
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
});
// Lanjutkan percakapan dengan container yang sama
const messages: Juglow.MessageParam[] = [
{ role: "user", content: "Create a sample sales dataset and analyze it" },
{
role: "assistant",
// Teruskan teks asisten; container.id membawa status eksekusi
content: response1.content
.filter((block) => block.type === "text")
.map((block) => block.text)
.join("\n")
},
{ role: "user", content: "What was the total revenue?" }
];
const response2 = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
id: response1.container!.id, // Reuse container
tracks: [{ type: "juglow", skill_id: "xlsx", version: "latest" }]
},
messages,
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
}); JuglowClient client = new();
// Permintaan pertama dengan Track
var parameters1 = new MessageCreateParams
{
Model = "haijun-opus-5-5",
MaxTokens = 4096,
Container = new ContainerParams
{
Tracks =
[
new SkillParams
{
Type = SkillParamsType.Juglow,
SkillID = "xlsx",
Version = "latest",
},
],
},
Messages = [new() { Role = Role.User, Content = "Create a sample sales dataset and analyze it" }],
Tools = [new CodeExecutionTool20250825()],
};
var response1 = await client.Messages.Create(parameters1);
// Lanjutkan percakapan dalam container yang sama
// Teruskan teks asisten; container.id membawa status eksekusi
var assistantText = string.Join(
"\n",
response1.Content.Select(block => block.TryPickText(out var text) ? text.Text : null).Where(text => text is not null)
);
var parameters2 = new MessageCreateParams
{
Model = "haijun-opus-5-5",
MaxTokens = 4096,
Container = new ContainerParams
{
ID = response1.Container!.ID,
Tracks =
[
new SkillParams
{
Type = SkillParamsType.Juglow,
SkillID = "xlsx",
Version = "latest",
},
],
},
Messages =
[
new() { Role = Role.User, Content = "Create a sample sales dataset and analyze it" },
new() { Role = Role.Assistant, Content = assistantText },
new() { Role = Role.User, Content = "What was the total revenue?" },
],
Tools = [new CodeExecutionTool20250825()],
};
var response2 = await client.Messages.Create(parameters2);
Console.WriteLine(response2); client := juglow.NewClient()
response1, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: "haijun-opus-5-5",
MaxTokens: 4096,
Container: juglow.MessageCreateParamsContainerUnion{
OfContainers: &juglow.ContainerParams{
Tracks: []juglow.SkillParams{
{
Type: juglow.SkillParamsTypeJuglow,
SkillID: "xlsx",
Version: juglow.String("latest"),
},
},
},
},
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Create a sample sales dataset and analyze it")),
},
Tools: []juglow.ToolUnionParam{
{OfCodeExecutionTool20250825: &juglow.CodeExecutionTool20250825Param{}},
},
})
if err != nil {
log.Fatal(err)
}
// Teruskan teks asisten; container.id membawa status eksekusi
var textParts []string
for _, block := range response1.Content {
if block.Type == "text" {
textParts = append(textParts, block.Text)
}
}
assistantText := strings.Join(textParts, "\n")
response2, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: "haijun-opus-5-5",
MaxTokens: 4096,
Container: juglow.MessageCreateParamsContainerUnion{
OfContainers: &juglow.ContainerParams{
ID: juglow.String(response1.Container.ID), // Reuse container
Tracks: []juglow.SkillParams{
{
Type: juglow.SkillParamsTypeJuglow,
SkillID: "xlsx",
Version: juglow.String("latest"),
},
},
},
},
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Create a sample sales dataset and analyze it")),
{
Role: juglow.MessageParamRoleAssistant,
Content: []juglow.ContentBlockParamUnion{juglow.NewTextBlock(assistantText)},
},
juglow.NewUserMessage(juglow.NewTextBlock("What was the total revenue?")),
},
Tools: []juglow.ToolUnionParam{
{OfCodeExecutionTool20250825: &juglow.CodeExecutionTool20250825Param{}},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(response2) import com.juglow.models.messages.ContainerParams;
import com.juglow.models.messages.SkillParams;
import com.juglow.models.messages.CodeExecutionTool20250825;
import com.juglow.models.messages.ContentBlock;
// ...
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
MessageCreateParams params1 = MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L)
.container(ContainerParams.builder()
.addSkill(SkillParams.builder()
.type(SkillParams.Type.JUGLOW)
.skillId("xlsx")
.version("latest")
.build())
.build())
.addUserMessage("Create a sample sales dataset and analyze it")
.addTool(CodeExecutionTool20250825.builder().build())
.build();
Message response1 = client.messages().create(params1);
MessageCreateParams params2 = MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L)
.container(ContainerParams.builder()
.id(response1.container().get().id())
.addSkill(SkillParams.builder()
.type(SkillParams.Type.JUGLOW)
.skillId("xlsx")
.version("latest")
.build())
.build())
.addUserMessage("Create a sample sales dataset and analyze it")
// Teruskan teks asisten; container.id membawa status eksekusi
.addAssistantMessage(response1.content().stream()
.filter(ContentBlock::isText)
.map(block -> block.asText().text())
.collect(Collectors.joining("\n")))
.addUserMessage("What was the total revenue?")
.addTool(CodeExecutionTool20250825.builder().build())
.build();
Message response2 = client.messages().create(params2);
System.out.println(response2);
} $client = new Client();
$response1 = $client->messages->create(
maxTokens: 4096,
messages: [
['role' => 'user', 'content' => 'Create a sample sales dataset and analyze it']
],
model: 'haijun-opus-5-5',
container: [
'tracks' => [
['type' => 'juglow', 'skillID' => 'xlsx', 'version' => 'latest']
]
],
tools: [
['type' => 'code_execution_20250825', 'name' => 'code_execution']
]
);
$messages = [
['role' => 'user', 'content' => 'Create a sample sales dataset and analyze it'],
// Teruskan teks asisten; container.id membawa status eksekusi
['role' => 'assistant', 'content' => implode("\n", array_map(
fn ($block) => $block->text,
array_filter($response1->content, fn ($block) => $block->type === 'text'),
))],
['role' => 'user', 'content' => 'What was the total revenue?']
];
$response2 = $client->messages->create(
maxTokens: 4096,
messages: $messages,
model: 'haijun-opus-5-5',
container: [
'id' => $response1->container->id,
'tracks' => [
['type' => 'juglow', 'skillID' => 'xlsx', 'version' => 'latest']
]
],
tools: [
['type' => 'code_execution_20250825', 'name' => 'code_execution']
]
);
echo $response2; client = Juglow::Client.new
response1 = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [{ type: "juglow", skill_id: "xlsx", version: "latest" }]
},
messages: [
{ role: "user", content: "Create a sample sales dataset and analyze it" }
],
tools: [
{ type: "code_execution_20250825", name: "code_execution" }
]
)
messages = [
{ role: "user", content: "Create a sample sales dataset and analyze it" },
{
# Teruskan teks asisten; container.id membawa status eksekusi
role: "assistant",
content: response1.content.filter_map { |block| block.text if block.type == :text }.join("\n")
},
{ role: "user", content: "What was the total revenue?" }
]
response2 = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
id: response1.container.id,
tracks: [
{ type: "juglow", skill_id: "xlsx", version: "latest" }
]
},
messages: messages,
tools: [
{ type: "code_execution_20250825", name: "code_execution" }
]
)
puts response2Operasi yang berjalan lama
Tracks dapat melakukan operasi yang memerlukan beberapa giliran. Tangani stop reason pause_turn:
# Permintaan awal
RESPONSE=$(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,
"container": {
"tracks": [
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "latest"
}
]
},
"messages": [{
"role": "user",
"content": "Generate and process a large sample dataset"
}],
"tools": [{
"type": "code_execution_20250825",
"name": "code_execution"
}]
}')
# Jika stop_reason adalah "pause_turn", lanjutkan di container yang sama, dengan menambahkan
# array content dari respons sebelumnya ke messages sebagai giliran assistant.
# Ulangi permintaan lanjutan ini hingga stop_reason bukan lagi "pause_turn".
STOP_REASON=$(echo "$RESPONSE" | jq -r '.stop_reason')
CONTAINER_ID=$(echo "$RESPONSE" | jq -r '.container.id')
RESPONSE=$(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,
\"container\": {
\"id\": \"$CONTAINER_ID\",
\"tracks\": [{
\"type\": \"custom\",
\"skill_id\": \"skill_01AbCdEfGhIjKlMnOpQrStUv\",
\"version\": \"latest\"
}]
},
\"messages\": [],
\"tools\": [{
\"type\": \"code_execution_20250825\",
\"name\": \"code_execution\"
}]
}") RESP=$(mktemp)
# Permintaan awal: simpan respons JSON lengkap ke file sementara
ant messages create > "$RESP" <<'YAML'
model: haijun-opus-5-5
max_tokens: 4096
container:
tracks:
- type: custom
skill_id: skill_01AbCdEfGhIjKlMnOpQrStUv
version: latest
messages:
- role: user
content: Generate and process a large sample dataset
tools:
- type: code_execution_20250825
name: code_execution
YAML
# Jika stop_reason adalah "pause_turn", lanjutkan di container yang sama,
# dengan menambahkan array content dari respons sebelumnya ke messages sebagai
# giliran assistant. Ulangi hingga stop_reason bukan lagi "pause_turn".
CONTAINER_ID=$(jq -r '.container.id' "$RESP")
ant messages create > "$RESP" <<YAML
model: haijun-opus-5-5
max_tokens: 4096
container:
id: $CONTAINER_ID
tracks:
- type: custom
skill_id: skill_01AbCdEfGhIjKlMnOpQrStUv
version: latest
messages: [] # replace with conversation history + prior assistant content
tools:
- type: code_execution_20250825
name: code_execution
YAML client = juglow.Juglow()
messages = [{"role": "user", "content": "Generate and process a large sample dataset"}]
max_retries = 10
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=4096,
container={
"tracks": [
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "latest",
}
]
},
messages=messages,
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
# Tangani pause_turn untuk operasi yang berjalan lama
for _ in range(max_retries):
if response.stop_reason != "pause_turn":
break
messages.append({"role": "assistant", "content": response.content})
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=4096,
container={
"id": response.container.id,
"tracks": [
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "latest",
}
],
},
messages=messages,
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
) const client = new Juglow();
const messages: Juglow.MessageParam[] = [
{ role: "user", content: "Generate and process a large sample dataset" }
];
const maxRetries = 10;
let response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [{ type: "custom", skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv", version: "latest" }]
},
messages,
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
});
// Tangani pause_turn untuk operasi yang berjalan lama
for (let i = 0; i < maxRetries; i++) {
if (response.stop_reason !== "pause_turn") {
break;
}
messages.push({
role: "assistant",
content: response.content as Juglow.ContentBlockParam[]
});
response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
id: response.container!.id,
tracks: [
{ type: "custom", skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv", version: "latest" }
]
},
messages,
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
});
} using System.Text.Json;
// ...
JuglowClient client = new();
List<MessageParam> messages =
[
new() { Role = Role.User, Content = "Generate and process a large sample dataset" },
];
var maxRetries = 10;
string? containerId = null;
Message? response = null;
for (var i = 0; i < maxRetries; i++)
{
var parameters = new MessageCreateParams
{
Model = "haijun-opus-5-5",
MaxTokens = 4096,
Container = containerId is null
? new ContainerParams
{
Tracks =
[
new SkillParams
{
Type = SkillParamsType.Custom,
SkillID = "skill_01AbCdEfGhIjKlMnOpQrStUv",
Version = "latest",
},
],
}
: new ContainerParams
{
ID = containerId,
Tracks =
[
new SkillParams
{
Type = SkillParamsType.Custom,
SkillID = "skill_01AbCdEfGhIjKlMnOpQrStUv",
Version = "latest",
},
],
},
Messages = messages,
Tools = [new CodeExecutionTool20250825()],
};
response = await client.Messages.Create(parameters);
containerId = response.Container!.ID;
if (response.StopReason != StopReason.PauseTurn)
{
break;
}
// Tambahkan konten giliran yang dijeda, lalu lanjutkan
var assistantContent = JsonSerializer.SerializeToElement(
response.Content.Select(block => block.Json).ToArray()
);
messages.Add(new() { Role = Role.Assistant, Content = new MessageParamContent(assistantContent) });
} client := juglow.NewClient()
messages := []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Generate and process a large sample dataset")),
}
maxRetries := 10
response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: "haijun-opus-5-5",
MaxTokens: 4096,
Container: juglow.MessageCreateParamsContainerUnion{
OfContainers: &juglow.ContainerParams{
Tracks: []juglow.SkillParams{
{
Type: juglow.SkillParamsTypeCustom,
SkillID: "skill_01AbCdEfGhIjKlMnOpQrStUv",
Version: juglow.String("latest"),
},
},
},
},
Messages: messages,
Tools: []juglow.ToolUnionParam{
{OfCodeExecutionTool20250825: &juglow.CodeExecutionTool20250825Param{}},
},
})
if err != nil {
log.Fatal(err)
}
for i := 0; i < maxRetries; i++ {
if response.StopReason != juglow.StopReasonPauseTurn {
break
}
messages = append(messages, response.ToParam())
response, err = client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: "haijun-opus-5-5",
MaxTokens: 4096,
Container: juglow.MessageCreateParamsContainerUnion{
OfContainers: &juglow.ContainerParams{
ID: juglow.String(response.Container.ID), // Reuse container
Tracks: []juglow.SkillParams{
{
Type: juglow.SkillParamsTypeCustom,
SkillID: "skill_01AbCdEfGhIjKlMnOpQrStUv",
Version: juglow.String("latest"),
},
},
},
},
Messages: messages,
Tools: []juglow.ToolUnionParam{
{OfCodeExecutionTool20250825: &juglow.CodeExecutionTool20250825Param{}},
},
})
if err != nil {
log.Fatal(err)
}
}
fmt.Println(response) import com.juglow.models.messages.ContainerParams;
import com.juglow.models.messages.SkillParams;
import com.juglow.models.messages.CodeExecutionTool20250825;
import com.juglow.models.messages.StopReason;
// ...
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
List<MessageParam> messages = new ArrayList<>();
messages.add(
MessageParam.builder()
.role(MessageParam.Role.USER)
.content("Generate and process a large sample dataset")
.build()
);
int maxRetries = 10;
Message response = client.messages().create(
MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L)
.container(ContainerParams.builder()
.addSkill(SkillParams.builder()
.type(SkillParams.Type.CUSTOM)
.skillId("skill_01AbCdEfGhIjKlMnOpQrStUv")
.version("latest")
.build())
.build())
.messages(messages)
.addTool(CodeExecutionTool20250825.builder().build())
.build());
for (int i = 0; i < maxRetries; i++) {
if (!response.stopReason().isPresent()
|| !response.stopReason().get().equals(StopReason.PAUSE_TURN)) {
break;
}
messages.add(response.toParam());
response = client.messages().create(
MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L)
.container(ContainerParams.builder()
.id(response.container().get().id())
.addSkill(SkillParams.builder()
.type(SkillParams.Type.CUSTOM)
.skillId("skill_01AbCdEfGhIjKlMnOpQrStUv")
.version("latest")
.build())
.build())
.messages(messages)
.addTool(CodeExecutionTool20250825.builder().build())
.build());
}
} $client = new Client();
$messages = [
['role' => 'user', 'content' => 'Generate and process a large sample dataset']
];
$maxRetries = 10;
$response = $client->messages->create(
maxTokens: 4096,
messages: $messages,
model: 'haijun-opus-5-5',
container: [
'tracks' => [
[
'type' => 'custom',
'skillID' => 'skill_01AbCdEfGhIjKlMnOpQrStUv',
'version' => 'latest'
]
]
],
tools: [['type' => 'code_execution_20250825', 'name' => 'code_execution']]
);
for ($i = 0; $i < $maxRetries; $i++) {
if ($response->stopReason !== 'pause_turn') {
break;
}
$messages[] = ['role' => 'assistant', 'content' => $response->content];
$response = $client->messages->create(
maxTokens: 4096,
messages: $messages,
model: 'haijun-opus-5-5',
container: [
'id' => $response->container->id,
'tracks' => [
[
'type' => 'custom',
'skillID' => 'skill_01AbCdEfGhIjKlMnOpQrStUv',
'version' => 'latest'
]
]
],
tools: [['type' => 'code_execution_20250825', 'name' => 'code_execution']]
);
} client = Juglow::Client.new
messages = [
{ role: "user", content: "Generate and process a large sample dataset" }
]
max_retries = 10
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [
{
type: "custom",
skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv",
version: "latest"
}
]
},
messages: messages,
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
)
max_retries.times do
break if response.stop_reason != :pause_turn
messages << { role: "assistant", content: response.content }
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
id: response.container.id,
tracks: [
{
type: "custom",
skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv",
version: "latest"
}
]
},
messages: messages,
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
)
endNote: Respons dapat menyertakan stop reason
pause_turn, yang menunjukkan bahwa API menjeda operasi Track yang berjalan lama. Anda dapat memberikan respons tersebut kembali apa adanya dalam permintaan berikutnya agar Haijun melanjutkan gilirannya, atau memodifikasi kontennya jika Anda ingin menginterupsi percakapan dan memberikan panduan tambahan.
Menggunakan beberapa Tracks
Gabungkan beberapa Tracks dalam satu permintaan untuk menangani alur kerja yang kompleks:
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,
"container": {
"tracks": [
{
"type": "juglow",
"skill_id": "xlsx",
"version": "latest"
},
{
"type": "juglow",
"skill_id": "pptx",
"version": "latest"
},
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "latest"
}
]
},
"messages": [{
"role": "user",
"content": "Analyze sales data and create a presentation"
}],
"tools": [{
"type": "code_execution_20250825",
"name": "code_execution"
}]
}' ant messages create <<'YAML'
model: haijun-opus-5-5
max_tokens: 4096
container:
tracks:
- type: juglow
skill_id: xlsx
version: latest
- type: juglow
skill_id: pptx
version: latest
- type: custom
skill_id: skill_01AbCdEfGhIjKlMnOpQrStUv
version: latest
messages:
- role: user
content: Analyze sales data and create a presentation
tools:
- type: code_execution_20250825
name: code_execution
YAML client = juglow.Juglow()
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=4096,
container={
"tracks": [
{"type": "juglow", "skill_id": "xlsx", "version": "latest"},
{"type": "juglow", "skill_id": "pptx", "version": "latest"},
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "latest",
},
]
},
messages=[
{"role": "user", "content": "Analyze sales data and create a presentation"}
],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
) const client = new Juglow();
const response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [
{
type: "juglow",
skill_id: "xlsx",
version: "latest"
},
{
type: "juglow",
skill_id: "pptx",
version: "latest"
},
{
type: "custom",
skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv",
version: "latest"
}
]
},
messages: [
{
role: "user",
content: "Analyze sales data and create a presentation"
}
],
tools: [
{
type: "code_execution_20250825",
name: "code_execution"
}
]
}); JuglowClient client = new();
var parameters = new MessageCreateParams
{
Model = "haijun-opus-5-5",
MaxTokens = 4096,
Container = new ContainerParams
{
Tracks =
[
new SkillParams
{
Type = SkillParamsType.Juglow,
SkillID = "xlsx",
Version = "latest",
},
new SkillParams
{
Type = SkillParamsType.Juglow,
SkillID = "pptx",
Version = "latest",
},
new SkillParams
{
Type = SkillParamsType.Custom,
SkillID = "skill_01AbCdEfGhIjKlMnOpQrStUv",
Version = "latest",
},
],
},
Messages = [new() { Role = Role.User, Content = "Analyze sales data and create a presentation" }],
Tools = [new CodeExecutionTool20250825()],
};
var message = await client.Messages.Create(parameters);
Console.WriteLine(message); client := juglow.NewClient()
response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: "haijun-opus-5-5",
MaxTokens: 4096,
Container: juglow.MessageCreateParamsContainerUnion{
OfContainers: &juglow.ContainerParams{
Tracks: []juglow.SkillParams{
{
Type: juglow.SkillParamsTypeJuglow,
SkillID: "xlsx",
Version: juglow.String("latest"),
},
{
Type: juglow.SkillParamsTypeJuglow,
SkillID: "pptx",
Version: juglow.String("latest"),
},
{
Type: juglow.SkillParamsTypeCustom,
SkillID: "skill_01AbCdEfGhIjKlMnOpQrStUv",
Version: juglow.String("latest"),
},
},
},
},
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Analyze sales data and create a presentation")),
},
Tools: []juglow.ToolUnionParam{
{OfCodeExecutionTool20250825: &juglow.CodeExecutionTool20250825Param{}},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(response) import com.juglow.models.messages.ContainerParams;
import com.juglow.models.messages.SkillParams;
import com.juglow.models.messages.CodeExecutionTool20250825;
// ...
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
MessageCreateParams params = MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L)
.container(ContainerParams.builder()
.tracks(List.of(
SkillParams.builder()
.type(SkillParams.Type.JUGLOW)
.skillId("xlsx")
.version("latest")
.build(),
SkillParams.builder()
.type(SkillParams.Type.JUGLOW)
.skillId("pptx")
.version("latest")
.build(),
SkillParams.builder()
.type(SkillParams.Type.CUSTOM)
.skillId("skill_01AbCdEfGhIjKlMnOpQrStUv")
.version("latest")
.build()
))
.build())
.addUserMessage("Analyze sales data and create a presentation")
.addTool(CodeExecutionTool20250825.builder().build())
.build();
Message response = client.messages().create(params);
System.out.println(response);
} $client = new Client();
$message = $client->messages->create(
maxTokens: 4096,
messages: [
['role' => 'user', 'content' => 'Analyze sales data and create a presentation']
],
model: 'haijun-opus-5-5',
container: [
'tracks' => [
[
'type' => 'juglow',
'skillID' => 'xlsx',
'version' => 'latest'
],
[
'type' => 'juglow',
'skillID' => 'pptx',
'version' => 'latest'
],
[
'type' => 'custom',
'skillID' => 'skill_01AbCdEfGhIjKlMnOpQrStUv',
'version' => 'latest'
]
]
],
tools: [
['type' => 'code_execution_20250825', 'name' => 'code_execution']
]
);
echo $message; client = Juglow::Client.new
message = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [
{
type: "juglow",
skill_id: "xlsx",
version: "latest"
},
{
type: "juglow",
skill_id: "pptx",
version: "latest"
},
{
type: "custom",
skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv",
version: "latest"
}
]
},
messages: [
{ role: "user", content: "Analyze sales data and create a presentation" }
],
tools: [
{ type: "code_execution_20250825", name: "code_execution" }
]
)
puts messageMengelola Tracks kustom
Warning: Tracks kustom dapat diakses oleh seluruh workspace Anda, tidak dibatasi pada pengguna akhir, percakapan, atau sesi tertentu. Kunci API apa pun yang memiliki akses ke suatu workspace dapat membaca, memanggil, dan menghapus setiap Track kustom yang diunggah ke workspace tersebut. Setiap service account, dan setiap pengguna yang peran organisasinya mengizinkan akses API, dapat menggunakan Default Workspace selain workspace mana pun yang Anda tambahkan untuk mereka, jadi simpan Tracks yang harus tetap terpisah di workspace tersendiri dan akses hanya dengan kunci yang dibatasi pada workspace tersebut. Jika Anda membangun platform multi-tenant di atas Tracks API, buat workspace terpisah untuk setiap tenant. Workspace adalah batas isolasi untuk Tracks kustom, sehingga satu workspace per tenant memberikan isolasi ketat bagi Tracks setiap tenant dari semua tenant lainnya. Setiap organisasi dapat memiliki hingga 100 workspace secara default (lihat Cara kerja workspace); jika Anda memerlukan lebih banyak untuk isolasi tenant, hubungi tim akun Anda.
Membuat Track
Bundle Track adalah direktori yang berisi file SKILL.md di tingkat teratas dengan frontmatter YAML name dan description, ditambah skrip atau sumber daya pendukung apa pun. Lihat Memulai dengan Agent Tracks di API untuk menulisnya, dan daftar Persyaratan setelah contoh-contoh berikut untuk batasan lengkapnya.
Unggah Track kustom Anda agar tersedia di workspace Anda. Anda dapat mengunggah arsip zip atau objek file individual. Python SDK juga menyediakan helper files_from_dir yang menerima path direktori, dan ant apply pada CLI mengunggah direktori itu sendiri.
File diidentifikasi berdasarkan nama file yang Anda lampirkan (sufiks ;filename= dalam contoh cURL dan argumen nama file dalam contoh SDK). Untuk track dalam panduan ini, buat zip dengan zip -r financial_skill.zip financial_skill/ dan gunakan sebagai pengganti placeholder example_skill.zip dalam opsi unggah zip.
curl -X POST "https://haijun.my.id/v1/tracks" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-F "files[]=@financial_skill/SKILL.md;filename=financial_skill/SKILL.md" \
-F "files[]=@financial_skill/analyze.py;filename=financial_skill/analyze.py" ant apply financial_skill ---
name: financial-track
description: Docs example track.
--- print("financial analysis helper") from juglow.lib import files_from_dir
client = juglow.Juglow()
# Opsi 1: Menggunakan file zip
track = client.tracks.create(
files=[open("example_skill.zip", "rb")],
)
# Opsi 2: Menggunakan tuple file (filename, file_content, mime_type)
track = client.tracks.create(
files=[
(
"financial_skill/SKILL.md",
open("financial_skill/SKILL.md", "rb"),
"text/markdown",
),
(
"financial_skill/analyze.py",
open("financial_skill/analyze.py", "rb"),
"text/x-python",
),
],
)
# Opsi 3: Menggunakan helper files_from_dir (khusus Python)
track = client.tracks.create(
files=files_from_dir("financial_skill"),
)
print(f"Created track: {track.id}")
print(f"Latest version: {track.latest_version_id}") import { toFile } from "@juglow-ai/sdk";
import fs from "node:fs";
// ...
const client = new Juglow();
// Opsi 1: Menggunakan file zip
const skillFromZip = await client.tracks.create({
files: [await toFile(fs.createReadStream("example_skill.zip"), "example_skill.zip")]
});
// Opsi 2: Menggunakan objek file individual
const track = await client.tracks.create({
files: [
await toFile(fs.createReadStream("financial_skill/SKILL.md"), "financial_skill/SKILL.md", {
type: "text/markdown"
}),
await toFile(
fs.createReadStream("financial_skill/analyze.py"),
"financial_skill/analyze.py",
{ type: "text/x-python" }
)
]
});
console.log(`Created track: ${track.id}`);
console.log(`Latest version: ${track.latest_version_id}`); using Juglow.Core;
// ...
JuglowClient client = new();
// Opsi 1: Menggunakan file zip
var parameters = new SkillCreateParams
{
Files = [File.OpenRead("example_skill.zip")],
};
var track = await client.Tracks.Create(parameters);
// Opsi 2: Menggunakan file individual (nama file dengan path lengkap mempertahankan tata letak direktori Track)
var parameters2 = new SkillCreateParams
{
Files =
[
new BinaryContent
{
Stream = File.OpenRead("financial_skill/SKILL.md"),
FileName = "financial_skill/SKILL.md",
},
new BinaryContent
{
Stream = File.OpenRead("financial_skill/analyze.py"),
FileName = "financial_skill/analyze.py",
},
],
};
var skill2 = await client.Tracks.Create(parameters2);
Console.WriteLine($"Created track: {track.ID}");
Console.WriteLine($"Latest version: {track.LatestVersionID}");
Console.WriteLine($"Created track 2: {skill2.ID}"); client := juglow.NewClient()
// Opsi 1: Menggunakan file zip
zipFile, err := os.Open("example_skill.zip")
if err != nil {
log.Fatal(err)
}
defer zipFile.Close()
track, err := client.Tracks.New(context.TODO(), juglow.SkillNewParams{
Files: []io.Reader{zipFile},
})
if err != nil {
log.Fatal(err)
}
// Opsi 2: Menggunakan file individual
skillMd, err := os.Open("financial_skill/SKILL.md")
if err != nil {
log.Fatal(err)
}
defer skillMd.Close()
analyzePy, err := os.Open("financial_skill/analyze.py")
if err != nil {
log.Fatal(err)
}
defer analyzePy.Close()
skill2, err := client.Tracks.New(context.TODO(), juglow.SkillNewParams{
Files: []io.Reader{
juglow.File(skillMd, "financial_skill/SKILL.md", "text/markdown"),
juglow.File(analyzePy, "financial_skill/analyze.py", "text/x-python"),
},
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Created track: %s\n", track.ID)
fmt.Printf("Latest version: %s\n", track.LatestVersionID)
fmt.Printf("Created track 2: %s\n", skill2.ID) import com.juglow.core.MultipartField;
import com.juglow.models.tracks.SkillCreateParams;
import com.juglow.models.tracks.Track;
// ...
void main() throws Exception {
// ...
JuglowClient client = JuglowOkHttpClient.fromEnv();
// Opsi 1: Menggunakan file zip
SkillCreateParams params = SkillCreateParams.builder()
.addFile(MultipartField.<InputStream>builder()
.value(Files.newInputStream(Path.of("example_skill.zip")))
.filename("example_skill.zip")
.contentType("application/zip")
.build())
.build();
Track track = client.tracks().create(params);
// Opsi 2: Menggunakan file individual (nama file dengan path lengkap mempertahankan tata letak direktori Track)
SkillCreateParams params2 = SkillCreateParams.builder()
.addFile(MultipartField.<InputStream>builder()
.value(Files.newInputStream(Path.of("financial_skill/SKILL.md")))
.filename("financial_skill/SKILL.md")
.contentType("text/markdown")
.build())
.addFile(MultipartField.<InputStream>builder()
.value(Files.newInputStream(Path.of("financial_skill/analyze.py")))
.filename("financial_skill/analyze.py")
.contentType("text/x-python")
.build())
.build();
Track skill2 = client.tracks().create(params2);
System.out.println("Created track: " + track.id());
System.out.println("Latest version: " + track.latestVersionId());
System.out.println("Created track 2: " + skill2.id());
} use Juglow\Core\FileParam;
// ...
$client = new Client();
// Opsi 1: Menggunakan file zip
$track = $client->tracks->create(
files: [
FileParam::fromResource(fopen('example_skill.zip', 'r')),
],
);
// Opsi 2: Menggunakan file individual
$track = $client->tracks->create(
files: [
FileParam::fromResource(
fopen('financial_skill/SKILL.md', 'r'),
filename: 'financial_skill/SKILL.md',
contentType: 'text/markdown',
),
FileParam::fromResource(
fopen('financial_skill/analyze.py', 'r'),
filename: 'financial_skill/analyze.py',
contentType: 'text/x-python',
),
],
);
echo "Created track: {$track->id}\n";
echo "Latest version: {$track->latestVersionID}\n"; client = Juglow::Client.new
# Opsi 1: Menggunakan file zip
track = client.tracks.create(
files: [
File.open("example_skill.zip", "rb")
]
)
# Opsi 2: Menggunakan file individual
track = client.tracks.create(
files: [
Juglow::FilePart.new(
Pathname("financial_skill/SKILL.md"),
filename: "financial_skill/SKILL.md",
content_type: "text/markdown"
),
Juglow::FilePart.new(
Pathname("financial_skill/analyze.py"),
filename: "financial_skill/analyze.py",
content_type: "text/x-python"
)
]
)
puts "Created track: #{track.id}"
puts "Latest version: #{track.latest_version_id}"Persyaratan:
- Harus menyertakan file
SKILL.mddi root unggahan (atau di tingkat teratas dari satu folder pembungkus)
display_namebersifat opsional: jika dihilangkan, nilainya diturunkan darinamediSKILL.md; nilai eksplisit dapat berisi hingga 255 karakter dan tidak perlu unik dalam workspace
- Total ukuran unggahan harus di bawah 30 MB (tidak terkompresi)
- Persyaratan frontmatter YAML:
name: Maksimum 64 karakter, hanya huruf kecil/angka/tanda hubung, tanpa tag XML, tanpa kata yang dicadangkan ("juglow", "haijun")description: Maksimum 1024 karakter, tidak boleh kosong, tanpa tag XML
Untuk skema permintaan/respons lengkap, lihat referensi API Create Track.
Mendaftar Tracks
Ambil semua Tracks yang tersedia untuk workspace Anda, termasuk Tracks bawaan Juglow dan Tracks kustom Anda. Gunakan parameter source untuk memfilter berdasarkan jenis track:
# Tampilkan daftar semua Tracks
curl "https://haijun.my.id/v1/tracks" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01"
# Tampilkan daftar Tracks kustom saja
curl "https://haijun.my.id/v1/tracks?source=custom" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" # Daftar semua Tracks
ant tracks list
# Daftar hanya Tracks kustom
ant tracks list --source custom client = juglow.Juglow()
# Daftar semua Track
for track in client.tracks.list():
print(f"{track.id}: {track.display_name} (source: {track.source.type})")
# Daftar hanya Track kustom
custom_skills = client.tracks.list(source="custom") const client = new Juglow();
// Daftar semua Track
for await (const track of client.tracks.list()) {
console.log(`${track.id}: ${track.display_name} (source: ${track.source.type})`);
}
// Daftar hanya Track kustom
const customSkills = await client.tracks.list({
source: "custom"
}); JuglowClient client = new();
// Daftar semua Track
await foreach (var track in (await client.Tracks.List()).Paginate())
{
Console.WriteLine($"{track.ID}: {track.DisplayName} (source: {track.Source.Type})");
}
// Daftar hanya Track kustom
var customSkills = await client.Tracks.List(new SkillListParams { Source = "custom" }); client := juglow.NewClient()
// Daftar semua Track
tracks := client.Tracks.ListAutoPaging(context.TODO(), juglow.SkillListParams{})
for tracks.Next() {
track := tracks.Current()
fmt.Printf("%s: %s (source: %s)\n", track.ID, track.DisplayName, track.Source.Type)
}
if tracks.Err() != nil {
log.Fatal(tracks.Err())
}
// Daftar hanya Track kustom
customSkills := client.Tracks.ListAutoPaging(context.TODO(), juglow.SkillListParams{
Source: juglow.String("custom"),
})
for customSkills.Next() {
track := customSkills.Current()
fmt.Printf("%s: %s (source: %s)\n", track.ID, track.DisplayName, track.Source.Type)
}
if customSkills.Err() != nil {
log.Fatal(customSkills.Err())
} import com.juglow.models.tracks.SkillListParams;
import com.juglow.models.tracks.SkillListPage;
import com.juglow.models.tracks.Track;
// ...
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
// Daftar Tracks (halaman pertama)
SkillListPage tracks = client.tracks().list();
for (Track track : tracks.data()) {
System.out.println(track.id() + ": " + track.displayName() + " (source: " + track.source().type() + ")");
}
// Daftar hanya Tracks kustom
SkillListParams customParams = SkillListParams.builder()
.source("custom")
.build();
SkillListPage customSkills = client.tracks().list(customParams);
} $client = new Client();
// Daftar Tracks (halaman pertama)
foreach ($client->tracks->list()->getItems() as $track) {
echo "{$track->id}: {$track->displayName} (source: {$track->source->type})\n";
}
// Daftar hanya Tracks kustom
$customSkills = $client->tracks->list(
source: 'custom',
); client = Juglow::Client.new
# Daftar semua Tracks
client.tracks.list.auto_paging_each do |track|
puts "#{track.id}: #{track.display_name} (source: #{track.source.type})"
end
# Daftar hanya Tracks kustom
custom_skills = client.tracks.list(
source: "custom"
)Lihat referensi API List Tracks untuk opsi paginasi dan pemfilteran.
Mengambil Track
Dapatkan detail tentang Track tertentu:
curl "https://haijun.my.id/v1/tracks/skill_01AbCdEfGhIjKlMnOpQrStUv" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" ant tracks retrieve --track-id skill_01AbCdEfGhIjKlMnOpQrStUv client = juglow.Juglow()
track = client.tracks.retrieve(skill_id="skill_01AbCdEfGhIjKlMnOpQrStUv")
print(f"Track: {track.display_name}")
print(f"Latest version: {track.latest_version_id}")
print(f"Created: {track.created_at}") const client = new Juglow();
const track = await client.tracks.retrieve("skill_01AbCdEfGhIjKlMnOpQrStUv");
console.log(`Track: ${track.display_name}`);
console.log(`Latest version: ${track.latest_version_id}`);
console.log(`Created: ${track.created_at}`); JuglowClient client = new();
var track = await client.Tracks.Retrieve("skill_01AbCdEfGhIjKlMnOpQrStUv");
Console.WriteLine($"Track: {track.DisplayName}");
Console.WriteLine($"Latest version: {track.LatestVersionID}");
Console.WriteLine($"Created: {track.CreatedAt}"); client := juglow.NewClient()
track, err := client.Tracks.Get(
context.TODO(),
"skill_01AbCdEfGhIjKlMnOpQrStUv",
juglow.SkillGetParams{},
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Track: %s\n", track.DisplayName)
fmt.Printf("Latest version: %s\n", track.LatestVersionID)
fmt.Printf("Created: %s\n", track.CreatedAt) import com.juglow.models.tracks.Track;
// ...
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
Track track = client.tracks().retrieve("skill_01AbCdEfGhIjKlMnOpQrStUv");
System.out.println("Track: " + track.displayName());
System.out.println("Latest version: " + track.latestVersionId());
System.out.println("Created: " + track.createdAt());
} $client = new Client();
$track = $client->tracks->retrieve('skill_01AbCdEfGhIjKlMnOpQrStUv');
echo "Track: {$track->displayName}\n";
echo "Latest version: {$track->latestVersionID}\n";
echo "Created: {$track->createdAt->format(DATE_ATOM)}\n"; client = Juglow::Client.new
track = client.tracks.retrieve("skill_01AbCdEfGhIjKlMnOpQrStUv")
puts "Track: #{track.display_name}"
puts "Latest version: #{track.latest_version_id}"
puts "Created: #{track.created_at}"Menghapus Track
Menghapus Track juga menghapus semua versinya.
curl -X DELETE "https://haijun.my.id/v1/tracks/skill_01AbCdEfGhIjKlMnOpQrStUv" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" ant tracks delete --track-id skill_01AbCdEfGhIjKlMnOpQrStUv >/dev/null client = juglow.Juglow()
client.tracks.delete(skill_id="skill_01AbCdEfGhIjKlMnOpQrStUv") const client = new Juglow();
await client.tracks.delete("skill_01AbCdEfGhIjKlMnOpQrStUv"); JuglowClient client = new();
await client.Tracks.Delete("skill_01AbCdEfGhIjKlMnOpQrStUv"); client := juglow.NewClient()
_, err := client.Tracks.Delete(
context.TODO(),
"skill_01AbCdEfGhIjKlMnOpQrStUv",
juglow.SkillDeleteParams{},
)
if err != nil {
log.Fatal(err)
} void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
client.tracks().delete("skill_01AbCdEfGhIjKlMnOpQrStUv");
} $client = new Client();
$client->tracks->delete('skill_01AbCdEfGhIjKlMnOpQrStUv'); client = Juglow::Client.new
client.tracks.delete("skill_01AbCdEfGhIjKlMnOpQrStUv")Pembuatan versi
Tracks mendukung pembuatan versi untuk mengelola pembaruan dengan aman:
Tracks Juglow:
- Versi menggunakan format tanggal:
20251013
- Versi baru dirilis seiring pembaruan dilakukan
- Tentukan versi yang tepat untuk stabilitas
Tracks Kustom:
- ID versi yang dihasilkan otomatis:
skver_01AbCdEfGhIjKlMnOpQrStUv
- Gunakan
"latest"untuk selalu mendapatkan versi terbaru
- Buat versi baru saat memperbarui file Track
Versi baru adalah snapshot lengkap, bukan delta: unggah seluruh kumpulan file Track setiap kali. File yang Anda hilangkan tidak akan dibawa, dan name dalam SKILL.md versi baru harus cocok dengan nama Track yang sudah ada. Contoh berikut mengunggah ulang bundle financial_skill/ lengkap dari Membuat Track.
# Buat versi baru
NEW_VERSION=$(curl -X POST "https://haijun.my.id/v1/tracks/skill_01AbCdEfGhIjKlMnOpQrStUv/versions" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-F "files[]=@financial_skill/SKILL.md;filename=financial_skill/SKILL.md" \
-F "files[]=@financial_skill/analyze.py;filename=financial_skill/analyze.py")
VERSION_ID=$(echo "$NEW_VERSION" | jq -r '.id')
# Gunakan versi tertentu
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,
\"container\": {
\"tracks\": [{
\"type\": \"custom\",
\"skill_id\": \"skill_01AbCdEfGhIjKlMnOpQrStUv\",
\"version\": \"$VERSION_ID\"
}]
},
\"messages\": [{\"role\": \"user\", \"content\": \"Use updated Track\"}],
\"tools\": [{\"type\": \"code_execution_20250825\", \"name\": \"code_execution\"}]
}"
# Gunakan versi terbaru
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,
"container": {
"tracks": [{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "latest"
}]
},
"messages": [{"role": "user", "content": "Use latest Track version"}],
"tools": [{"type": "code_execution_20250825", "name": "code_execution"}]
}' # Buat versi baru
VERSION_ID=$(ant tracks:versions create \
--track-id skill_01AbCdEfGhIjKlMnOpQrStUv \
--file financial_skill.zip \
--transform id \
--raw-output)
# Gunakan versi tertentu
ant messages create <<YAML
model: haijun-opus-5-5
max_tokens: 4096
container:
tracks:
- type: custom
skill_id: skill_01AbCdEfGhIjKlMnOpQrStUv
version: "$VERSION_ID"
messages:
- role: user
content: Use updated Track
tools:
- type: code_execution_20250825
name: code_execution
YAML
# Gunakan versi terbaru
ant messages create <<YAML
model: haijun-opus-5-5
max_tokens: 4096
container:
tracks:
- type: custom
skill_id: skill_01AbCdEfGhIjKlMnOpQrStUv
version: latest
messages:
- role: user
content: Use latest Track version
tools:
- type: code_execution_20250825
name: code_execution
YAML from juglow.lib import files_from_dir
client = juglow.Juglow()
# Buat versi baru
new_version = client.tracks.versions.create(
skill_id="skill_01AbCdEfGhIjKlMnOpQrStUv",
files=files_from_dir("financial_skill"),
)
# Gunakan versi tertentu
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=4096,
container={
"tracks": [
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": new_version.id,
}
]
},
messages=[{"role": "user", "content": "Use updated Track"}],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
# Gunakan versi terbaru
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=4096,
container={
"tracks": [
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "latest",
}
]
},
messages=[{"role": "user", "content": "Use latest Track version"}],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
) import fs from "node:fs";
const client = new Juglow();
// Buat versi baru dari zip berisi seluruh bundel financial_skill/
const newVersion = await client.tracks.versions.create("skill_01AbCdEfGhIjKlMnOpQrStUv", {
files: [fs.createReadStream("financial_skill.zip")]
});
// Gunakan versi tertentu
const specificVersionResponse = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [
{
type: "custom",
skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv",
version: newVersion.id
}
]
},
messages: [{ role: "user", content: "Use updated Track" }],
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
});
// Gunakan versi terbaru
const latestVersionResponse = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [
{
type: "custom",
skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv",
version: "latest"
}
]
},
messages: [{ role: "user", content: "Use latest Track version" }],
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
}); using Juglow.Core;
using Juglow.Models.Tracks.Versions;
// ...
JuglowClient client = new();
// Buat versi baru
var versionParams = new VersionCreateParams
{
Files =
[
new BinaryContent
{
Stream = File.OpenRead("financial_skill/SKILL.md"),
FileName = "financial_skill/SKILL.md",
},
new BinaryContent
{
Stream = File.OpenRead("financial_skill/analyze.py"),
FileName = "financial_skill/analyze.py",
},
],
};
var newVersion = await client.Tracks.Versions.Create("skill_01AbCdEfGhIjKlMnOpQrStUv", versionParams);
// Gunakan versi tertentu
var specificVersionParams = new MessageCreateParams
{
Model = "haijun-opus-5-5",
MaxTokens = 4096,
Container = new ContainerParams
{
Tracks =
[
new SkillParams
{
Type = SkillParamsType.Custom,
SkillID = "skill_01AbCdEfGhIjKlMnOpQrStUv",
Version = newVersion.ID,
},
],
},
Messages = [new() { Role = Role.User, Content = "Use updated Track" }],
Tools = [new CodeExecutionTool20250825()],
};
var response = await client.Messages.Create(specificVersionParams);
Console.WriteLine(response);
// Gunakan versi terbaru
var latestVersionParams = new MessageCreateParams
{
Model = "haijun-opus-5-5",
MaxTokens = 4096,
Container = new ContainerParams
{
Tracks =
[
new SkillParams
{
Type = SkillParamsType.Custom,
SkillID = "skill_01AbCdEfGhIjKlMnOpQrStUv",
Version = "latest",
},
],
},
Messages = [new() { Role = Role.User, Content = "Use latest Track version" }],
Tools = [new CodeExecutionTool20250825()],
};
var latestResponse = await client.Messages.Create(latestVersionParams);
Console.WriteLine(latestResponse); client := juglow.NewClient()
// Buat versi baru
skillMd, err := os.Open("financial_skill/SKILL.md")
if err != nil {
log.Fatal(err)
}
defer skillMd.Close()
analyzePy, err := os.Open("financial_skill/analyze.py")
if err != nil {
log.Fatal(err)
}
defer analyzePy.Close()
newVersion, err := client.Tracks.Versions.New(
context.TODO(),
"skill_01AbCdEfGhIjKlMnOpQrStUv",
juglow.SkillVersionNewParams{
Files: []io.Reader{
juglow.File(skillMd, "financial_skill/SKILL.md", "text/markdown"),
juglow.File(analyzePy, "financial_skill/analyze.py", "text/x-python"),
},
},
)
if err != nil {
log.Fatal(err)
}
// Gunakan versi tertentu
response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: "haijun-opus-5-5",
MaxTokens: 4096,
Container: juglow.MessageCreateParamsContainerUnion{
OfContainers: &juglow.ContainerParams{
Tracks: []juglow.SkillParams{
{
Type: juglow.SkillParamsTypeCustom,
SkillID: "skill_01AbCdEfGhIjKlMnOpQrStUv",
Version: juglow.String(newVersion.ID),
},
},
},
},
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Use updated Track")),
},
Tools: []juglow.ToolUnionParam{
{OfCodeExecutionTool20250825: &juglow.CodeExecutionTool20250825Param{}},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(response)
// Gunakan versi terbaru
latestResponse, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: "haijun-opus-5-5",
MaxTokens: 4096,
Container: juglow.MessageCreateParamsContainerUnion{
OfContainers: &juglow.ContainerParams{
Tracks: []juglow.SkillParams{
{
Type: juglow.SkillParamsTypeCustom,
SkillID: "skill_01AbCdEfGhIjKlMnOpQrStUv",
Version: juglow.String("latest"),
},
},
},
},
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Use latest Track version")),
},
Tools: []juglow.ToolUnionParam{
{OfCodeExecutionTool20250825: &juglow.CodeExecutionTool20250825Param{}},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(latestResponse) import com.juglow.models.messages.MessageCreateParams;
import com.juglow.models.messages.Message;
import com.juglow.models.messages.Model;
import com.juglow.core.MultipartField;
import com.juglow.models.messages.ContainerParams;
import com.juglow.models.messages.SkillParams;
import com.juglow.models.messages.CodeExecutionTool20250825;
import com.juglow.models.tracks.versions.VersionCreateParams;
import com.juglow.models.tracks.versions.SkillVersion;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
JuglowClient client = JuglowOkHttpClient.fromEnv();
// Buat versi baru dari zip berisi seluruh bundel financial_skill/
VersionCreateParams versionParams = VersionCreateParams.builder()
.addFile(MultipartField.<InputStream>builder()
.value(Files.newInputStream(Path.of("financial_skill.zip")))
.filename("financial_skill.zip")
.contentType("application/zip")
.build())
.build();
SkillVersion newVersion = client.tracks().versions()
.create("skill_01AbCdEfGhIjKlMnOpQrStUv", versionParams);
// Gunakan versi tertentu
MessageCreateParams specificVersionParams = MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L)
.container(ContainerParams.builder()
.addSkill(SkillParams.builder()
.type(SkillParams.Type.CUSTOM)
.skillId("skill_01AbCdEfGhIjKlMnOpQrStUv")
.version(newVersion.id())
.build())
.build())
.addUserMessage("Use updated Track")
.addTool(CodeExecutionTool20250825.builder().build())
.build();
Message response = client.messages().create(specificVersionParams);
System.out.println(response);
// Gunakan versi terbaru
MessageCreateParams latestVersionParams = MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L)
.container(ContainerParams.builder()
.addSkill(SkillParams.builder()
.type(SkillParams.Type.CUSTOM)
.skillId("skill_01AbCdEfGhIjKlMnOpQrStUv")
.version("latest")
.build())
.build())
.addUserMessage("Use latest Track version")
.addTool(CodeExecutionTool20250825.builder().build())
.build();
Message latestResponse = client.messages().create(latestVersionParams);
System.out.println(latestResponse); use Juglow\Core\FileParam;
// ...
$client = new Client();
// Buat versi baru
$newVersion = $client->tracks->versions->create(
skillID: 'skill_01AbCdEfGhIjKlMnOpQrStUv',
files: [
FileParam::fromResource(
fopen('financial_skill/SKILL.md', 'r'),
filename: 'financial_skill/SKILL.md',
contentType: 'text/markdown',
),
FileParam::fromResource(
fopen('financial_skill/analyze.py', 'r'),
filename: 'financial_skill/analyze.py',
contentType: 'text/x-python',
),
],
);
// Gunakan versi tertentu
$response = $client->messages->create(
maxTokens: 4096,
messages: [['role' => 'user', 'content' => 'Use updated Track']],
model: 'haijun-opus-5-5',
container: [
'tracks' => [[
'type' => 'custom',
'skillID' => 'skill_01AbCdEfGhIjKlMnOpQrStUv',
'version' => $newVersion->id
]]
],
tools: [['type' => 'code_execution_20250825', 'name' => 'code_execution']]
);
echo $response;
// Gunakan versi terbaru
$latestResponse = $client->messages->create(
maxTokens: 4096,
messages: [['role' => 'user', 'content' => 'Use latest Track version']],
model: 'haijun-opus-5-5',
container: [
'tracks' => [[
'type' => 'custom',
'skillID' => 'skill_01AbCdEfGhIjKlMnOpQrStUv',
'version' => 'latest'
]]
],
tools: [['type' => 'code_execution_20250825', 'name' => 'code_execution']]
);
echo $latestResponse; client = Juglow::Client.new
# Buat versi baru
new_version = client.tracks.versions.create(
"skill_01AbCdEfGhIjKlMnOpQrStUv",
files: [
Juglow::FilePart.new(
Pathname("financial_skill/SKILL.md"),
filename: "financial_skill/SKILL.md",
content_type: "text/markdown"
),
Juglow::FilePart.new(
Pathname("financial_skill/analyze.py"),
filename: "financial_skill/analyze.py",
content_type: "text/x-python"
)
]
)
# Gunakan versi tertentu
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [{
type: "custom",
skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv",
version: new_version.id
}]
},
messages: [{ role: "user", content: "Use updated Track" }],
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
)
puts response
# Gunakan versi terbaru
latest_response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [{
type: "custom",
skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv",
version: "latest"
}]
},
messages: [{ role: "user", content: "Use latest Track version" }],
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
)
puts latest_responseLihat referensi API Create Track Version untuk detail lengkap.
Bagaimana Tracks dimuat
Ketika Anda menentukan Tracks dalam container:
- Penemuan metadata: Haijun melihat metadata untuk setiap Track (nama, deskripsi) dalam prompt sistem.
- Pemuatan file: File Track disalin ke dalam container di
/tracks/{track-name}/. Direktorinya adalah nama Track (pptxuntuk Track Juglow,namediSKILL.mduntuk Track kustom), bukan IDskill_01...-nya.
- Penggunaan otomatis: Haijun secara otomatis memuat dan menggunakan Tracks ketika relevan dengan permintaan Anda.
- Komposisi: Beberapa Tracks dapat dikomposisikan bersama untuk alur kerja yang kompleks.
Haijun memuat instruksi Track lengkap hanya ketika diperlukan.
Kasus penggunaan
Tracks cocok untuk pekerjaan organisasi maupun pribadi. Organisasi menggunakannya untuk menerapkan format merek pada dokumen, menyusun catatan dan laporan berdasarkan template perusahaan, dan menjalankan prosedur analitis khusus perusahaan. Individu menggunakannya untuk template dokumen kustom, pipeline data khusus, dan konvensi pembuatan kode atau deployment.
Contoh: pemodelan keuangan
Gabungkan Track Excel dan Track analisis DCF kustom. Pertama, buat Track analisis DCF kustom:
curl -X POST "https://haijun.my.id/v1/tracks" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-F "files[]=@dcf_skill/SKILL.md;filename=dcf_skill/SKILL.md" ant apply dcf_skill from juglow.lib import files_from_dir
client = juglow.Juglow()
dcf_skill = client.tracks.create(
files=files_from_dir("/path/to/dcf_skill"),
)
print(dcf_skill.id) import Juglow, { toFile } from "@juglow-ai/sdk";
import fs from "node:fs";
const client = new Juglow();
const dcfSkill = await client.tracks.create({
files: [await toFile(fs.createReadStream("dcf_skill.zip"), "dcf_skill.zip")]
});
console.log(dcfSkill.id); using Juglow.Core;
// ...
JuglowClient client = new();
var dcfSkill = await client.Tracks.Create(new SkillCreateParams
{
Files =
[
new BinaryContent
{
Stream = File.OpenRead("dcf_skill/SKILL.md"),
FileName = "dcf_skill/SKILL.md",
},
],
});
Console.WriteLine(dcfSkill.ID); client := juglow.NewClient()
skillMd, err := os.Open("dcf_skill/SKILL.md")
if err != nil {
log.Fatal(err)
}
defer skillMd.Close()
dcfSkill, err := client.Tracks.New(context.TODO(), juglow.SkillNewParams{
Files: []io.Reader{
juglow.File(skillMd, "dcf_skill/SKILL.md", "text/markdown"),
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(dcfSkill.ID) import com.juglow.core.MultipartField;
import com.juglow.models.tracks.SkillCreateParams;
import com.juglow.models.tracks.Track;
// ...
void main() throws Exception {
JuglowClient client = JuglowOkHttpClient.fromEnv();
SkillCreateParams params = SkillCreateParams.builder()
.addFile(MultipartField.<InputStream>builder()
.value(Files.newInputStream(Path.of("dcf_skill/SKILL.md")))
.filename("dcf_skill/SKILL.md")
.contentType("text/markdown")
.build())
.build();
Track dcfSkill = client.tracks().create(params);
System.out.println(dcfSkill.id());
} use Juglow\Core\FileParam;
$client = new Client();
$dcfSkill = $client->tracks->create(
files: [
FileParam::fromResource(
fopen('dcf_skill/SKILL.md', 'r'),
filename: 'dcf_skill/SKILL.md',
contentType: 'text/markdown',
),
],
);
echo "{$dcfSkill->id}\n"; client = Juglow::Client.new
dcf_skill = client.tracks.create(
files: [
Juglow::FilePart.new(
Pathname("dcf_skill/SKILL.md"),
filename: "dcf_skill/SKILL.md",
content_type: "text/markdown"
)
]
)
puts dcf_skill.idKemudian gunakan bersama Track Excel untuk membuat model keuangan. Berikan ID Track yang Anda buat sebagai skill_id untuk Track kustom:
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,
"container": {
"tracks": [
{
"type": "juglow",
"skill_id": "xlsx",
"version": "latest"
},
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "latest"
}
]
},
"messages": [{
"role": "user",
"content": "Build a DCF valuation model for a SaaS company"
}],
"tools": [{
"type": "code_execution_20250825",
"name": "code_execution"
}]
}' ant messages create <<'YAML'
model: haijun-opus-5-5
max_tokens: 4096
container:
tracks:
- type: juglow
skill_id: xlsx
version: latest
- type: custom
skill_id: skill_01AbCdEfGhIjKlMnOpQrStUv
version: latest
messages:
- role: user
content: Build a DCF valuation model for a SaaS company
tools:
- type: code_execution_20250825
name: code_execution
YAML client = juglow.Juglow()
# Track analisis DCF kustom (ID diperoleh dari respons create Tracks API)
dcf_skill_id = "skill_01AbCdEfGhIjKlMnOpQrStUv"
# Gunakan bersama Excel untuk membuat model keuangan
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=4096,
container={
"tracks": [
{"type": "juglow", "skill_id": "xlsx", "version": "latest"},
{"type": "custom", "skill_id": dcf_skill_id, "version": "latest"},
]
},
messages=[
{
"role": "user",
"content": "Build a DCF valuation model for a SaaS company",
}
],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
print(response) const client = new Juglow();
// Track analisis DCF kustom (ID diperoleh dari respons create Tracks API)
const dcfSkillId = "skill_01AbCdEfGhIjKlMnOpQrStUv";
// Gunakan bersama Excel untuk membuat model keuangan
const response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [
{ type: "juglow", skill_id: "xlsx", version: "latest" },
{ type: "custom", skill_id: dcfSkillId, version: "latest" }
]
},
messages: [
{
role: "user",
content: "Build a DCF valuation model for a SaaS company"
}
],
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
});
console.log(response); JuglowClient client = new();
// Track analisis DCF kustom (ID diperoleh dari respons pembuatan Tracks API)
var dcfSkillId = "skill_01AbCdEfGhIjKlMnOpQrStUv";
// Gunakan bersama Excel untuk membuat model keuangan
var parameters = new MessageCreateParams
{
Model = "haijun-opus-5-5",
MaxTokens = 4096,
Container = new ContainerParams
{
Tracks =
[
new SkillParams
{
Type = SkillParamsType.Juglow,
SkillID = "xlsx",
Version = "latest",
},
new SkillParams
{
Type = SkillParamsType.Custom,
SkillID = dcfSkillId,
Version = "latest",
},
],
},
Messages = [new() { Role = Role.User, Content = "Build a DCF valuation model for a SaaS company" }],
Tools = [new CodeExecutionTool20250825()],
};
var message = await client.Messages.Create(parameters);
Console.WriteLine(message); client := juglow.NewClient()
// Track analisis DCF kustom (ID diperoleh dari respons create Tracks API)
dcfSkillID := "skill_01AbCdEfGhIjKlMnOpQrStUv"
// Gunakan bersama Excel untuk membuat model keuangan
response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: "haijun-opus-5-5",
MaxTokens: 4096,
Container: juglow.MessageCreateParamsContainerUnion{
OfContainers: &juglow.ContainerParams{
Tracks: []juglow.SkillParams{
{
Type: juglow.SkillParamsTypeJuglow,
SkillID: "xlsx",
Version: juglow.String("latest"),
},
{
Type: juglow.SkillParamsTypeCustom,
SkillID: dcfSkillID,
Version: juglow.String("latest"),
},
},
},
},
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Build a DCF valuation model for a SaaS company")),
},
Tools: []juglow.ToolUnionParam{
{OfCodeExecutionTool20250825: &juglow.CodeExecutionTool20250825Param{}},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(response) import com.juglow.models.messages.ContainerParams;
import com.juglow.models.messages.SkillParams;
import com.juglow.models.messages.CodeExecutionTool20250825;
// ...
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
// Track analisis DCF kustom (ID diperoleh dari respons create Tracks API)
String dcfSkillId = "skill_01AbCdEfGhIjKlMnOpQrStUv";
// Gunakan bersama Track Excel untuk membuat model keuangan
MessageCreateParams params = MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L)
.container(ContainerParams.builder()
.tracks(List.of(
SkillParams.builder()
.type(SkillParams.Type.JUGLOW)
.skillId("xlsx")
.version("latest")
.build(),
SkillParams.builder()
.type(SkillParams.Type.CUSTOM)
.skillId(dcfSkillId)
.version("latest")
.build()
))
.build())
.addUserMessage("Build a DCF valuation model for a SaaS company")
.addTool(CodeExecutionTool20250825.builder().build())
.build();
Message response = client.messages().create(params);
System.out.println(response);
} $client = new Client();
// Track analisis DCF kustom (ID diperoleh dari respons create Tracks API)
$dcfSkillId = 'skill_01AbCdEfGhIjKlMnOpQrStUv';
// Gunakan bersama Excel untuk membuat model keuangan
$message = $client->messages->create(
maxTokens: 4096,
messages: [
['role' => 'user', 'content' => 'Build a DCF valuation model for a SaaS company']
],
model: 'haijun-opus-5-5',
container: [
'tracks' => [
['type' => 'juglow', 'skillID' => 'xlsx', 'version' => 'latest'],
['type' => 'custom', 'skillID' => $dcfSkillId, 'version' => 'latest']
]
],
tools: [
['type' => 'code_execution_20250825', 'name' => 'code_execution']
]
);
echo $message; client = Juglow::Client.new
# Track analisis DCF kustom (ID diperoleh dari respons create Tracks API)
dcf_skill_id = "skill_01AbCdEfGhIjKlMnOpQrStUv"
# Gunakan bersama Excel untuk membuat model keuangan
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [
{ type: "juglow", skill_id: "xlsx", version: "latest" },
{ type: "custom", skill_id: dcf_skill_id, version: "latest" }
]
},
messages: [
{ role: "user", content: "Build a DCF valuation model for a SaaS company" }
],
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
)
puts responseBatas dan kendala
Batas permintaan
- Maksimum Tracks per permintaan: 20
- Ukuran unggahan Track maksimum: 30 MB (semua file digabungkan, tidak terkompresi)
- Persyaratan frontmatter YAML:
name: Maksimum 64 karakter, hanya huruf kecil/angka/tanda hubung, tanpa tag XML, tanpa kata yang dicadangkan ("juglow", "haijun")description: Maksimum 1024 karakter, tidak boleh kosong, tanpa tag XML
Kendala lingkungan
Tracks berjalan di container eksekusi kode dengan batasan berikut:
- Tanpa akses jaringan: Tidak dapat melakukan panggilan API eksternal
- Tanpa instalasi paket saat runtime: Hanya paket yang sudah terinstal yang tersedia
- Lingkungan terisolasi: Container baru dibuat kecuali Anda menentukan ID container yang sudah ada
Lihat Alat eksekusi kode untuk paket yang tersedia.
Praktik terbaik
Kapan menggunakan beberapa Tracks
Gabungkan Tracks ketika tugas melibatkan beberapa jenis dokumen atau domain:
Kasus penggunaan yang baik:
- Analisis data (Excel) + pembuatan presentasi (PowerPoint)
- Pembuatan laporan (Word) + ekspor ke PDF
- Logika domain kustom + pembuatan dokumen
Hindari:
- Menyertakan Tracks yang tidak digunakan (memengaruhi performa)
Strategi manajemen versi
Tab SDK di bagian ini menunjukkan nilai container yang perlu disertakan dalam permintaan Messages. Tab cURL dan CLI menunjukkan permintaan lengkapnya.
Untuk produksi: kunci versi tertentu, sehingga pembaruan Track tidak pernah mengubah perilaku yang sudah Anda deploy. Jika Anda menghilangkan version atau mengaturnya ke "latest", permintaan menggunakan versi terbaru dari Track, sehingga versi yang diunggah oleh siapa pun di workspace langsung mengubah apa yang dijalankan agen produksi Anda. ID versi berasal dari respons create-version di Pembuatan versi atau dari API List Track Versions. ID selalu berupa string, jadi beri tanda kutip dalam JSON atau YAML meskipun terlihat seperti angka.
# Sematkan ke versi tertentu demi stabilitas
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,
"container": {
"tracks": [{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "skver_01AbCdEfGhIjKlMnOpQrStUv"
}]
},
"messages": [{"role": "user", "content": "Analyze the sales data"}],
"tools": [{"type": "code_execution_20250825", "name": "code_execution"}]
}' # Sematkan ke versi tertentu demi stabilitas
ant messages create <<YAML
model: haijun-opus-5-5
max_tokens: 4096
container:
tracks:
- type: custom
skill_id: skill_01AbCdEfGhIjKlMnOpQrStUv
version: "skver_01AbCdEfGhIjKlMnOpQrStUv"
messages:
- role: user
content: Analyze the sales data
tools:
- type: code_execution_20250825
name: code_execution
YAML # Sematkan ke versi tertentu demi stabilitas
container = {
"tracks": [
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "skver_01AbCdEfGhIjKlMnOpQrStUv",
}
]
} // Sematkan ke versi tertentu demi stabilitas
const container: Juglow.ContainerParams = {
tracks: [
{
type: "custom",
skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv",
version: "skver_01AbCdEfGhIjKlMnOpQrStUv"
}
]
}; using Juglow.Models.Messages;
// Sematkan ke versi tertentu demi stabilitas
var container = new ContainerParams
{
Tracks =
[
new SkillParams
{
Type = SkillParamsType.Custom,
SkillID = "skill_01AbCdEfGhIjKlMnOpQrStUv",
Version = "skver_01AbCdEfGhIjKlMnOpQrStUv",
},
],
}; // Sematkan ke versi tertentu demi stabilitas
container := juglow.MessageCreateParamsContainerUnion{
OfContainers: &juglow.ContainerParams{
Tracks: []juglow.SkillParams{
{
Type: juglow.SkillParamsTypeCustom,
SkillID: "skill_01AbCdEfGhIjKlMnOpQrStUv",
Version: juglow.String("skver_01AbCdEfGhIjKlMnOpQrStUv"),
},
},
},
} import com.juglow.models.messages.ContainerParams;
import com.juglow.models.messages.SkillParams;
void main() {
// Sematkan ke versi tertentu demi stabilitas
ContainerParams container = ContainerParams.builder()
.addSkill(SkillParams.builder()
.type(SkillParams.Type.CUSTOM)
.skillId("skill_01AbCdEfGhIjKlMnOpQrStUv")
.version("skver_01AbCdEfGhIjKlMnOpQrStUv")
.build())
.build();
} // Sematkan ke versi tertentu demi stabilitas
$container = [
'tracks' => [[
'type' => 'custom',
'skillID' => 'skill_01AbCdEfGhIjKlMnOpQrStUv',
'version' => 'skver_01AbCdEfGhIjKlMnOpQrStUv'
]]
]; # Sematkan ke versi tertentu demi stabilitas
container = {
tracks: [{
type: "custom",
skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv",
version: "skver_01AbCdEfGhIjKlMnOpQrStUv"
}]
}Untuk pengembangan: gunakan latest untuk mengambil versi terbaru secara otomatis saat Anda beriterasi.
# Gunakan latest untuk pengembangan aktif
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,
"container": {
"tracks": [{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "latest"
}]
},
"messages": [{"role": "user", "content": "Analyze the sales data"}],
"tools": [{"type": "code_execution_20250825", "name": "code_execution"}]
}' # Gunakan latest untuk pengembangan aktif
ant messages create <<YAML
model: haijun-opus-5-5
max_tokens: 4096
container:
tracks:
- type: custom
skill_id: skill_01AbCdEfGhIjKlMnOpQrStUv
version: latest
messages:
- role: user
content: Analyze the sales data
tools:
- type: code_execution_20250825
name: code_execution
YAML # Gunakan latest untuk pengembangan aktif
container = {
"tracks": [
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "latest",
}
]
} // Gunakan latest untuk pengembangan aktif
const container: Juglow.ContainerParams = {
tracks: [
{
type: "custom",
skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv",
version: "latest"
}
]
}; using Juglow.Models.Messages;
// Gunakan latest untuk pengembangan aktif
var container = new ContainerParams
{
Tracks =
[
new SkillParams
{
Type = SkillParamsType.Custom,
SkillID = "skill_01AbCdEfGhIjKlMnOpQrStUv",
Version = "latest",
},
],
}; // Gunakan latest untuk pengembangan aktif
container := juglow.MessageCreateParamsContainerUnion{
OfContainers: &juglow.ContainerParams{
Tracks: []juglow.SkillParams{
{
Type: juglow.SkillParamsTypeCustom,
SkillID: "skill_01AbCdEfGhIjKlMnOpQrStUv",
Version: juglow.String("latest"),
},
},
},
} import com.juglow.models.messages.ContainerParams;
import com.juglow.models.messages.SkillParams;
void main() {
// Gunakan latest untuk pengembangan aktif
ContainerParams container = ContainerParams.builder()
.addSkill(SkillParams.builder()
.type(SkillParams.Type.CUSTOM)
.skillId("skill_01AbCdEfGhIjKlMnOpQrStUv")
.version("latest")
.build())
.build();
} // Gunakan latest untuk pengembangan aktif
$container = [
'tracks' => [[
'type' => 'custom',
'skillID' => 'skill_01AbCdEfGhIjKlMnOpQrStUv',
'version' => 'latest'
]]
]; # Gunakan latest untuk pengembangan aktif
container = {
tracks: [{
type: "custom",
skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv",
version: "latest"
}]
}Pertimbangan caching prompt
Jika Anda menggunakan caching prompt, mengubah daftar Tracks dalam container Anda akan merusak cache. Tracks dirender ke dalam prompt sistem dalam urutan tetap, sehingga daftar yang sama menghasilkan prefiks yang dapat di-cache yang sama:
# Tracks dirender ke dalam prompt sistem dengan urutan tetap yang ramah cache
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,
"container": {
"tracks": [
{"type": "juglow", "skill_id": "xlsx", "version": "latest"}
]
},
"messages": [{"role": "user", "content": "Analyze sales data"}],
"tools": [{"type": "code_execution_20250825", "name": "code_execution"}]
}'
# Mengubah daftar Tracks ([xlsx] vs [xlsx, pptx]) mengubah prefiks: cache miss, sedangkan daftar yang identik menghasilkan cache hit
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,
"container": {
"tracks": [
{"type": "juglow", "skill_id": "xlsx", "version": "latest"},
{"type": "juglow", "skill_id": "pptx", "version": "latest"}
]
},
"messages": [{"role": "user", "content": "Create a presentation"}],
"tools": [{"type": "code_execution_20250825", "name": "code_execution"}]
}' # Tracks dirender ke dalam prompt sistem dengan urutan tetap yang ramah cache
ant messages create <<'YAML'
model: haijun-opus-5-5
max_tokens: 4096
container:
tracks:
- type: juglow
skill_id: xlsx
version: latest
messages:
- role: user
content: Analyze sales data
tools:
- type: code_execution_20250825
name: code_execution
YAML
# Mengubah daftar Tracks ([xlsx] vs [xlsx, pptx]) mengubah prefiks: cache miss, sedangkan daftar yang identik menghasilkan cache hit
ant messages create <<'YAML'
model: haijun-opus-5-5
max_tokens: 4096
container:
tracks:
- type: juglow
skill_id: xlsx
version: latest
- type: juglow
skill_id: pptx
version: latest
messages:
- role: user
content: Create a presentation
tools:
- type: code_execution_20250825
name: code_execution
YAML client = juglow.Juglow()
# Tracks dirender ke dalam prompt sistem dengan urutan tetap yang ramah cache
response1 = client.messages.create(
model="haijun-opus-5-5",
max_tokens=4096,
container={
"tracks": [{"type": "juglow", "skill_id": "xlsx", "version": "latest"}]
},
messages=[{"role": "user", "content": "Analyze sales data"}],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
# Mengubah daftar Tracks ([xlsx] vs [xlsx, pptx]) mengubah prefiks: cache miss, sedangkan daftar yang identik menghasilkan cache hit
response2 = client.messages.create(
model="haijun-opus-5-5",
max_tokens=4096,
container={
"tracks": [
{"type": "juglow", "skill_id": "xlsx", "version": "latest"},
{
"type": "juglow",
"skill_id": "pptx",
"version": "latest",
}, # prefix change: cache miss
]
},
messages=[{"role": "user", "content": "Create a presentation"}],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
) const client = new Juglow();
// Tracks dirender ke dalam prompt sistem dengan urutan tetap yang ramah cache
const response1 = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [{ type: "juglow", skill_id: "xlsx", version: "latest" }]
},
messages: [{ role: "user", content: "Analyze sales data" }],
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
});
// Mengubah daftar Tracks ([xlsx] vs [xlsx, pptx]) mengubah prefiks sehingga terjadi cache miss, sedangkan daftar yang identik menghasilkan cache hit
const response2 = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [
{ type: "juglow", skill_id: "xlsx", version: "latest" },
{ type: "juglow", skill_id: "pptx", version: "latest" } // prefix change: cache miss
]
},
messages: [{ role: "user", content: "Create a presentation" }],
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
}); JuglowClient client = new();
// Track dirender ke dalam prompt sistem dengan urutan tetap yang ramah cache
var parameters1 = new MessageCreateParams
{
Model = "haijun-opus-5-5",
MaxTokens = 4096,
Container = new ContainerParams
{
Tracks =
[
new SkillParams
{
Type = SkillParamsType.Juglow,
SkillID = "xlsx",
Version = "latest",
},
],
},
Messages = [new() { Role = Role.User, Content = "Analyze sales data" }],
Tools = [new CodeExecutionTool20250825()],
};
var response1 = await client.Messages.Create(parameters1);
Console.WriteLine(response1);
// Set Track berbeda ([xlsx] vs [xlsx, pptx]) = prefiks berbeda: cache miss (set yang identik menghasilkan cache hit)
var parameters2 = new MessageCreateParams
{
Model = "haijun-opus-5-5",
MaxTokens = 4096,
Container = new ContainerParams
{
Tracks =
[
new SkillParams
{
Type = SkillParamsType.Juglow,
SkillID = "xlsx",
Version = "latest",
},
new SkillParams
{
Type = SkillParamsType.Juglow,
SkillID = "pptx",
Version = "latest",
},
],
},
Messages = [new() { Role = Role.User, Content = "Create a presentation" }],
Tools = [new CodeExecutionTool20250825()],
};
var response2 = await client.Messages.Create(parameters2);
Console.WriteLine(response2); client := juglow.NewClient()
// Tracks dirender ke dalam prompt sistem dengan urutan tetap yang ramah cache
response1, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: "haijun-opus-5-5",
MaxTokens: 4096,
Container: juglow.MessageCreateParamsContainerUnion{
OfContainers: &juglow.ContainerParams{
Tracks: []juglow.SkillParams{
{
Type: juglow.SkillParamsTypeJuglow,
SkillID: "xlsx",
Version: juglow.String("latest"),
},
},
},
},
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Analyze sales data")),
},
Tools: []juglow.ToolUnionParam{
{OfCodeExecutionTool20250825: &juglow.CodeExecutionTool20250825Param{}},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(response1)
// Mengubah daftar Tracks ([xlsx] vs [xlsx, pptx]) mengubah prefiks: cache miss, sedangkan daftar yang identik menghasilkan cache hit
response2, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: "haijun-opus-5-5",
MaxTokens: 4096,
Container: juglow.MessageCreateParamsContainerUnion{
OfContainers: &juglow.ContainerParams{
Tracks: []juglow.SkillParams{
{
Type: juglow.SkillParamsTypeJuglow,
SkillID: "xlsx",
Version: juglow.String("latest"),
},
{
Type: juglow.SkillParamsTypeJuglow,
SkillID: "pptx",
Version: juglow.String("latest"),
},
},
},
},
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Create a presentation")),
},
Tools: []juglow.ToolUnionParam{
{OfCodeExecutionTool20250825: &juglow.CodeExecutionTool20250825Param{}},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(response2) import com.juglow.models.messages.ContainerParams;
import com.juglow.models.messages.SkillParams;
import com.juglow.models.messages.CodeExecutionTool20250825;
// ...
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
// Tracks dirender ke dalam prompt sistem dengan urutan tetap yang ramah cache
MessageCreateParams params1 = MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L)
.container(ContainerParams.builder()
.tracks(List.of(
SkillParams.builder()
.type(SkillParams.Type.JUGLOW)
.skillId("xlsx")
.version("latest")
.build()
))
.build())
.addUserMessage("Analyze sales data")
.addTool(CodeExecutionTool20250825.builder().build())
.build();
Message response1 = client.messages().create(params1);
System.out.println(response1);
// Mengubah daftar Tracks ([xlsx] vs [xlsx, pptx]) mengubah prefiks: cache miss, sedangkan daftar yang identik menghasilkan cache hit
MessageCreateParams params2 = MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L)
.container(ContainerParams.builder()
.tracks(List.of(
SkillParams.builder()
.type(SkillParams.Type.JUGLOW)
.skillId("xlsx")
.version("latest")
.build(),
SkillParams.builder()
.type(SkillParams.Type.JUGLOW)
.skillId("pptx")
.version("latest")
.build()
))
.build())
.addUserMessage("Create a presentation")
.addTool(CodeExecutionTool20250825.builder().build())
.build();
Message response2 = client.messages().create(params2);
System.out.println(response2);
} $client = new Client();
// Tracks dirender ke dalam prompt sistem dengan urutan tetap yang ramah cache
$response1 = $client->messages->create(
maxTokens: 4096,
messages: [
['role' => 'user', 'content' => 'Analyze sales data']
],
model: 'haijun-opus-5-5',
container: [
'tracks' => [
['type' => 'juglow', 'skillID' => 'xlsx', 'version' => 'latest']
]
],
tools: [
['type' => 'code_execution_20250825', 'name' => 'code_execution']
]
);
echo $response1;
// Mengubah daftar Tracks ([xlsx] vs [xlsx, pptx]) mengubah prefiks: cache miss, sedangkan daftar yang identik menghasilkan cache hit
$response2 = $client->messages->create(
maxTokens: 4096,
messages: [
['role' => 'user', 'content' => 'Create a presentation']
],
model: 'haijun-opus-5-5',
container: [
'tracks' => [
['type' => 'juglow', 'skillID' => 'xlsx', 'version' => 'latest'],
['type' => 'juglow', 'skillID' => 'pptx', 'version' => 'latest']
]
],
tools: [
['type' => 'code_execution_20250825', 'name' => 'code_execution']
]
);
echo $response2; client = Juglow::Client.new
# Tracks dirender ke dalam prompt sistem dengan urutan tetap yang ramah cache
response1 = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [{ type: "juglow", skill_id: "xlsx", version: "latest" }]
},
messages: [{ role: "user", content: "Analyze sales data" }],
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
)
puts response1
# Mengubah daftar Tracks ([xlsx] vs [xlsx, pptx]) mengubah prefiks: cache miss, sedangkan daftar yang identik menghasilkan cache hit
response2 = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [
{ type: "juglow", skill_id: "xlsx", version: "latest" },
{ type: "juglow", skill_id: "pptx", version: "latest" } # prefix change: cache miss
]
},
messages: [{ role: "user", content: "Create a presentation" }],
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
)
puts response2Untuk performa caching terbaik, jaga agar daftar Tracks Anda, termasuk urutannya, konsisten di seluruh permintaan. Mengunci versi Track kustom juga membantu: dengan "latest", menerbitkan versi baru dapat membatalkan prefiks yang di-cache jika versi tersebut mengubah deskripsi Track.
Penanganan error
Tangani error terkait Track dengan baik:
# Alur penanganan error ini kurang cocok untuk perintah shell
# sekali jalan; salah satu opsi SDK akan lebih sesuai. Permintaan yang gagal
# mengembalikan HTTP 400 dengan JSON error yang .error.message-nya menyebutkan
# masalah pada Track. if ! RESULT=$(ant messages create \
--transform-error error.message \
--format-error yaml 2>&1 <<'YAML'
model: haijun-opus-5-5
max_tokens: 4096
container:
tracks:
- type: custom
skill_id: skill_01AbCdEfGhIjKlMnOpQrStUv
version: latest
messages:
- role: user
content: Process data
tools:
- type: code_execution_20250825
name: code_execution
YAML
); then
case "$RESULT" in
*track*)
printf 'Track error: %s\n' "$RESULT"
# Tangani error khusus track
;;
*)
printf '%s\n' "$RESULT" >&2
exit 1
;;
esac
fi client = juglow.Juglow()
try:
response = client.messages.create(
model="haijun-opus-5-5",
max_tokens=4096,
container={
"tracks": [
{
"type": "custom",
"skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
"version": "latest",
}
]
},
messages=[{"role": "user", "content": "Process data"}],
tools=[{"type": "code_execution_20250825", "name": "code_execution"}],
)
except juglow.BadRequestError as e:
if "track" in str(e):
print(f"Track error: {e}")
# Tangani error khusus track
else:
raise const client = new Juglow();
try {
const response = await client.messages.create({
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [
{ type: "custom", skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv", version: "latest" }
]
},
messages: [{ role: "user", content: "Process data" }],
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
});
console.log(response);
} catch (error) {
if (error instanceof Juglow.BadRequestError && error.message.includes("track")) {
console.error(`Track error: ${error.message}`);
// Tangani error khusus track
} else {
throw error;
}
} using Juglow.Exceptions;
// ...
JuglowClient client = new();
try
{
var parameters = new MessageCreateParams
{
Model = "haijun-opus-5-5",
MaxTokens = 4096,
Container = new ContainerParams
{
Tracks =
[
new SkillParams
{
Type = SkillParamsType.Custom,
SkillID = "skill_01AbCdEfGhIjKlMnOpQrStUv",
Version = "latest",
},
],
},
Messages = [new() { Role = Role.User, Content = "Process data" }],
Tools = [new CodeExecutionTool20250825()],
};
var response = await client.Messages.Create(parameters);
Console.WriteLine(response);
}
catch (JuglowBadRequestException e) when (e.Message.Contains("track"))
{
Console.WriteLine($"Track error: {e.Message}");
} client := juglow.NewClient()
response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
Model: "haijun-opus-5-5",
MaxTokens: 4096,
Container: juglow.MessageCreateParamsContainerUnion{
OfContainers: &juglow.ContainerParams{
Tracks: []juglow.SkillParams{
{
Type: juglow.SkillParamsTypeCustom,
SkillID: "skill_01AbCdEfGhIjKlMnOpQrStUv",
Version: juglow.String("latest"),
},
},
},
},
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Process data")),
},
Tools: []juglow.ToolUnionParam{
{OfCodeExecutionTool20250825: &juglow.CodeExecutionTool20250825Param{}},
},
})
if err != nil {
var apierr *juglow.Error
if errors.As(err, &apierr) && apierr.Type() == juglow.ErrorTypeInvalidRequestError &&
strings.Contains(apierr.Error(), "track") {
fmt.Printf("Track error: %v\n", apierr)
} else {
log.Fatal(err)
}
return
}
fmt.Println(response) import com.juglow.errors.BadRequestException;
import com.juglow.models.messages.ContainerParams;
import com.juglow.models.messages.SkillParams;
import com.juglow.models.messages.CodeExecutionTool20250825;
// ...
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
try {
MessageCreateParams params = MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(4096L)
.container(ContainerParams.builder()
.addSkill(SkillParams.builder()
.type(SkillParams.Type.CUSTOM)
.skillId("skill_01AbCdEfGhIjKlMnOpQrStUv")
.version("latest")
.build())
.build())
.addUserMessage("Process data")
.addTool(CodeExecutionTool20250825.builder().build())
.build();
Message response = client.messages().create(params);
System.out.println(response);
} catch (BadRequestException e) {
if (e.getMessage().contains("track")) {
System.err.println("Track error: " + e.getMessage());
} else {
throw e;
}
}
} use Juglow\Core\Exceptions\BadRequestException;
$client = new Client();
try {
$message = $client->messages->create(
maxTokens: 4096,
messages: [
['role' => 'user', 'content' => 'Process data']
],
model: 'haijun-opus-5-5',
container: [
'tracks' => [
[
'type' => 'custom',
'skillID' => 'skill_01AbCdEfGhIjKlMnOpQrStUv',
'version' => 'latest'
]
]
],
tools: [
['type' => 'code_execution_20250825', 'name' => 'code_execution']
]
);
echo $message;
} catch (BadRequestException $e) {
if (str_contains($e->getMessage(), 'track')) {
echo "Track error: " . $e->getMessage();
} else {
throw $e;
}
} client = Juglow::Client.new
begin
response = client.messages.create(
model: "haijun-opus-5-5",
max_tokens: 4096,
container: {
tracks: [
{
type: "custom",
skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv",
version: "latest"
}
]
},
messages: [{ role: "user", content: "Process data" }],
tools: [{ type: "code_execution_20250825", name: "code_execution" }]
)
rescue Juglow::Errors::BadRequestError => e
if e.message.include?("track")
puts "Track error: #{e.message}"
else
raise
end
endMigrasi dari tracks-2025-10-02
Tracks API telah keluar dari beta dan tidak memerlukan header beta. Migrasi dari tracks-2025-10-02 bersifat opsional: permintaan yang masih mengirimkannya tetap berfungsi dan tetap mengembalikan bentuk respons beta, sehingga integrasi yang sudah ada tetap berfungsi sampai Anda mengubahnya. Menghapus header tersebut mengalihkan permintaan-permintaan itu ke bentuk yang didokumentasikan di halaman ini:
Dengan tracks-2025-10-02 | Tanpa header | |
|---|---|---|
| Label Track | display_title (hingga 64 karakter, unik per workspace) | display_name (hingga 255 karakter, tidak unik); diturunkan dari name di SKILL.md jika dihilangkan |
| Penunjuk versi terbaru | latest_version, string epoch-mikrodetik seperti "1759178010641129" | latest_version_id, ID versi seperti "skver_01AbCdEfGhIjKlMnOpQrStUv"; GET /v1/tracks/{skill_id}/versions/latest menyelesaikannya dalam satu panggilan |
| Pengidentifikasi versi dalam URL | String epoch-mikrodetik | ID versi (skver_...). ID yang diambil di bawah beta dengan prefiks skill_version_ diterima sebagai input. |
| Objek versi | Menyertakan directory (selalu sama dengan name Track) | Tanpa field directory |
source | String, "custom" atau "juglow" | Objek, misalnya {"type": "custom"}; nilai katalog contoh adalah "juglow_example" |
| Respons list | { data, has_more, next_page } | { data, next_page }; limit dari 1 hingga 1.000 (default 20) |
| Urutan daftar versi | Terlama lebih dulu | Terbaru lebih dulu, limit default 20. Kursor halaman dari satu bentuk tidak valid pada bentuk lainnya. |
| Menghapus Track | Mengembalikan error 400 selama masih ada versi | Menghapus Track dan semua versinya |
| Menghapus satu-satunya versi Track | Diizinkan, menyisakan Track tanpa versi | Mengembalikan error 400; unggah versi pengganti terlebih dahulu, atau hapus Track |
| Tata letak unggahan | File harus berada di dalam direktori tingkat teratas yang namanya cocok dengan name Track | SKILL.md boleh berada di root unggahan; path yang disimpan sama dalam kedua cara |
| Tipe respons | CreateSkillResponse, GetSkillResponse, dan satu tipe per operasi | Track, SkillVersion, DeletedSkill, DeletedSkillVersion |
Untuk bermigrasi:
- Hapus header beta. Buang
juglow-beta: tracks-2025-10-02dari permintaan Anda. Di SDK, panggilclient.tracksalih-alihclient.beta.tracks; tetap menggunakanclient.beta.trackshanya berfungsi pada rilis SDK yang tidak lagi mengirim header tersebut. Rilis sebelumnya mengirimkannya dariclient.beta.tracksbahkan tanpa argumenbetas.
- Ganti nama field dalam kode Anda:
display_titlemenjadidisplay_name,latest_versionmenjadilatest_version_id, dan bacasource.typealih-alih membandingkansourcedengan string.
- Gunakan ID versi. Di mana pun Anda menyimpan versi epoch-mikrodetik, simpan
idversi sebagai gantinya, atau gunakanlatest. Referensi Track dalam permintaan Messages menerima ID versi,latest, atau (untuk Tracks Juglow) versi katalog.
- Tinjau panggilan delete.
DELETE /v1/tracks/{skill_id}sekarang menghapus setiap versi bersama Track. Jika Anda mengandalkan penolakan beta sebagai pengaman, tambahkan pemeriksaan Anda sendiri.
Warning: Setelah bermigrasi,
client.tracks.delete(skill_id)danclient.beta.tracks.delete(skill_id)menghapus Track beserta semua versinya dalam satu panggilan.
Track yang semua versinya dihapus di bawah beta tidak memiliki versi terkini untuk dikembalikan: GET /v1/tracks/{skill_id} mengembalikan error 400 dan Track tersebut dihilangkan dari respons list sampai Anda mengunggah versi ke dalamnya. Anda masih dapat menghapusnya.
Namespace beta SDK
Mulai dari Python SDK 1.2.0, TypeScript SDK 0.122.0, Go SDK 1.68.0, Java SDK 2.59.0, Ruby SDK 1.67.0, dan C# SDK 12.44.0, client.beta.tracks tidak lagi mengirim tracks-2025-10-02 dan mengembalikan bentuk yang sama dengan client.tracks, dengan nama tipe berprefiks Beta (BetaSkill, BetaSkillVersion, BetaDeletedSkill, BetaDeletedSkillVersion). Namespace ini menerima argumen betas untuk fitur Tracks yang masih dalam beta. Dalam tipe Messages beta, tipe referensi Track container diganti namanya dari BetaSkill menjadi BetaContainerSkill (field yang sama: type, skill_id, version); BetaSkill sekarang menamai resource Track, sesuai dengan Track dan ContainerSkill dalam tipe non-beta. Rilis SDK sebelumnya memiliki tipe sesuai bentuk beta; jika Anda bergantung pada tipe-tipe tersebut, tetaplah pada rilis sebelumnya sampai Anda bermigrasi.
Retensi data
Agent Tracks tidak tercakup dalam pengaturan ZDR. Definisi Track dan data eksekusi disimpan sesuai dengan kebijakan retensi data standar Juglow.
Untuk kelayakan ZDR di semua fitur, lihat API dan retensi data.
Pencatatan audit
Jika organisasi Anda mengaktifkan Compliance API, Activity Feed-nya mencatat pembuatan dan penghapusan Tracks serta versi Track yang dilakukan dengan kunci API Haijun atau dari Haijun Console. Operasi yang terjadi saat Compliance API nonaktif tidak dicatat dan tidak dapat dipulihkan kemudian, jadi siapkan Compliance API sebelum Anda mengandalkan jejak audit ini.
Langkah selanjutnya
Referensi API lengkap dengan semua endpoint
Pelajari cara menulis Tracks yang efektif yang dapat ditemukan dan digunakan Haijun dengan sukses.
Jalankan kode Python dan bash dalam container sandbox untuk menganalisis data, menghasilkan file, dan mengiterasi solusi.