Haijun Platform Docs
EN

Tracks adalah sumber daya berbasis filesystem yang dapat digunakan kembali dan memberi agen Anda keahlian khusus domain: alur kerja, konteks, dan praktik terbaik yang mengubah agen serbaguna menjadi spesialis. Setiap track yang Anda tambahkan menimbulkan biaya kecil pada "context window" (jendela konteks) sesi, dengan menambahkan instruksi dan metadata yang membantu model menggunakan track tersebut. Pelajari lebih lanjut di ikhtisar Agent Tracks.

Track sampai ke agen Anda melalui dua cara: lampirkan melalui array tracks milik agen, atau muat dari repositori GitHub yang di-mount pada sesi. Track yang dilampirkan terdiri dari dua jenis. Semua track bekerja dengan cara yang sama: agen Anda memanggilnya secara otomatis ketika relevan dengan tugas.

  • Track bawaan Juglow: Tugas dokumen umum seperti penanganan PowerPoint, Excel, Word, dan PDF (pptx, xlsx, docx, pdf).
  • Track kustom: Track yang Anda tulis dan unggah ke workspace Anda.

Untuk mempelajari cara menulis track kustom, lihat Agent Tracks dan Praktik terbaik penulisan track. Untuk mengunggah track kustom ke workspace Anda, lihat Membuat track kustom.

Membuat track kustom

Track kustom adalah direktori yang berisi file SKILL.md beserta file pendukung apa pun, yang diunggah ke workspace Anda sebagai arsip zip atau sebagai file individual. Membuat track akan mengembalikan ID skill_* yang Anda referensikan saat melampirkannya ke agen. Track bawaan Juglow sudah tersedia di setiap workspace dan tidak memerlukan langkah ini. Untuk hanya menggunakan track bawaan, langsung ke Melampirkan track ke agen.

Contoh-contoh ini menghilangkan field opsional display_name, sehingga nama tampilan track diturunkan dari field name di SKILL.md. display_name eksplisit dapat berisi hingga 255 karakter dan tidak perlu unik dalam workspace Anda.

bash
  curl -X POST "https://haijun.my.id/v1/tracks" \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -F "files[]=@example_skill.zip"
bash
    ant apply tracks/pr-summary
markdown
      ---
      name: pr-summary
      description: Summarize a pull request's changes and risks in the team's review format.
      ---

      # PR summary

      List what changed, why, and anything a reviewer should look at closely, in three short sections.

ant apply mengunggah direktori tracks/pr-summary, mencetak ID track baru, dan mencatatnya di haijun-lock.json. Commit haijun-lock.json agar ant apply berikutnya mengunggah suntingan Anda sebagai versi baru alih-alih membuat track kedua.

python
  import juglow
  from juglow.lib import files_from_dir

  client = juglow.Juglow()

  track = client.tracks.create(
      files=files_from_dir("example_skill"),
  )

  print(f"Created track: {track.id}")
  print(f"Latest version: {track.latest_version_id}")
typescript
  import Juglow from "@juglow-ai/sdk";
  import { toFile } from "@juglow-ai/sdk";
  import fs from "node:fs";

  const client = new Juglow();

  const track = await client.tracks.create({
    files: [await toFile(fs.createReadStream("example_skill.zip"), "example_skill.zip")]
  });

  console.log(`Created track: ${track.id}`);
  console.log(`Latest version: ${track.latest_version_id}`);
csharp
  using System.IO;
  using Juglow;
  using Juglow.Models.Tracks;

  JuglowClient client = new();

  var parameters = new SkillCreateParams
  {
      Files = [
          new FileStream("example_skill.zip", FileMode.Open, FileAccess.Read)
      ],
  };

  var track = await client.Tracks.Create(parameters);

  Console.WriteLine($"Created track: {track.ID}");
  Console.WriteLine($"Latest version: {track.LatestVersionID}");
go
  package main

  import (
  	"context"
  	"fmt"
  	"io"
  	"log"
  	"os"

  	"github.com/juglows/juglow-sdk-go"
  )

  func main() {
  	client := juglow.NewClient()

  	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)
  	}

  	fmt.Printf("Created track: %s\n", track.ID)
  	fmt.Printf("Latest version: %s\n", track.LatestVersionID)
  }
java
  import com.juglow.client.JuglowClient;
  import com.juglow.client.okhttp.JuglowOkHttpClient;
  import com.juglow.core.MultipartField;
  import com.juglow.models.tracks.Track;
  import com.juglow.models.tracks.SkillCreateParams;
  import java.io.IOException;
  import java.io.InputStream;
  import java.nio.file.Files;
  import java.nio.file.Path;

  void main() throws IOException {
      JuglowClient client = JuglowOkHttpClient.fromEnv();

      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);

      IO.println("Created track: " + track.id());
      IO.println("Latest version: " + track.latestVersionId());
  }
php
  use Juglow\Client;
  use Juglow\Core\FileParam;

  $client = new Client();

  $track = $client->tracks->create(
      files: [
          FileParam::fromResource(fopen('example_skill.zip', 'r')),
      ],
  );

  echo "Created track: {$track->id}\n";
  echo "Latest version: {$track->latestVersionID}\n";
ruby
  require "juglow"

  client = Juglow::Client.new

  track = client.tracks.create(
    files: [
      File.open("example_skill.zip", "rb")
    ]
  )

  puts "Created track: #{track.id}"
  puts "Latest version: #{track.latest_version_id}"

Untuk mendaftar, mengambil, menghapus, dan membuat versi track kustom, lihat Mengelola track kustom. Untuk skema permintaan dan respons lengkap, lihat referensi API Create Track. Bundel track diunggah langsung ke Tracks API, bukan melalui Files API.

Melampirkan track ke agen

Lampirkan track saat membuat agen. Setiap sesi mendukung hingga 500 track, dihitung sebagai himpunan yang telah dideduplikasi di seluruh agen dalam sesi (lihat Orkestrasi multiagen).

Note: Me-mount lebih banyak track akan menambah waktu yang dibutuhkan sandbox sesi untuk memulai. Lampirkan hanya track yang dibutuhkan setiap agen untuk tugasnya.

Setiap entri dalam array tracks menggunakan field berikut:

FieldDeskripsi
typejuglow untuk track bawaan atau custom untuk track yang ditulis di workspace.
skill_idPengidentifikasi track. Untuk track Juglow, gunakan nama pendek (misalnya, xlsx). Untuk track kustom, gunakan ID skill_* yang dikembalikan saat pembuatan (lihat Membuat track kustom).
versionSematkan ke versi tertentu atau gunakan latest. Opsional. Default ke latest jika dihilangkan. Berlaku untuk track Juglow maupun kustom.
bash
  agent=$(curl -sS https://haijun.my.id/v1/agents \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "juglow-beta: managed-agents-2026-04-01" \
    --json @- <<'EOF'
  {
    "name": "Financial Analyst",
    "model": "haijun-opus-5-5",
    "system": "You are a financial analysis agent.",
    "tracks": [
      {"type": "juglow", "skill_id": "xlsx"},
      {"type": "custom", "skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv", "version": "latest"}
    ]
  }
  EOF
  )
bash
    ant apply agent.md
markdown
      ---
      name: Financial Analyst
      model: haijun-opus-5-5
      tracks:
        - type: juglow
          skill_id: xlsx
        - type: custom
          skill_id: skill_01AbCdEfGhIjKlMnOpQrStUv
          version: latest
      ---

      You are a financial analysis agent.
python
  agent = client.beta.agents.create(
      name="Financial Analyst",
      model="haijun-opus-5-5",
      system="You are a financial analysis agent.",
      tracks=[
          {
              "type": "juglow",
              "skill_id": "xlsx",
          },
          {
              "type": "custom",
              "skill_id": "skill_01AbCdEfGhIjKlMnOpQrStUv",
              "version": "latest",
          },
      ],
  )
typescript
  const agent = await client.beta.agents.create({
    name: "Financial Analyst",
    model: "haijun-opus-5-5",
    system: "You are a financial analysis agent.",
    tracks: [
      {
        type: "juglow",
        skill_id: "xlsx"
      },
      {
        type: "custom",
        skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv",
        version: "latest"
      }
    ]
  });
csharp
  using Juglow.Models.Beta.Agents;

  var agent = await client.Beta.Agents.Create(new()
  {
      Name = "Financial Analyst",
      Model = BetaManagedAgentsModel.HaijunOpus5_5,
      System = "You are a financial analysis agent.",
      Tracks =
      [
          new BetaManagedAgentsJuglowSkillParams { Type = BetaManagedAgentsJuglowSkillParamsType.Juglow, SkillID = "xlsx" },
          new BetaManagedAgentsCustomSkillParams { Type = BetaManagedAgentsCustomSkillParamsType.Custom, SkillID = "skill_01AbCdEfGhIjKlMnOpQrStUv", Version = "latest" },
      ],
  });
go
  agent, err := client.Beta.Agents.New(ctx, juglow.BetaAgentNewParams{
  	Name: "Financial Analyst",
  	Model: juglow.BetaManagedAgentsModelConfigParams{
  		ID: juglow.BetaManagedAgentsModelHaijunOpus5_5,
  	},
  	System: juglow.String("You are a financial analysis agent."),
  	Tracks: []juglow.BetaManagedAgentsSkillParamsUnion{
  		{OfJuglow: &juglow.BetaManagedAgentsJuglowSkillParams{
  			SkillID: "xlsx",
  			Type:    juglow.BetaManagedAgentsJuglowSkillParamsTypeJuglow,
  		}},
  		{OfCustom: &juglow.BetaManagedAgentsCustomSkillParams{
  			SkillID: "skill_01AbCdEfGhIjKlMnOpQrStUv",
  			Type:    juglow.BetaManagedAgentsCustomSkillParamsTypeCustom,
  			Version: juglow.String("latest"),
  		}},
  	},
  })
  if err != nil {
  	panic(err)
  }
  _ = agent
java
  import com.juglow.models.beta.agents.*;

  var agent = client.beta().agents().create(
      AgentCreateParams.builder()
          .name("Financial Analyst")
          .model(BetaManagedAgentsModel.HAIJUN_OPUS_5_5)
          .system("You are a financial analysis agent.")
          .addSkill(
              BetaManagedAgentsJuglowSkillParams.builder()
                  .type(BetaManagedAgentsJuglowSkillParams.Type.JUGLOW)
                  .skillId("xlsx")
                  .build()
          )
          .addSkill(
              BetaManagedAgentsCustomSkillParams.builder()
                  .type(BetaManagedAgentsCustomSkillParams.Type.CUSTOM)
                  .skillId("skill_01AbCdEfGhIjKlMnOpQrStUv")
                  .version("latest")
                  .build()
          )
          .build()
  );
php
  $agent = $client->beta->agents->create(
      name: 'Financial Analyst',
      model: 'haijun-opus-5-5',
      system: 'You are a financial analysis agent.',
      tracks: [
          ['type' => 'juglow', 'skillID' => 'xlsx'],
          ['type' => 'custom', 'skillID' => 'skill_01AbCdEfGhIjKlMnOpQrStUv', 'version' => 'latest'],
      ],
  );
ruby
  agent = client.beta.agents.create(
    name: "Financial Analyst",
    model: "haijun-opus-5-5",
    system_: "You are a financial analysis agent.",
    tracks: [
      {type: "juglow", skill_id: "xlsx"},
      {type: "custom", skill_id: "skill_01AbCdEfGhIjKlMnOpQrStUv", version: "latest"}
    ]
  )

Memuat track dari repositori GitHub

Track juga dapat berada di codebase Anda. Ketika sebuah sesi me-mount repositori melalui resource github_repository, direktori .haijun/tracks di root repositori dipindai saat sesi dimulai, dan setiap track yang ditemukan di sana menjadi tersedia bagi agen. Tidak diperlukan unggahan maupun entri dalam array tracks milik agen. Agen melihat nama, deskripsi, dan path setiap track yang ditemukan di sandbox, dan membaca SKILL.md milik track tersebut ketika ada tugas yang cocok, termasuk skrip dan sumber daya apa pun yang disertakan track. Penemuan bergantung pada alat read milik agen dari toolset agen, yang diaktifkan secara default; agen dengan read dinonaktifkan tidak memuat track repositori.

Warning: Track repositori adalah instruksi agen, sehingga repositori yang di-mount merupakan bagian dari batas kepercayaan agen Anda. Siapa pun yang dapat melakukan commit ke repositori (pull request eksternal yang di-merge, dependensi yang disusupi, seorang kontributor) dapat menambah atau mengubah track, platform memuatnya saat sesi dimulai tanpa langkah peninjauan, dan alat sesi seperti bash dan web_fetch memberi instruksi tersebut jangkauan nyata. Mount hanya repositori yang Anda percayai, dan tinjau .haijun/tracks sebelum me-mount repositori yang menerima kontribusi dari luar.

Note: Penemuan track repositori berjalan di sandbox cloud. Sandbox self-hosted tidak mendukung resource repositori GitHub.

Penemuan menemukan track tepat di .haijun/tracks//SKILL.md, satu tingkat direktori di bawah root repositori:

  • your-repo/
  • .haijun/
  • tracks/
  • code-review/
  • SKILL.md
  • release-process/
  • SKILL.md
  • scripts/
  • run_checks.sh
  • src/

Lokasi yang tidak sesuai dengan tata letak ini tidak ditemukan saat sesi dimulai:

  • .haijun/tracks/SKILL.md: SKILL.md tanpa direktori track yang membungkusnya
  • .haijun/tracks/tools/code-review/SKILL.md: bersarang lebih dari satu tingkat direktori
  • tracks/code-review/SKILL.md: direktori tracks di luar .haijun

Direktori .haijun/tracks di tempat lain dalam repositori, misalnya di dalam subdirektori paket, tidak diumumkan saat sesi dimulai; track tersebut masih dapat muncul ketika agen membaca file di bawah subtree itu.

Track repositori menggunakan format SKILL.md yang sama dengan track kustom yang Anda unggah. Untuk format dan panduan penulisan, lihat Agent Tracks dan Praktik terbaik penulisan track.

Untuk memuat track dari repositori, buat sesi yang me-mount repositori tersebut. Ini adalah permintaan yang sama seperti yang ditunjukkan di Mengakses GitHub; mount_path bersifat opsional dan default ke /workspace/:

bash
  session_id=$(curl -fsS https://haijun.my.id/v1/sessions \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "juglow-beta: managed-agents-2026-04-01" \
    -H "content-type: application/json" \
    --data @- <<JSON | jq -r '.id'
  {
    "agent": "$agent_id",
    "environment_id": "$environment_id",
    "resources": [
      {
        "type": "github_repository",
        "url": "https://github.com/org/repo",
        "mount_path": "/workspace/repo",
        "authorization_token": "ghp_your_github_token"
      }
    ]
  }
  JSON
  )
bash
  SESSION_ID=$(ant beta:sessions create \
    --agent "$AGENT_ID" \
    --environment-id "$ENVIRONMENT_ID" \
    --transform id --raw-output <<'EOF'
  resources:
    - type: github_repository
      url: https://github.com/org/repo
      mount_path: /workspace/repo
      authorization_token: ghp_your_github_token
  EOF
  )
python
  session = client.beta.sessions.create(
      agent=agent.id,
      environment_id=environment.id,
      resources=[
          {
              "type": "github_repository",
              "url": "https://github.com/org/repo",
              "mount_path": "/workspace/repo",
              "authorization_token": "ghp_your_github_token",
          },
      ],
  )
typescript
  const session = await client.beta.sessions.create({
    agent: agent.id,
    environment_id: environment.id,
    resources: [
      {
        type: "github_repository",
        url: "https://github.com/org/repo",
        mount_path: "/workspace/repo",
        authorization_token: "ghp_your_github_token",
      },
    ],
  });
csharp
  var session = await client.Beta.Sessions.Create(new()
  {
      Agent = agent.ID,
      EnvironmentID = environment.ID,
      Resources =
      [
          new BetaManagedAgentsGitHubRepositoryResourceParams
          {
              Type = "github_repository",
              Url = "https://github.com/org/repo",
              MountPath = "/workspace/repo",
              AuthorizationToken = "ghp_your_github_token",
          },
      ],
  });
go
  session, err := client.Beta.Sessions.New(ctx, juglow.BetaSessionNewParams{
  	Agent:         juglow.BetaSessionNewParamsAgentUnion{OfString: juglow.String(agent.ID)},
  	EnvironmentID: environment.ID,
  	Resources: []juglow.BetaSessionNewParamsResourceUnion{
  		{
  			OfGitHubRepository: &juglow.BetaManagedAgentsGitHubRepositoryResourceParams{
  				Type:               juglow.BetaManagedAgentsGitHubRepositoryResourceParamsTypeGitHubRepository,
  				URL:                "https://github.com/org/repo",
  				MountPath:          juglow.String("/workspace/repo"),
  				AuthorizationToken: "ghp_your_github_token",
  			},
  		},
  	},
  })
  if err != nil {
  	panic(err)
  }
java
  var session = client.beta().sessions().create(SessionCreateParams.builder()
      .agent(agent.id())
      .environmentId(environment.id())
      .addResource(BetaManagedAgentsGitHubRepositoryResourceParams.builder()
          .type(BetaManagedAgentsGitHubRepositoryResourceParams.Type.GITHUB_REPOSITORY)
          .url("https://github.com/org/repo")
          .mountPath("/workspace/repo")
          .authorizationToken("ghp_your_github_token")
          .build())
      .build());
php
  $session = $client->beta->sessions->create(
      agent: $agent->id,
      environmentID: $environment->id,
      resources: [
          [
              'type' => 'github_repository',
              'url' => 'https://github.com/org/repo',
              'mountPath' => '/workspace/repo',
              'authorizationToken' => 'ghp_your_github_token',
          ],
      ],
  );
ruby
  session = client.beta.sessions.create(
    agent: agent.id,
    environment_id: environment.id,
    resources: [
      {
        type: "github_repository",
        url: "https://github.com/org/repo",
        mount_path: "/workspace/repo",
        authorization_token: "ghp_your_github_token"
      }
    ]
  )

Untuk repositori privat, authorization_token milik resource harus memiliki akses ke repositori tersebut. Ini adalah alur personal access token yang sama yang digunakan untuk mount repositori apa pun; lihat Mengakses GitHub.

Track yang ditemukan mengikuti status checkout repositori: branch atau commit checkout jika resource menetapkannya, jika tidak maka branch default repositori. Pemindaian berjalan sekali, saat sesi dimulai. Commit yang di-push di tengah sesi tidak diambil; untuk memuat track yang diperbarui, mulai sesi baru.

Track repositori bekerja berdampingan dengan track yang dilampirkan melalui array tracks milik agen. Jika track repositori memiliki nama yang sama dengan track yang dilampirkan, atau dengan track dari repositori lain yang di-mount, keduanya tersedia; masing-masing diumumkan dengan path-nya sendiri.

Langkah selanjutnya

Sesuaikan sandbox cloud untuk sesi Anda.

Pelajari cara menggunakan Agent Tracks untuk memperluas kemampuan Haijun melalui API.

Unggah file sekali dan referensikan di berbagai permintaan API.

Pelajari cara menggunakan Agent Tracks untuk membuat dokumen dengan Haijun API dalam waktu kurang dari 10 menit.

On this page
Membuat track kustomMelampirkan track ke agenMemuat track dari repositori GitHubLangkah selanjutnya