Haijun Platform Docs
EN

Sebuah "outcome" (hasil akhir) memberi tahu sesi seperti apa hasil akhir yang seharusnya dan bagaimana mengukur kualitasnya. Agen bekerja menuju target tersebut, mengevaluasi diri dan beriterasi hingga outcome terpenuhi.

Saat Anda mendefinisikan outcome, harness secara otomatis menyediakan sebuah grader (penilai) untuk mengevaluasi artefak terhadap sebuah rubrik. Grader menggunakan "context window" (jendela konteks) terpisah agar tidak terpengaruh oleh pilihan implementasi agen utama.

Grader mengembalikan penjelasan yang merangkum kriteria mana yang lolos atau gagal, atau mengonfirmasi bahwa artefak memenuhi rubrik. Umpan balik tersebut diserahkan kembali kepada agen untuk iterasi berikutnya.

Membuat rubrik

Rubrik adalah dokumen markdown yang menjelaskan penilaian per kriteria. Rubrik bersifat wajib.

Tips menulis rubrik yang efektif

Susun rubrik sebagai kriteria yang eksplisit dan dapat dinilai, seperti "CSV berisi kolom price dengan nilai numerik" alih-alih "Datanya terlihat bagus." Grader menilai setiap kriteria secara independen, sehingga kriteria yang samar menghasilkan evaluasi yang tidak konsisten.

Jika Anda tidak memiliki rubrik, cobalah memberi Haijun contoh artefak yang sudah diketahui bagus dan minta Haijun menganalisis apa yang membuat konten tersebut bagus, lalu ubah analisis itu menjadi rubrik. Pendekatan jalan tengah ini sering menghasilkan hasil yang lebih baik daripada menulis kriteria dari nol.

Contoh rubrik:

markdown
# DCF Model Rubric

## Revenue Projections
- Uses historical revenue data from the last 5 fiscal years
- Projects revenue for at least 5 years forward
- Growth rate assumptions are explicitly stated and reasonable

## Cost Structure
- COGS and operating expenses are modeled separately
- Margins are consistent with historical trends or deviations are justified

## Discount Rate
- WACC is calculated with stated assumptions for cost of equity and cost of debt
- Beta, risk-free rate, and equity risk premium are sourced or justified

## Terminal Value
- Uses either perpetuity growth or exit multiple method (stated which)
- Terminal growth rate does not exceed long-term GDP growth

## Output Quality
- All figures are in a single .xlsx file with clearly labeled sheets
- Key assumptions are on a separate "Assumptions" sheet
- Sensitivity analysis on WACC and terminal growth rate is included

Teruskan rubrik sebagai teks inline pada user.define_outcome (lihat Membuat sesi dengan outcome), atau unggah melalui Files API untuk digunakan kembali di berbagai sesi.

bash
  curl -fsSL https://haijun.my.id/v1/files \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "juglow-beta: managed-agents-2026-04-01" \
    -F file=@/tmp/rubric.md
bash
  ant files upload --file /tmp/rubric.md
python
  import time
  from pathlib import Path

  from juglow import Juglow

  client = Juglow()

  RUBRIC = """# DCF Model Rubric

  ## Revenue Projections
  - Uses historical revenue data from the last 5 fiscal years
  - Projects revenue for at least 5 years forward

  ## Output Quality
  - All figures are in a single .xlsx file with clearly labeled sheets
  """
  Path("/tmp/rubric.md").write_text(RUBRIC)

  rubric = client.files.upload(file=Path("/tmp/rubric.md"))
  print(f"Uploaded rubric: {rubric.id}")
typescript
  import { writeFile, readFile } from "node:fs/promises";

  import Juglow from "@juglow-ai/sdk";
  import { toFile } from "@juglow-ai/sdk";

  const client = new Juglow();

  const RUBRIC = `# DCF Model Rubric

  ## Revenue Projections
  - Uses historical revenue data from the last 5 fiscal years
  - Projects revenue for at least 5 years forward

  ## Output Quality
  - All figures are in a single .xlsx file with clearly labeled sheets
  `;
  await writeFile("/tmp/rubric.md", RUBRIC);

  const rubric = await client.files.upload({
    file: await toFile(readFile("/tmp/rubric.md"), "/tmp/rubric.md"),
  });
  console.log(`Uploaded rubric: ${rubric.id}`);
csharp
  using Juglow;
  using Juglow.Models.Beta.Agents;
  using Juglow.Models.Beta.Environments;
  using Juglow.Models.Beta.Sessions;
  using Juglow.Models.Beta.Sessions.Events;
  using Juglow.Models.Files;

  var client = new JuglowClient();

  const string Rubric = """
      # DCF Model Rubric

      ## Revenue Projections
      - Uses historical revenue data from the last 5 fiscal years
      - Projects revenue for at least 5 years forward

      ## Output Quality
      - All figures are in a single .xlsx file with clearly labeled sheets
      """;
  await File.WriteAllTextAsync("/tmp/rubric.md", Rubric);

  var rubric = await client.Files.Upload(new()
  {
      File = File.OpenRead("/tmp/rubric.md"),
  });
  Console.WriteLine($"Uploaded rubric: {rubric.ID}");
go
  package main

  import (
  	"context"
  	"fmt"
  	"io"
  	"os"
  	"time"

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

  const rubric = `# DCF Model Rubric

  ## Revenue Projections
  - Uses historical revenue data from the last 5 fiscal years
  - Projects revenue for at least 5 years forward

  ## Output Quality
  - All figures are in a single .xlsx file with clearly labeled sheets
  `

  func main() {
  	ctx := context.Background()
  	client := juglow.NewClient()

  	if err := os.WriteFile("/tmp/rubric.md", []byte(rubric), 0o644); err != nil {
  		panic(err)
  	}

  	f, err := os.Open("/tmp/rubric.md")
  	if err != nil {
  		panic(err)
  	}

  	uploaded, err := client.Files.Upload(ctx, juglow.FileUploadParams{
  		File: juglow.File(f, "rubric.md", "text/markdown"),
  	})
  	if err != nil {
  		panic(err)
  	}
  	fmt.Printf("Uploaded rubric: %s\n", uploaded.ID)
java
  import com.juglow.client.okhttp.JuglowOkHttpClient;
  import com.juglow.core.http.HttpResponse;
  import com.juglow.models.beta.JuglowBeta;
  import com.juglow.models.beta.agents.AgentCreateParams;
  import com.juglow.models.beta.agents.BetaManagedAgentsAgentToolset20260401Params;
  import com.juglow.models.beta.agents.BetaManagedAgentsModel;
  import com.juglow.models.beta.environments.BetaCloudConfigParams;
  import com.juglow.models.beta.environments.EnvironmentCreateParams;
  import com.juglow.models.beta.files.FileListParams;
  import com.juglow.models.beta.sessions.SessionCreateParams;
  import com.juglow.models.beta.sessions.events.BetaManagedAgentsTextRubricParams;
  import com.juglow.models.beta.sessions.events.BetaManagedAgentsUserDefineOutcomeEventParams;
  import com.juglow.models.beta.sessions.events.BetaManagedAgentsUserInterruptEventParams;
  import com.juglow.models.beta.sessions.events.EventSendParams;
  import com.juglow.models.files.FileUploadParams;

  import java.io.InputStream;
  import java.nio.file.Files;
  import java.nio.file.Path;
  import java.nio.file.StandardCopyOption;

  void main() throws Exception {
      var client = JuglowOkHttpClient.fromEnv();

      var RUBRIC = """
          # DCF Model Rubric

          ## Revenue Projections
          - Uses historical revenue data from the last 5 fiscal years
          - Projects revenue for at least 5 years forward

          ## Output Quality
          - All figures are in a single .xlsx file with clearly labeled sheets
          """;
      Files.writeString(Path.of("/tmp/rubric.md"), RUBRIC);

      var rubric = client.files().upload(
          FileUploadParams.builder()
              .file(Path.of("/tmp/rubric.md"))
              .build());
      IO.println("Uploaded rubric: " + rubric.id());
php
  use Juglow\Client;
  use Juglow\Core\FileParam;

  $client = new Client();

  $rubricText = <<<'MD'
  # DCF Model Rubric

  ## Revenue Projections
  - Uses historical revenue data from the last 5 fiscal years
  - Projects revenue for at least 5 years forward

  ## Output Quality
  - All figures are in a single .xlsx file with clearly labeled sheets
  MD;
  file_put_contents('/tmp/rubric.md', $rubricText);

  $rubric = $client->files->upload(
      file: FileParam::fromResource(fopen('/tmp/rubric.md', 'r'), contentType: 'text/markdown'),
  );
  echo "Uploaded rubric: {$rubric->id}\n";
ruby
  require "juglow"
  require "pathname"

  client = Juglow::Client.new

  RUBRIC = <<~MD
    # DCF Model Rubric

    ## Revenue Projections
    - Uses historical revenue data from the last 5 fiscal years
    - Projects revenue for at least 5 years forward

    ## Output Quality
    - All figures are in a single .xlsx file with clearly labeled sheets
  MD
  File.write("/tmp/rubric.md", RUBRIC)

  rubric = client.files.upload(file: Pathname.new("/tmp/rubric.md"))
  puts "Uploaded rubric: #{rubric.id}"

Membuat sesi dengan outcome

Contoh berikut membuat sebuah sesi untuk agen dan environment yang sudah ada (keduanya dibuat secara terpisah), lalu mengirim event user.define_outcome. Agen segera mulai bekerja. Tidak diperlukan event pesan pengguna tambahan.

bash
  # Membuat sesi
  session=$(curl -fsSL 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" \
    --json @- <<EOF
  {
    "agent": "$AGENT_ID",
    "environment_id": "$ENVIRONMENT_ID",
    "title": "Financial analysis on Costco"
  }
  EOF
  )
  SESSION_ID=$(jq -r '.id' <<<"$session")

  # Mendefinisikan hasil — agen mulai bekerja begitu menerimanya
  curl -fsSL "https://haijun.my.id/v1/sessions/$SESSION_ID/events" \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "juglow-beta: managed-agents-2026-04-01" \
    --json @- >/dev/null <<EOF
  {
    "events": [
      {
        "type": "user.define_outcome",
        "description": "Build a DCF model for Costco in .xlsx",
        "rubric": {"type": "text", "content": "# DCF Model Rubric\n..."},
        "max_iterations": 5
      }
    ]
  }
  EOF
  # atau: "rubric": {"type": "file", "file_id": "$RUBRIC_ID"}
  # "max_iterations" bersifat opsional; default 3, maksimum 20
bash
  # Buat sesi
  SESSION_ID=$(ant beta:sessions create \
    --agent "$AGENT_ID" \
    --environment-id "$ENVIRONMENT_ID" \
    --title "Financial analysis on Costco" \
    --transform id --raw-output)

  # Definisikan hasil — agen mulai bekerja saat diterima
  ant beta:sessions:events send --session-id "$SESSION_ID" <<YAML
  events:
    - type: user.define_outcome
      description: Build a DCF model for Costco in .xlsx
      rubric: {type: file, file_id: $RUBRIC_ID}
      # or: rubric: {type: text, content: "..."}
      max_iterations: 5  # optional; default 3, max 20
  YAML
python
  # Buat sesi
  session = client.beta.sessions.create(
      agent=agent.id,
      environment_id=environment.id,
      title="Financial analysis on Costco",
  )

  # Definisikan hasil — agen mulai bekerja saat menerimanya
  client.beta.sessions.events.send(
      session_id=session.id,
      events=[
          {
              "type": "user.define_outcome",
              "description": "Build a DCF model for Costco in .xlsx",
              "rubric": {"type": "text", "content": RUBRIC},
              # atau: "rubric": {"type": "file", "file_id": rubric.id},
              "max_iterations": 5,  # optional; default 3, max 20
          }
      ],
  )
typescript
  // Buat sesi
  const session = await client.beta.sessions.create({
    agent: agent.id,
    environment_id: environment.id,
    title: "Financial analysis on Costco",
  });

  // Definisikan hasil — agen mulai bekerja saat menerimanya
  await client.beta.sessions.events.send(session.id, {
    events: [
      {
        type: "user.define_outcome",
        description: "Build a DCF model for Costco in .xlsx",
        rubric: { type: "text", content: RUBRIC },
        // atau: rubric: { type: "file", file_id: rubric.id },
        max_iterations: 5, // optional; default 3, max 20
      },
    ],
  });
csharp
  // Buat sesi
  var session = await client.Beta.Sessions.Create(new()
  {
      Agent = agent.ID,
      EnvironmentID = environment.ID,
      Title = "Financial analysis on Costco",
  });

  // Definisikan hasil — agen mulai bekerja saat diterima
  await client.Beta.Sessions.Events.Send(session.ID, new()
  {
      Events =
      [
          new BetaManagedAgentsUserDefineOutcomeEventParams
          {
              Type = BetaManagedAgentsUserDefineOutcomeEventParamsType.UserDefineOutcome,
              Description = "Build a DCF model for Costco in .xlsx",
              Rubric = new BetaManagedAgentsTextRubricParams
              {
                  Type = BetaManagedAgentsTextRubricParamsType.Text,
                  Content = Rubric,
              },
              // atau: Rubric = new BetaManagedAgentsFileRubricParams
              //     { Type = BetaManagedAgentsFileRubricParamsType.File, FileID = rubric.ID },
              MaxIterations = 5, // optional; default 3, max 20
          },
      ],
  });
go
  // Buat sesi
  session, err := client.Beta.Sessions.New(ctx, juglow.BetaSessionNewParams{
  	Agent: juglow.BetaSessionNewParamsAgentUnion{
  		OfString: juglow.String(agent.ID),
  	},
  	EnvironmentID: environment.ID,
  	Title:         juglow.String("Financial analysis on Costco"),
  })
  if err != nil {
  	panic(err)
  }

  // Definisikan hasil — agen mulai bekerja saat diterima
  _, err = client.Beta.Sessions.Events.Send(ctx, session.ID, juglow.BetaSessionEventSendParams{
  	Events: []juglow.BetaManagedAgentsEventParamsUnion{{
  		OfUserDefineOutcome: &juglow.BetaManagedAgentsUserDefineOutcomeEventParams{
  			Type:        juglow.BetaManagedAgentsUserDefineOutcomeEventParamsTypeUserDefineOutcome,
  			Description: "Build a DCF model for Costco in .xlsx",
  			Rubric: juglow.BetaManagedAgentsUserDefineOutcomeEventParamsRubricUnion{
  				OfText: &juglow.BetaManagedAgentsTextRubricParams{
  					Type:    juglow.BetaManagedAgentsTextRubricParamsTypeText,
  					Content: rubric,
  				},
  			},
  			// atau: OfFile: &juglow.BetaManagedAgentsFileRubricParams{
  			//     Type: juglow.BetaManagedAgentsFileRubricParamsTypeFile, FileID: uploaded.ID},
  			MaxIterations: juglow.Int(5), // optional; default 3, max 20
  		},
  	}},
  })
  if err != nil {
  	panic(err)
  }
java
  // Buat sesi
  var session = client.beta().sessions().create(
      SessionCreateParams.builder()
          .agent(agent.id())
          .environmentId(environment.id())
          .title("Financial analysis on Costco")
          .build());

  // Definisikan hasil — agen mulai bekerja saat menerimanya
  client.beta().sessions().events().send(
      session.id(),
      EventSendParams.builder()
          .addEvent(BetaManagedAgentsUserDefineOutcomeEventParams.builder()
              .type(BetaManagedAgentsUserDefineOutcomeEventParams.Type.USER_DEFINE_OUTCOME)
              .description("Build a DCF model for Costco in .xlsx")
              .rubric(BetaManagedAgentsTextRubricParams.builder()
                  .type(BetaManagedAgentsTextRubricParams.Type.TEXT)
                  .content(RUBRIC)
                  .build())
              // atau: .rubric(BetaManagedAgentsFileRubricParams.builder()
              //     .type(BetaManagedAgentsFileRubricParams.Type.FILE).fileId(rubric.id()).build())
              .maxIterations(5) // optional; default 3, max 20
              .build())
          .build());
php
  // Buat sesi
  $session = $client->beta->sessions->create(
      agent: $agent->id,
      environmentID: $environment->id,
      title: 'Financial analysis on Costco',
  );

  // Definisikan hasil — agen mulai bekerja saat diterima
  $client->beta->sessions->events->send(
      $session->id,
      events: [
          [
              'type' => 'user.define_outcome',
              'description' => 'Build a DCF model for Costco in .xlsx',
              'rubric' => ['type' => 'text', 'content' => $rubricText],
              // atau: 'rubric' => ['type' => 'file', 'file_id' => $rubric->id],
              'max_iterations' => 5, // optional; default 3, max 20
          ],
      ],
  );
ruby
  # Buat sesi
  session = client.beta.sessions.create(
    agent: agent.id,
    environment_id: environment.id,
    title: "Financial analysis on Costco"
  )

  # Definisikan hasil — agen mulai bekerja saat menerimanya
  client.beta.sessions.events.send_(
    session.id,
    events: [
      {
        type: "user.define_outcome",
        description: "Build a DCF model for Costco in .xlsx",
        rubric: {type: "text", content: RUBRIC},
        # atau: rubric: {type: "file", file_id: rubric.id},
        max_iterations: 5 # optional; default 3, max 20
      }
    ]
  )

Note: Anda juga dapat mendefinisikan outcome di dalam permintaan pembuatan itu sendiri: teruskan satu event user.define_outcome dalam initial_events untuk membuat sesi dan memulai pekerjaan menuju outcome dalam satu panggilan.

Event outcome

Kemajuan pada sesi berorientasi outcome ditampilkan pada stream event.

  • Event agent.* (seperti pesan dan penggunaan alat) menunjukkan kemajuan menuju outcome.
  • Event span.outcome_evaluation_* hanya dipancarkan untuk sesi berorientasi outcome dan menunjukkan jumlah loop iterasi serta proses umpan balik grader.
  • Anda juga dapat mengirim event user.message ke sesi berorientasi outcome untuk mengarahkan pekerjaan agen seiring kemajuannya, tetapi ini tidak wajib: agen bekerja menuju outcome secara mandiri, beriterasi hingga berhasil atau kehabisan iterasi.
  • Event user.interrupt menjeda pekerjaan pada outcome saat ini dan menandai span.outcome_evaluation_end.result sebagai interrupted, sehingga Anda dapat memulai outcome baru.
  • Setelah evaluasi outcome terakhir, sesi dapat dilanjutkan sebagai sesi percakapan, atau outcome baru dapat dimulai. Sesi mempertahankan riwayat outcome sebelumnya.

Event pengguna define outcome

Note: Hanya satu outcome yang didukung dalam satu waktu, tetapi Anda dapat merangkai outcome secara berurutan. Untuk melakukannya, kirim event user.define_outcome baru setelah event terminal span.outcome_evaluation_end dari outcome sebelumnya.

Ini adalah event yang Anda kirim untuk memulai sebuah outcome. Event ini dipantulkan kembali saat diterima, termasuk timestamp processed_at dan outcome_id.

json
{
  "type": "user.define_outcome",
  "description": "Build a DCF model for Costco in .xlsx",
  "rubric": { "type": "file", "file_id": "file_01..." },
  "max_iterations": 5
}

Awal evaluasi outcome

Dipancarkan saat grader memulai evaluasi atas satu loop iterasi. Field iteration adalah penghitung revisi berindeks 0: 0 adalah evaluasi pertama, 1 adalah evaluasi ulang setelah revisi pertama, dan seterusnya.

json
{
  "type": "span.outcome_evaluation_start",
  "id": "sevt_01def...",
  "outcome_id": "outc_01a...",
  "iteration": 0,
  "processed_at": "2026-03-25T14:01:45Z"
}

Evaluasi outcome sedang berlangsung

Heartbeat yang dipancarkan selama grader berjalan. Penalaran internal grader bersifat tertutup: Anda melihat bahwa grader sedang bekerja, bukan apa yang dipikirkannya.

json
{
  "type": "span.outcome_evaluation_ongoing",
  "id": "sevt_01ghi...",
  "outcome_id": "outc_01a...",
  "iteration": 0,
  "processed_at": "2026-03-25T14:02:10Z"
}

Akhir evaluasi outcome

Dipancarkan ketika siklus evaluasi outcome berakhir: setelah grader selesai mengevaluasi satu iterasi, atau ketika sesi diinterupsi saat sebuah outcome sedang aktif. Field result menunjukkan apa yang terjadi selanjutnya.

HasilSelanjutnya
satisfiedSesi beralih ke idle.
needs_revisionAgen memulai siklus iterasi baru.
max_iterations_reachedSatu giliran pengakuan terakhir menyusul sebelum sesi beralih ke idle. Tidak ada evaluasi lebih lanjut yang dijalankan.
failedSesi beralih ke idle. Dikembalikan ketika rubrik tidak berlaku untuk deliverable, misalnya jika deskripsi dan rubrik saling bertentangan.
interruptedDipancarkan ketika sesi diinterupsi saat sebuah outcome sedang aktif, bahkan jika evaluasi belum dimulai. Jika tidak ada outcome_evaluation_start yang terpicu sebelum interupsi, outcome_evaluation_start_id berupa string kosong.
json
{
  "type": "span.outcome_evaluation_end",
  "id": "sevt_01jkl...",
  "outcome_evaluation_start_id": "sevt_01def...",
  "outcome_id": "outc_01a...",
  "result": "satisfied",
  "explanation": "All 12 criteria met: revenue projections use 5 years of historical data, WACC assumptions are stated, sensitivity table is included...",
  "iteration": 0,
  "usage": {
    "input_tokens": 2400,
    "output_tokens": 350,
    "cache_creation_input_tokens": 0,
    "cache_read_input_tokens": 1800
  },
  "processed_at": "2026-03-25T14:03:00Z"
}

Memeriksa status outcome

Anda dapat mendengarkan stream event untuk span.outcome_evaluation_end, atau melakukan polling GET /v1/sessions/{session_id} dan membaca outcome_evaluations[].result. Hingga evaluasi selesai, result melaporkan pending, running, atau evaluating:

bash
  curl -fsSL "https://haijun.my.id/v1/sessions/$SESSION_ID" \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "juglow-beta: managed-agents-2026-04-01"
bash
  ant beta:sessions retrieve --session-id "$SESSION_ID"
python
  session = client.beta.sessions.retrieve(session.id)

  for outcome in session.outcome_evaluations:
      print(f"{outcome.outcome_id}: {outcome.result}")
      # outc_01a...: satisfied
typescript
  const retrieved = await client.beta.sessions.retrieve(session.id);

  for (const outcome of retrieved.outcome_evaluations) {
    console.log(`${outcome.outcome_id}: ${outcome.result}`);
    // outc_01a...: satisfied
  }
csharp
  session = await client.Beta.Sessions.Retrieve(session.ID);

  foreach (var outcome in session.OutcomeEvaluations)
  {
      Console.WriteLine($"{outcome.OutcomeID}: {outcome.Result}");
      // outc_01a...: satisfied
  }
go
  session, err = client.Beta.Sessions.Get(ctx, session.ID, juglow.BetaSessionGetParams{})
  if err != nil {
  	panic(err)
  }

  for _, outcome := range session.OutcomeEvaluations {
  	fmt.Printf("%s: %s\n", outcome.OutcomeID, outcome.Result)
  	// outc_01a...: satisfied
  }
java
  var retrieved = client.beta().sessions().retrieve(session.id());

  for (var outcome : retrieved.outcomeEvaluations()) {
      IO.println(outcome.outcomeId() + ": " + outcome.result());
      // outc_01a...: satisfied
  }
php
  $session = $client->beta->sessions->retrieve($session->id);

  foreach ($session->outcomeEvaluations as $outcome) {
      echo "{$outcome->outcomeID}: {$outcome->result}\n";
      // outc_01a...: satisfied
  }
ruby
  session = client.beta.sessions.retrieve(session.id)

  session.outcome_evaluations.each do
    puts "#{it.outcome_id}: #{it.result}"
    # outc_01a...: satisfied
  end

Mengambil deliverable

Agen menulis file output ke /mnt/session/outputs/ di dalam sandbox. Untuk mengambilnya, daftarkan file melalui Files API dengan ID sesi sebagai scope_id, lalu unduh berdasarkan ID. Pemfilteran berdasarkan scope_id memerlukan header beta managed-agents-2026-04-01 pada permintaan list, sehingga contoh SDK dan CLI melakukan panggilan tersebut melalui namespace beta dan meneruskan header secara eksplisit. File muncul dalam daftar tak lama setelah agen selesai menulisnya, terkadang beberapa detik setelah sesi menjadi idle. Jika file yang Anda harapkan belum terdaftar, lakukan list lagi setelah jeda singkat; setelah file muncul dalam daftar, pengunggahannya telah selesai.

bash
  # Mencantumkan file yang dihasilkan oleh sesi ini
  # Pemfilteran scope_id memerlukan beta managed-agents
  curl -fsSL "https://haijun.my.id/v1/files?scope_id=$SESSION_ID" \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "juglow-beta: managed-agents-2026-04-01"

  # Mengunduh file
  FILE_ID=$(curl -fsSL "https://haijun.my.id/v1/files?scope_id=$SESSION_ID" \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "juglow-beta: managed-agents-2026-04-01" | jq -r '.data[0].id // empty')
  if [[ -n $FILE_ID ]]; then
    curl -fsSL "https://haijun.my.id/v1/files/$FILE_ID/content" \
      -H "x-api-key: $JUGLOW_API_KEY" \
      -H "juglow-version: 2023-06-01" \
      -H "juglow-beta: managed-agents-2026-04-01" \
      -o /tmp/output.txt
  fi
bash
  # Daftar file yang dihasilkan oleh sesi ini
  # Pemfilteran scope_id memerlukan beta managed-agents pada permintaan files
  ant beta:files list --scope-id "$SESSION_ID" --beta managed-agents-2026-04-01

  # Unduh file
  FILE_ID=$(ant beta:files list --scope-id "$SESSION_ID" \
    --beta managed-agents-2026-04-01 \
    --transform 'data[0].id' --raw-output)
  if [[ -n $FILE_ID ]]; then
    ant files download --file-id "$FILE_ID" --output /tmp/output.txt
  fi
python
  # Daftar file yang dihasilkan oleh sesi ini
  # Pemfilteran scope_id memerlukan beta managed-agents pada permintaan files
  files = client.beta.files.list(scope_id=session.id, betas=["managed-agents-2026-04-01"])
  for file in files:
      print(file.id, file.filename)

  # Unduh file
  if files.data:
      content = client.files.download(files.data[0].id)
      content.write_to_file("/tmp/output.txt")
typescript
  // Daftar file yang dihasilkan oleh sesi ini
  // Pemfilteran scope_id memerlukan beta managed-agents pada permintaan files
  const files = await client.beta.files.list({
    scope_id: session.id,
    betas: ["managed-agents-2026-04-01"],
  });
  for (const file of files.data) {
    console.log(file.id, file.filename);
  }

  // Unduh file
  if (files.data.length > 0) {
    const content = await client.files.download(files.data[0].id);
    await writeFile("/tmp/output.txt", new Uint8Array(await content.arrayBuffer()));
  }
csharp
  // Daftar file yang dihasilkan oleh sesi ini
  // (pemfilteran scope_id memerlukan beta managed-agents pada permintaan files)
  var files = await client.Beta.Files.List(new()
  {
      ScopeID = session.ID,
      Betas = ["managed-agents-2026-04-01"],
  });
  foreach (var file in files.Items)
  {
      Console.WriteLine($"{file.ID} {file.Filename}");
  }

  // Unduh file
  if (files.Items.Count > 0)
  {
      using var download = await client.Files.Download(files.Items[0].ID);
      await using var output = File.Create("/tmp/output.txt");
      await (await download.ReadAsStream()).CopyToAsync(output);
  }
go
  // Daftar file yang dihasilkan oleh sesi ini
  // (pemfilteran scope_id memerlukan beta managed-agents pada permintaan files)
  files, err := client.Beta.Files.List(ctx, juglow.BetaFileListParams{
  	ScopeID: juglow.String(session.ID),
  	Betas:   []juglow.JuglowBeta{juglow.JuglowBetaManagedAgents2026_04_01},
  })
  if err != nil {
  	panic(err)
  }
  for _, file := range files.Data {
  	fmt.Println(file.ID, file.Filename)
  }

  // Unduh file
  if len(files.Data) > 0 {
  	resp, err := client.Files.Download(ctx, files.Data[0].ID, juglow.FileDownloadParams{})
  	if err != nil {
  		panic(err)
  	}
  	defer resp.Body.Close()
  	out, err := os.Create("/tmp/output.txt")
  	if err != nil {
  		panic(err)
  	}
  	defer out.Close()
  	if _, err := io.Copy(out, resp.Body); err != nil {
  		panic(err)
  	}
  }
java
  // Daftar file yang dihasilkan oleh sesi ini
  // (pemfilteran scope_id memerlukan beta managed-agents pada permintaan files)
  var files = client.beta().files().list(
      FileListParams.builder()
          .scopeId(session.id())
          .addBeta(JuglowBeta.MANAGED_AGENTS_2026_04_01)
          .build());
  for (var file : files.data()) {
      IO.println(file.id() + " " + file.filename());
  }

  // Unduh file
  if (!files.data().isEmpty()) {
      try (HttpResponse response = client.files().download(files.data().getFirst().id())) {
          try (InputStream body = response.body()) {
              Files.copy(body, Path.of("/tmp/output.txt"), StandardCopyOption.REPLACE_EXISTING);
          }
      }
  }
php
  // Daftar file yang dihasilkan oleh sesi ini
  // Pemfilteran scope_id memerlukan beta managed-agents pada permintaan files
  $files = $client->beta->files->list(scopeID: $session->id, betas: ['managed-agents-2026-04-01']);
  foreach ($files->getItems() as $file) {
      echo "{$file->id} {$file->filename}\n";
  }

  // Unduh file
  if (count($files->getItems()) > 0) {
      $content = $client->files->download($files->getItems()[0]->id);
      file_put_contents('/tmp/output.txt', $content);
  }
ruby
  # Daftar file yang dihasilkan oleh sesi ini
  # Pemfilteran scope_id memerlukan beta managed-agents pada permintaan files
  files = client.beta.files.list(scope_id: session.id, betas: ["managed-agents-2026-04-01"])
  files.data.each { |file| puts "#{file.id} #{file.filename}" }

  # Unduh file
  if (first = files.data.first)
    content = client.files.download(first.id)
    File.binwrite("/tmp/output.txt", content.read)
  end

Langkah selanjutnya

Daftarkan kredensial per pengguna saat membuat sesi.

Kirim event, lakukan streaming respons, dan interupsi atau arahkan ulang sesi Anda di tengah eksekusi.

Unggah file dan mount ke dalam sandbox Anda untuk dibaca dan diproses.

On this page
Membuat rubrikTips menulis rubrik yang efektifMembuat sesi dengan outcomeEvent outcomeEvent pengguna define outcomeAwal evaluasi outcomeEvaluasi outcome sedang berlangsungAkhir evaluasi outcomeMemeriksa status outcomeMengambil deliverableLangkah selanjutnya