Haijun Platform Docs
EN

"Programmatic tool calling" (pemanggilan alat secara programatik) memungkinkan Haijun menulis kode yang memanggil alat Anda secara programatik di dalam kontainer eksekusi kode, alih-alih memerlukan perjalanan bolak-balik melalui model untuk setiap pemanggilan alat. Ini mengurangi "latency" (latensi) untuk alur kerja multi-alat dan menurunkan konsumsi token dengan memungkinkan Haijun memfilter atau memproses data sebelum mencapai "context window" (jendela konteks) model. Pada benchmark pencarian agentik seperti BrowseComp dan DeepSearchQA, yang menguji riset web multilangkah dan pengambilan informasi yang kompleks, menambahkan pemanggilan alat secara programatik di atas alat pencarian dasar meningkatkan kinerja rata-rata sebesar 11% sambil menggunakan 24% lebih sedikit token input (lihat Improved web search with dynamic filtering).

Pertimbangkan pemeriksaan kepatuhan anggaran untuk 20 karyawan: pendekatan tradisional memerlukan 20 perjalanan bolak-balik model yang terpisah, menarik ribuan baris item pengeluaran ke dalam konteks sepanjang prosesnya. Dengan pemanggilan alat secara programatik, satu skrip menjalankan ke-20 pencarian tersebut, memfilter hasilnya, dan hanya mengembalikan karyawan yang melampaui batas mereka, menyusutkan apa yang perlu dipertimbangkan Haijun dari ratusan kilobyte menjadi hanya beberapa baris.

Tip: Untuk pembahasan lebih mendalam tentang biaya inferensi dan konteks yang diatasi oleh pemanggilan alat secara programatik, lihat Advanced tool use.

Pemanggilan alat secara programatik memerlukan alat eksekusi kode dengan versi alat code_execution_20260120 atau yang lebih baru.

Mulai cepat

Berikut adalah contoh di mana Haijun secara programatik melakukan kueri ke database beberapa kali dan mengagregasi hasilnya. Menambahkan allowed_callers: ["code_execution_20260120"] ke definisi alat adalah yang membuat alat tersebut dapat dipanggil dari dalam eksekusi kode (lihat Field allowed_callers):

bash
  curl https://haijun.my.id/v1/messages \
      --header "x-api-key: $JUGLOW_API_KEY" \
      --header "juglow-version: 2023-06-01" \
      --header "content-type: application/json" \
      --data '{
          "model": "haijun-opus-5-5",
          "max_tokens": 4096,
          "messages": [
              {
                  "role": "user",
                  "content": "Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue"
              }
          ],
          "tools": [
              {
                  "type": "code_execution_20260120",
                  "name": "code_execution"
              },
              {
                  "name": "query_database",
                  "description": "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
                  "input_schema": {
                      "type": "object",
                      "properties": {
                          "sql": {
                              "type": "string",
                              "description": "SQL query to execute"
                          }
                      },
                      "required": ["sql"]
                  },
                  "allowed_callers": ["code_execution_20260120"]
              }
          ]
      }'
bash
  ant messages create <<'YAML'
  model: haijun-opus-5-5
  max_tokens: 4096
  messages:
    - role: user
      content: >-
        Query sales data for the West, East, and Central regions, then
        tell me which region had the highest revenue
  tools:
    - type: code_execution_20260120
      name: code_execution
    - name: query_database
      description: >-
        Execute a SQL query against the sales database. Returns a list
        of rows as JSON objects.
      input_schema:
        type: object
        properties:
          sql:
            type: string
            description: SQL query to execute
        required:
          - sql
      allowed_callers:
        - code_execution_20260120
  YAML
python
  client = juglow.Juglow()

  response = client.messages.create(
      model="haijun-opus-5-5",
      max_tokens=4096,
      messages=[
          {
              "role": "user",
              "content": "Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue",
          }
      ],
      tools=[
          {"type": "code_execution_20260120", "name": "code_execution"},
          {
              "name": "query_database",
              "description": "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "sql": {"type": "string", "description": "SQL query to execute"}
                  },
                  "required": ["sql"],
              },
              "allowed_callers": ["code_execution_20260120"],
          },
      ],
  )

  print(response)
typescript
  const client = new Juglow();

  const response = await client.messages.create({
    model: "haijun-opus-5-5",
    max_tokens: 4096,
    messages: [
      {
        role: "user",
        content:
          "Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue"
      }
    ],
    tools: [
      {
        type: "code_execution_20260120",
        name: "code_execution"
      },
      {
        name: "query_database",
        description:
          "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
        input_schema: {
          type: "object" as const,
          properties: {
            sql: {
              type: "string",
              description: "SQL query to execute"
            }
          },
          required: ["sql"]
        },
        allowed_callers: ["code_execution_20260120"]
      }
    ]
  });

  console.log(response);
csharp
  JuglowClient client = new();

  var parameters = new MessageCreateParams
  {
      Model = Model.HaijunOpus5_5,
      MaxTokens = 4096,
      Messages = [
          new() {
              Role = Role.User,
              Content = "Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue"
          }
      ],
      Tools = [
          new CodeExecutionTool20260120(),
          new ToolUnion(new Tool()
          {
              Name = "query_database",
              Description = "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
              InputSchema = new InputSchema()
              {
                  Properties = new Dictionary<string, JsonElement>
                  {
                      ["sql"] = JsonSerializer.SerializeToElement(new { type = "string", description = "SQL query to execute" }),
                  },
                  Required = ["sql"],
              },
              AllowedCallers = ["code_execution_20260120"]
          }),
      ]
  };

  var message = await client.Messages.Create(parameters);
  Console.WriteLine(message);
go
  client := juglow.NewClient()

  response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
  	Model:     juglow.ModelHaijunOpus5_5,
  	MaxTokens: 4096,
  	Messages: []juglow.MessageParam{
  		juglow.NewUserMessage(juglow.NewTextBlock("Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue")),
  	},
  	Tools: []juglow.ToolUnionParam{
  		{OfCodeExecutionTool20260120: &juglow.CodeExecutionTool20260120Param{}},
  		{OfTool: &juglow.ToolParam{
  			Name:        "query_database",
  			Description: juglow.String("Execute a SQL query against the sales database. Returns a list of rows as JSON objects."),
  			InputSchema: juglow.ToolInputSchemaParam{
  				Properties: map[string]any{
  					"sql": map[string]any{
  						"type":        "string",
  						"description": "SQL query to execute",
  					},
  				},
  				Required: []string{"sql"},
  			},
  			AllowedCallers: []string{"code_execution_20260120"},
  		}},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }
  fmt.Println(response.RawJSON())
java
  import com.juglow.models.messages.CodeExecutionTool20260120;
  // ...

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

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.HAIJUN_OPUS_5_5)
          .maxTokens(4096L)
          .addUserMessage("Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue")
          .addTool(CodeExecutionTool20260120.builder().build())
          .addTool(Tool.builder()
              .name("query_database")
              .description("Execute a SQL query against the sales database. Returns a list of rows as JSON objects.")
              .inputSchema(InputSchema.builder()
                  .properties(JsonValue.from(Map.of(
                      "sql", Map.of(
                          "type", "string",
                          "description", "SQL query to execute"
                      )
                  )))
                  .putAdditionalProperty("required", JsonValue.from(List.of("sql")))
                  .build())
              .allowedCallers(List.of(Tool.AllowedCaller.of("code_execution_20260120")))
              .build())
          .build();

      Message response = client.messages().create(params);
      IO.println(response);
  }
php
  $client = new Client();

  $message = $client->messages->create(
      maxTokens: 4096,
      messages: [
          ['role' => 'user', 'content' => 'Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue'],
      ],
      model: 'haijun-opus-5-5',
      tools: [
          [
              'type' => 'code_execution_20260120',
              'name' => 'code_execution',
          ],
          [
              'name' => 'query_database',
              'description' => 'Execute a SQL query against the sales database. Returns a list of rows as JSON objects.',
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'sql' => [
                          'type' => 'string',
                          'description' => 'SQL query to execute',
                      ],
                  ],
                  'required' => ['sql'],
              ],
              'allowed_callers' => ['code_execution_20260120'],
          ],
      ],
  );

  echo $message;
ruby
  client = Juglow::Client.new

  message = client.messages.create(
    model: "haijun-opus-5-5",
    max_tokens: 4096,
    messages: [
      {
        role: "user",
        content: "Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue"
      }
    ],
    tools: [
      {
        type: "code_execution_20260120",
        name: "code_execution"
      },
      {
        name: "query_database",
        description: "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
        input_schema: {
          type: "object",
          properties: {
            sql: {
              type: "string",
              description: "SQL query to execute"
            }
          },
          required: ["sql"]
        },
        allowed_callers: ["code_execution_20260120"]
      }
    ]
  )

  puts message

Respons berhenti dengan stop_reason: "tool_use", sebuah ID container, dan blok tool_use untuk query_database yang field caller-nya mengidentifikasi proses eksekusi kode yang memanggilnya. Kembalikan hasilnya seperti yang ditunjukkan pada Langkah 3 dari contoh alur kerja agar kode dapat selesai.

Cara kerja pemanggilan alat secara programatik

Ketika Anda mengonfigurasi sebuah alat agar dapat dipanggil dari eksekusi kode dan Haijun menentukan bahwa alat tersebut diperlukan:

  1. Haijun menulis kode Python yang memanggil alat sebagai fungsi, yang berpotensi mencakup beberapa pemanggilan alat dan logika pra/pasca-pemrosesan
  1. Haijun menjalankan kode ini dalam kontainer sandbox melalui eksekusi kode
  1. Ketika fungsi alat dipanggil, eksekusi kode dijeda dan API mengembalikan blok tool_use
  1. Anda memberikan hasil alat, dan eksekusi kode berlanjut (hasil antara tidak dimuat ke dalam jendela konteks Haijun)
  1. Setelah semua eksekusi kode selesai, Haijun menerima output akhir dan melanjutkan pengerjaan tugas

Pendekatan ini sangat berguna untuk:

  • Pemrosesan data besar: Memfilter atau mengagregasi hasil alat sebelum mencapai konteks Haijun
  • Alur kerja multilangkah: Menghemat token dan latensi dengan memanggil alat secara berurutan atau dalam loop tanpa melakukan sampling Haijun di antara pemanggilan alat
  • Logika kondisional: Membuat keputusan berdasarkan hasil alat antara

Note: Alat yang mengizinkan pemanggil eksekusi kode diekspos ke kode Haijun sebagai fungsi Python async, sehingga Haijun dapat menjalankannya secara paralel dengan asyncio.gather. Setiap fungsi menerima satu dict argumen dan mengembalikan string: teks dari tool_result yang Anda kirim kembali. Kode Haijun menunggu fungsi-fungsi ini dengan await tingkat atas dan mengurai hasil yang dibutuhkannya sebagai data terstruktur, misalnya rows = json.loads(await query_database({"sql": ""})).

Konsep inti

Field allowed_callers

Field allowed_callers menentukan konteks mana yang dapat memanggil sebuah alat:

json
{
  "name": "query_database",
  "description": "Execute a SQL query against the database",
  "input_schema": {
    // ...
  },
  "allowed_callers": ["code_execution_20260120"]
}

Nilai yang mungkin:

  • ["direct"] - Haijun diarahkan untuk memanggil alat ini secara langsung (default jika dihilangkan)
  • ["code_execution_20260120"] - Haijun diarahkan untuk memanggil alat ini hanya dari dalam eksekusi kode
  • ["direct", "code_execution_20260120"] - Haijun dapat memanggil alat ini secara langsung atau dari dalam eksekusi kode

Baik "code_execution_20260120" maupun "code_execution_20260521" diterima dalam allowed_callers dan dapat saling menggantikan: permintaan yang menggunakan salah satu versi alat eksekusi kode memenuhi alat yang mencantumkan salah satu pemanggil tersebut. Blok respons selalu menandai pemanggil sebagai code_execution_20260120 terlepas dari versi mana yang dideklarasikan oleh permintaan.

Tip: Pilih salah satu antara ["direct"] atau ["code_execution_20260120"] untuk setiap alat daripada mengaktifkan keduanya, karena ini memberikan panduan yang lebih jelas kepada Haijun tentang cara terbaik menggunakan alat tersebut.

Note: allowed_callers mengontrol bagaimana alat disajikan kepada Haijun dan divalidasi terhadap tool_choice, tetapi ini bukan pemblokiran keras di tingkat API terhadap pemanggilan langsung. Haijun sangat diarahkan untuk mematuhinya, tetapi klien Anda tetap harus siap menangani tool_use langsung untuk alat apa pun yang didefinisikannya. Jangan mengandalkan allowed_callers sebagai batas keamanan.

Field caller dalam respons

Setiap blok penggunaan alat menyertakan field caller yang menunjukkan bagaimana alat tersebut dipanggil:

Pemanggilan langsung (penggunaan alat tradisional):

json
{
  "type": "tool_use",
  "id": "toolu_abc123",
  "name": "query_database",
  "input": { "sql": "<sql>" },
  "caller": { "type": "direct" }
}

Pemanggilan programatik:

json
{
  "type": "tool_use",
  "id": "toolu_xyz789",
  "name": "query_database",
  "input": { "sql": "<sql>" },
  "caller": {
    "type": "code_execution_20260120",
    "tool_id": "srvtoolu_abc123"
  }
}

tool_id adalah id dari blok server_tool_use eksekusi kode yang melakukan pemanggilan, sehingga Anda dapat mencocokkan setiap tool_use programatik dengan proses eksekusi kode yang menghasilkannya.

Siklus hidup kontainer

Pemanggilan alat secara programatik menggunakan kontainer yang sama dengan eksekusi kode:

  • Pembuatan kontainer: Kontainer baru dibuat untuk setiap permintaan kecuali Anda menggunakan kembali kontainer yang sudah ada
  • ID kontainer: Dikembalikan dalam respons pada field container, bersama dengan timestamp expires_at
  • Penggunaan kembali: Kirimkan kembali ID kontainer pada permintaan berikutnya untuk mempertahankan state. Saat pemanggilan alat programatik sedang menunggu hasil Anda, ID kontainer wajib ada pada permintaan tersebut, bukan opsional: API menolak permintaan tanpanya.
  • Kedaluwarsa: expires_at memberi tahu Anda berapa lama waktu yang tersisa untuk kontainer. Kontainer yang menganggur saat ini diambil kembali setelah sekitar 5 menit, dan tidak ada kontainer yang dapat digunakan kembali lebih dari 30 hari setelah dibuat.

Warning: Saat kode Haijun sedang menunggu hasil alat programatik, pemanggilan yang tertunda akan habis waktu setelah sekitar 4 menit dan memunculkan TimeoutError di dalam kode. Kembalikan setiap hasil alat jauh sebelum timestamp expires_at pada respons yang dijeda. Lihat Kedaluwarsa kontainer selama pemanggilan alat.

Contoh alur kerja

Berikut adalah cara kerja alur pemanggilan alat secara programatik yang lengkap:

Langkah 1: Permintaan awal

Kirim permintaan dengan eksekusi kode dan alat yang mengizinkan pemanggilan programatik. Untuk mengaktifkan pemanggilan programatik, tambahkan field allowed_callers ke definisi alat Anda.

Note: Berikan deskripsi terperinci tentang format output alat Anda dalam deskripsi alat. Jika Anda menentukan bahwa alat mengembalikan JSON, Haijun akan mencoba melakukan deserialisasi dan memproses hasilnya dalam kode. Semakin banyak detail yang Anda berikan tentang skema output, semakin baik Haijun dapat menangani respons secara programatik.

Bentuk permintaannya identik dengan contoh Mulai cepat: sertakan code_execution dalam daftar alat Anda, tambahkan allowed_callers: ["code_execution_20260120"] ke alat apa pun yang Anda ingin Haijun panggil dari kode, dan kirim pesan pengguna Anda. Langkah-langkah selanjutnya dalam alur kerja ini menggunakan pesan pengguna "Query customer purchase history from the last quarter and identify our top 5 customers by revenue".

Langkah 2: Respons API dengan pemanggilan alat

Haijun menulis kode yang memanggil alat Anda. API menjeda dan mengembalikan:

json
{
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "I'll query the purchase history and analyze the results."
    },
    {
      "type": "server_tool_use",
      "id": "srvtoolu_abc123",
      "name": "code_execution",
      "input": {
        "code": "import json\n\nrows = json.loads(await query_database({'sql': '<sql>'}))\ntop_customers = sorted(rows, key=lambda x: x['revenue'], reverse=True)[:5]\nprint(f'Top 5 customers: {top_customers}')"
      }
    },
    {
      "type": "tool_use",
      "id": "toolu_def456",
      "name": "query_database",
      "input": { "sql": "<sql>" },
      "caller": {
        "type": "code_execution_20260120",
        "tool_id": "srvtoolu_abc123"
      }
    }
  ],
  "container": {
    "id": "container_xyz789",
    "expires_at": "2026-01-20T14:30:00Z"
  },
  "stop_reason": "tool_use"
}

Langkah 3: Berikan hasil alat

Kirim riwayat percakapan lengkap ditambah hasil alat Anda. Tiga detail penting pada permintaan ini:

  • Kirimkan ID container dari respons yang dijeda. API menolak kelanjutan yang memiliki pemanggilan alat programatik tertunda tetapi tanpa ID kontainer.
  • Kirim array tools yang sama dengan permintaan asli. Alat eksekusi kode harus tetap ada agar kode yang dijeda dapat dilanjutkan, dan alat yang Anda kirim pada permintaan ini adalah definisi yang dapat digunakan Haijun dan kode yang sedang berjalan untuk sisa giliran tersebut.
bash
  curl https://haijun.my.id/v1/messages \
      --header "x-api-key: $JUGLOW_API_KEY" \
      --header "juglow-version: 2023-06-01" \
      --header "content-type: application/json" \
      --data '{
          "model": "haijun-opus-5-5",
          "max_tokens": 4096,
          "container": "container_xyz789",
          "messages": [
              {
                  "role": "user",
                  "content": "Query customer purchase history from the last quarter and identify our top 5 customers by revenue"
              },
              {
                  "role": "assistant",
                  "content": [
                      {
                          "type": "text",
                          "text": "I'\''ll query the purchase history and analyze the results."
                      },
                      {
                          "type": "server_tool_use",
                          "id": "srvtoolu_abc123",
                          "name": "code_execution",
                          "input": {"code": "..."}
                      },
                      {
                          "type": "tool_use",
                          "id": "toolu_def456",
                          "name": "query_database",
                          "input": {"sql": "<sql>"},
                          "caller": {
                              "type": "code_execution_20260120",
                              "tool_id": "srvtoolu_abc123"
                          }
                      }
                  ]
              },
              {
                  "role": "user",
                  "content": [
                      {
                          "type": "tool_result",
                          "tool_use_id": "toolu_def456",
                          "content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}, {\"customer_id\": \"C2\", \"revenue\": 38000}]"
                      }
                  ]
              }
          ],
          "tools": [
              {
                  "type": "code_execution_20260120",
                  "name": "code_execution"
              },
              {
                  "name": "query_database",
                  "description": "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
                  "input_schema": {
                      "type": "object",
                      "properties": {
                          "sql": {
                              "type": "string",
                              "description": "SQL query to execute"
                          }
                      },
                      "required": ["sql"]
                  },
                  "allowed_callers": ["code_execution_20260120"]
              }
          ]
      }'
bash
  ant messages create <<'YAML'
  model: haijun-opus-5-5
  max_tokens: 4096
  container: container_xyz789
  messages:
    - role: user
      content: >-
        Query customer purchase history from the last quarter and identify our
        top 5 customers by revenue
    - role: assistant
      content:
        - type: text
          text: I'll query the purchase history and analyze the results.
        - type: server_tool_use
          id: srvtoolu_abc123
          name: code_execution
          input:
            code: "..."
        - type: tool_use
          id: toolu_def456
          name: query_database
          input:
            sql: "<sql>"
          caller:
            type: code_execution_20260120
            tool_id: srvtoolu_abc123
    - role: user
      content:
        - type: tool_result
          tool_use_id: toolu_def456
          content: >-
            [{"customer_id": "C1", "revenue": 45000}, {"customer_id": "C2",
            "revenue": 38000}, ...]
  # Array tools yang sama dengan permintaan awal
  tools:
    - type: code_execution_20260120
      name: code_execution
    - name: query_database
      description: >-
        Execute a SQL query against the sales database. Returns a list
        of rows as JSON objects.
      input_schema:
        type: object
        properties:
          sql:
            type: string
            description: SQL query to execute
        required:
          - sql
      allowed_callers:
        - code_execution_20260120
  YAML
python
  response = client.messages.create(
      model="haijun-opus-5-5",
      max_tokens=4096,
      container="container_xyz789",  # Reuse the container
      messages=[
          {
              "role": "user",
              "content": "Query customer purchase history from the last quarter and identify our top 5 customers by revenue",
          },
          {
              "role": "assistant",
              "content": [
                  {
                      "type": "text",
                      "text": "I'll query the purchase history and analyze the results.",
                  },
                  {
                      "type": "server_tool_use",
                      "id": "srvtoolu_abc123",
                      "name": "code_execution",
                      "input": {"code": "..."},
                  },
                  {
                      "type": "tool_use",
                      "id": "toolu_def456",
                      "name": "query_database",
                      "input": {"sql": "<sql>"},
                      "caller": {
                          "type": "code_execution_20260120",
                          "tool_id": "srvtoolu_abc123",
                      },
                  },
              ],
          },
          {
              "role": "user",
              "content": [
                  {
                      "type": "tool_result",
                      "tool_use_id": "toolu_def456",
                      "content": '[{"customer_id": "C1", "revenue": 45000}, {"customer_id": "C2", "revenue": 38000}, ...]',
                  }
              ],
          },
      ],
      # Array tools yang sama dengan permintaan awal
      tools=[
          {"type": "code_execution_20260120", "name": "code_execution"},
          {
              "name": "query_database",
              "description": "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
              "input_schema": {
                  "type": "object",
                  "properties": {
                      "sql": {"type": "string", "description": "SQL query to execute"}
                  },
                  "required": ["sql"],
              },
              "allowed_callers": ["code_execution_20260120"],
          },
      ],
  )

  print(response)
typescript
  const response = await client.messages.create({
    model: "haijun-opus-5-5",
    max_tokens: 4096,
    container: "container_xyz789", // Reuse the container
    messages: [
      {
        role: "user",
        content:
          "Query customer purchase history from the last quarter and identify our top 5 customers by revenue"
      },
      {
        role: "assistant",
        content: [
          { type: "text", text: "I'll query the purchase history and analyze the results." },
          {
            type: "server_tool_use",
            id: "srvtoolu_abc123",
            name: "code_execution",
            input: { code: "..." }
          },
          {
            type: "tool_use",
            id: "toolu_def456",
            name: "query_database",
            input: { sql: "<sql>" },
            caller: {
              type: "code_execution_20260120",
              tool_id: "srvtoolu_abc123"
            }
          }
        ]
      },
      {
        role: "user",
        content: [
          {
            type: "tool_result",
            tool_use_id: "toolu_def456",
            content:
              '[{"customer_id": "C1", "revenue": 45000}, {"customer_id": "C2", "revenue": 38000}, ...]'
          }
        ]
      }
    ],
    // Array tools yang sama dengan permintaan awal
    tools: [
      {
        type: "code_execution_20260120",
        name: "code_execution"
      },
      {
        name: "query_database",
        description:
          "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
        input_schema: {
          type: "object" as const,
          properties: {
            sql: {
              type: "string",
              description: "SQL query to execute"
            }
          },
          required: ["sql"]
        },
        allowed_callers: ["code_execution_20260120"]
      }
    ]
  });

  console.log(response);
csharp
  JuglowClient client = new();

  var parameters = new MessageCreateParams
  {
      Model = Model.HaijunOpus5_5,
      MaxTokens = 4096,
      Container = "container_xyz789",
      Messages =
      [
          new()
          {
              Role = Role.User,
              Content = "Query customer purchase history from the last quarter and identify our top 5 customers by revenue"
          },
          new()
          {
              Role = Role.Assistant,
              Content = new ContentBlock[]
              {
                  new TextBlock { Text = "I'll query the purchase history and analyze the results." },
                  new ServerToolUseBlock
                  {
                      Id = "srvtoolu_abc123",
                      Name = "code_execution",
                      Input = new { code = "..." }
                  },
                  new ToolUseBlock
                  {
                      Id = "toolu_def456",
                      Name = "query_database",
                      Input = new { sql = "<sql>" },
                      Caller = new ToolCaller
                      {
                          Type = "code_execution_20260120",
                          ToolId = "srvtoolu_abc123"
                      }
                  }
              }
          },
          new()
          {
              Role = Role.User,
              Content = new ContentBlockParam[]
              {
                  new ToolResultBlockParam
                  {
                      ToolUseID = "toolu_def456",
                      Content = "[{\"customer_id\": \"C1\", \"revenue\": 45000}, {\"customer_id\": \"C2\", \"revenue\": 38000}, ...]"
                  }
              }
          }
      ],
      // Array tools yang sama dengan permintaan asli
      Tools = [
          new CodeExecutionTool20260120(),
          new ToolUnion(new Tool()
          {
              Name = "query_database",
              Description = "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
              InputSchema = new InputSchema()
              {
                  Properties = new Dictionary<string, JsonElement>
                  {
                      ["sql"] = JsonSerializer.SerializeToElement(new { type = "string", description = "SQL query to execute" }),
                  },
                  Required = ["sql"],
              },
              AllowedCallers = ["code_execution_20260120"]
          }),
      ]
  };

  var message = await client.Messages.Create(parameters);
  Console.WriteLine(message);
go
  client := juglow.NewClient()

  response, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
  	Model:     juglow.ModelHaijunOpus5_5,
  	MaxTokens: 4096,
  	Container: juglow.MessageCreateParamsContainerUnion{
  		OfString: juglow.String("container_xyz789"),
  	},
  	Messages: []juglow.MessageParam{
  		juglow.NewUserMessage(juglow.NewTextBlock("Query customer purchase history from the last quarter and identify our top 5 customers by revenue")),
  		{
  			Role: juglow.MessageParamRoleAssistant,
  			Content: []juglow.ContentBlockParamUnion{
  				juglow.NewTextBlock("I'll query the purchase history and analyze the results."),
  				{OfServerToolUse: &juglow.ServerToolUseBlockParam{
  					ID:    "srvtoolu_abc123",
  					Name:  juglow.ServerToolUseBlockParamNameCodeExecution,
  					Input: map[string]any{"code": "..."},
  				}},
  				{OfToolUse: &juglow.ToolUseBlockParam{
  					ID:    "toolu_def456",
  					Name:  "query_database",
  					Input: map[string]any{"sql": "<sql>"},
  					Caller: juglow.ServerToolUseBlockParamCallerUnion{
  						OfCodeExecution20260120: &juglow.ServerToolCaller20260120Param{
  							ToolID: "srvtoolu_abc123",
  						},
  					},
  				}},
  			},
  		},
  		{
  			Role: juglow.MessageParamRoleUser,
  			Content: []juglow.ContentBlockParamUnion{
  				{OfToolResult: &juglow.ToolResultBlockParam{
  					ToolUseID: "toolu_def456",
  					Content: []juglow.ToolResultBlockParamContentUnion{
  						{OfText: &juglow.TextBlockParam{
  							Text: `[{"customer_id": "C1", "revenue": 45000}, {"customer_id": "C2", "revenue": 38000}, ...]`,
  						}},
  					},
  				}},
  			},
  		},
  	},
  	// Array tools yang sama dengan permintaan awal
  	Tools: []juglow.ToolUnionParam{
  		{OfCodeExecutionTool20260120: &juglow.CodeExecutionTool20260120Param{}},
  		{OfTool: &juglow.ToolParam{
  			Name:        "query_database",
  			Description: juglow.String("Execute a SQL query against the sales database. Returns a list of rows as JSON objects."),
  			InputSchema: juglow.ToolInputSchemaParam{
  				Properties: map[string]any{
  					"sql": map[string]any{
  						"type":        "string",
  						"description": "SQL query to execute",
  					},
  				},
  				Required: []string{"sql"},
  			},
  			AllowedCallers: []string{"code_execution_20260120"},
  		}},
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }
  fmt.Println(response.RawJSON())
java
  import com.juglow.models.messages.CodeExecutionTool20260120;
  // ...

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

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.HAIJUN_OPUS_5_5)
          .maxTokens(4096L)
          .container("container_xyz789")
          .addUserMessage("Query customer purchase history from the last quarter and identify our top 5 customers by revenue")
          .addAssistantMessageOfBlockParams(List.of(
              ContentBlockParam.ofText(
                  TextBlockParam.builder()
                      .text("I'll query the purchase history and analyze the results.")
                      .build()),
              ContentBlockParam.ofServerToolUse(
                  ServerToolUseBlockParam.builder()
                      .id("srvtoolu_abc123")
                      .name("code_execution")
                      .input(JsonValue.from(Map.of("code", "...")))
                      .build()),
              ContentBlockParam.ofToolUse(
                  ToolUseBlockParam.builder()
                      .id("toolu_def456")
                      .name("query_database")
                      .input(JsonValue.from(Map.of("sql", "<sql>")))
                      .codeExecution20260120Caller("srvtoolu_abc123")
                      .build())
          ))
          .addUserMessageOfBlockParams(List.of(
              ContentBlockParam.ofToolResult(
                  ToolResultBlockParam.builder()
                      .toolUseId("toolu_def456")
                      .content("[{\"customer_id\": \"C1\", \"revenue\": 45000}, {\"customer_id\": \"C2\", \"revenue\": 38000}, ...]")
                      .build())
          ))
          // Array tools yang sama dengan permintaan awal
          .addTool(CodeExecutionTool20260120.builder().build())
          .addTool(Tool.builder()
              .name("query_database")
              .description("Execute a SQL query against the sales database. Returns a list of rows as JSON objects.")
              .inputSchema(InputSchema.builder()
                  .properties(JsonValue.from(Map.of(
                      "sql", Map.of(
                          "type", "string",
                          "description", "SQL query to execute"
                      )
                  )))
                  .putAdditionalProperty("required", JsonValue.from(List.of("sql")))
                  .build())
              .allowedCallers(List.of(Tool.AllowedCaller.of("code_execution_20260120")))
              .build())
          .build();

      Message response = client.messages().create(params);
      IO.println(response);
  }
php
  $client = new Client();

  $message = $client->messages->create(
      maxTokens: 4096,
      messages: [
          [
              'role' => 'user',
              'content' => 'Query customer purchase history from the last quarter and identify our top 5 customers by revenue',
          ],
          [
              'role' => 'assistant',
              'content' => [
                  [
                      'type' => 'text',
                      'text' => "I'll query the purchase history and analyze the results.",
                  ],
                  [
                      'type' => 'server_tool_use',
                      'id' => 'srvtoolu_abc123',
                      'name' => 'code_execution',
                      'input' => ['code' => '...'],
                  ],
                  [
                      'type' => 'tool_use',
                      'id' => 'toolu_def456',
                      'name' => 'query_database',
                      'input' => ['sql' => '<sql>'],
                      'caller' => [
                          'type' => 'code_execution_20260120',
                          'tool_id' => 'srvtoolu_abc123',
                      ],
                  ],
              ],
          ],
          [
              'role' => 'user',
              'content' => [
                  [
                      'type' => 'tool_result',
                      'tool_use_id' => 'toolu_def456',
                      'content' => '[{"customer_id": "C1", "revenue": 45000}, {"customer_id": "C2", "revenue": 38000}, ...]',
                  ],
              ],
          ],
      ],
      model: 'haijun-opus-5-5',
      container: 'container_xyz789',
      // Array tools yang sama dengan permintaan awal
      tools: [
          [
              'type' => 'code_execution_20260120',
              'name' => 'code_execution',
          ],
          [
              'name' => 'query_database',
              'description' => 'Execute a SQL query against the sales database. Returns a list of rows as JSON objects.',
              'input_schema' => [
                  'type' => 'object',
                  'properties' => [
                      'sql' => [
                          'type' => 'string',
                          'description' => 'SQL query to execute',
                      ],
                  ],
                  'required' => ['sql'],
              ],
              'allowed_callers' => ['code_execution_20260120'],
          ],
      ],
  );

  echo $message;
ruby
  require "juglow"

  client = Juglow::Client.new

  message = client.messages.create(
    model: "haijun-opus-5-5",
    max_tokens: 4096,
    container: "container_xyz789",
    messages: [
      {
        role: "user",
        content: "Query customer purchase history from the last quarter and identify our top 5 customers by revenue"
      },
      {
        role: "assistant",
        content: [
          {
            type: "text",
            text: "I'll query the purchase history and analyze the results."
          },
          {
            type: "server_tool_use",
            id: "srvtoolu_abc123",
            name: "code_execution",
            input: { code: "..." }
          },
          {
            type: "tool_use",
            id: "toolu_def456",
            name: "query_database",
            input: { sql: "<sql>" },
            caller: {
              type: "code_execution_20260120",
              tool_id: "srvtoolu_abc123"
            }
          }
        ]
      },
      {
        role: "user",
        content: [
          {
            type: "tool_result",
            tool_use_id: "toolu_def456",
            content: '[{"customer_id": "C1", "revenue": 45000}, {"customer_id": "C2", "revenue": 38000}, ...]'
          }
        ]
      }
    ],
    # Array tools yang sama seperti pada permintaan awal
    tools: [
      {
        type: "code_execution_20260120",
        name: "code_execution"
      },
      {
        name: "query_database",
        description: "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
        input_schema: {
          type: "object",
          properties: {
            sql: {
              type: "string",
              description: "SQL query to execute"
            }
          },
          required: ["sql"]
        },
        allowed_callers: ["code_execution_20260120"]
      }
    ]
  )

  puts message

Langkah 4: Pemanggilan alat berikutnya atau penyelesaian

Kode melanjutkan dari tempat ia dijeda dan memproses hasil Anda. Setiap respons kelanjutan akan dijeda lagi dengan lebih banyak blok tool_use programatik, atau menyelesaikan eksekusi kode dan membiarkan Haijun melanjutkan giliran (Langkah 5). Periksa stop_reason dan caller dari setiap blok tool_use untuk membedakan keduanya: respons yang dijeda untuk Anda memiliki stop_reason: "tool_use" dan blok tool_use yang caller-nya menyebutkan versi eksekusi kode, dan Anda mengulangi Langkah 3 dengan tool_result untuk setiap pemanggilan programatik yang tertunda dalam satu pesan pengguna.

Langkah 5: Respons akhir

Setelah eksekusi kode selesai, Haijun memberikan respons akhir:

json
{
  "content": [
    {
      "type": "code_execution_tool_result",
      "tool_use_id": "srvtoolu_abc123",
      "content": {
        "type": "code_execution_result",
        "stdout": "Top 5 customers: [{'customer_id': 'C1', 'revenue': 45000}, {'customer_id': 'C2', 'revenue': 38000}, {'customer_id': 'C5', 'revenue': 32000}, {'customer_id': 'C8', 'revenue': 28500}, {'customer_id': 'C3', 'revenue': 24000}]",
        "stderr": "",
        "return_code": 0,
        "content": []
      }
    },
    {
      "type": "text",
      "text": "I've analyzed the purchase history from last quarter. Your top 5 customers generated $167,500 in total revenue, with Customer C1 leading at $45,000."
    }
  ],
  "stop_reason": "end_turn"
}

Pola lanjutan

Pemrosesan batch dengan loop

Haijun dapat menulis kode yang memproses banyak item secara efisien:

python
regions = ["West", "East", "Central", "North", "South"]
results = {}
for region in regions:
    rows = json.loads(await query_database({"sql": f"<sql for {region}>"}))
    results[region] = sum(row["revenue"] for row in rows)

# Proses hasil secara terprogram
top_region = max(results.items(), key=lambda x: x[1])
print(f"Top region: {top_region[0]} with ${top_region[1]:,} in revenue")

Pola ini:

  • Mengurangi perjalanan bolak-balik model dari N (satu per wilayah) menjadi 1
  • Memproses kumpulan hasil yang besar secara programatik sebelum dikembalikan ke Haijun
  • Menghemat token dengan hanya mengembalikan kesimpulan teragregasi alih-alih data mentah

Penghentian dini

Haijun dapat menghentikan pemrosesan segera setelah kriteria keberhasilan terpenuhi:

python
endpoints = ["us-east", "eu-west", "apac"]
for endpoint in endpoints:
    status = await check_health({"endpoint": endpoint})
    if status == "healthy":
        print(f"Found healthy endpoint: {endpoint}")
        break  # Stop early, don't check remaining

Pemilihan alat kondisional

python
path = "/tmp/example.txt"
file_info = json.loads(await get_file_info({"path": path}))
if file_info["size"] < 10000:
    content = await read_full_file({"path": path})
else:
    content = await read_file_summary({"path": path})
print(content)

Pemfilteran data

python
server_id = "srv-01"
log_text = await fetch_logs({"server_id": server_id})
errors = [line for line in log_text.splitlines() if "ERROR" in line]
print(f"Found {len(errors)} errors")
for error in errors[-10:]:  # Only return last 10 errors
    print(error)

Format respons

Pemanggilan alat programatik

Ketika eksekusi kode memanggil sebuah alat:

json
{
  "type": "tool_use",
  "id": "toolu_abc123",
  "name": "query_database",
  "input": { "sql": "<sql>" },
  "caller": {
    "type": "code_execution_20260120",
    "tool_id": "srvtoolu_xyz789"
  }
}

Penanganan hasil alat

Hasil alat Anda diteruskan kembali ke kode yang sedang berjalan:

json
{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_abc123",
      "content": "[{\"customer_id\": \"C1\", \"revenue\": 45000, \"orders\": 23}, {\"customer_id\": \"C2\", \"revenue\": 38000, \"orders\": 18}, ...]"
    }
  ]
}

Penyelesaian eksekusi kode

Ketika semua pemanggilan alat terpenuhi dan kode selesai:

json
{
  "type": "code_execution_tool_result",
  "tool_use_id": "srvtoolu_xyz789",
  "content": {
    "type": "code_execution_result",
    "stdout": "Analysis complete. Top 5 customers identified from 847 total records.",
    "stderr": "",
    "return_code": 0,
    "content": []
  }
}

Penanganan error

Error umum

ErrorTempat munculnyaDeskripsiSolusi
invalid_tool_inputerror_code pada blok error code_execution_tool_result dalam responsParameter tidak valid diteruskan ke alat eksekusi kodeLihat error alat eksekusi kode
invalid_request_error (pada tool_choice)Respons error HTTP 400tool_choice menyebutkan alat yang allowed_callers-nya tidak menyertakan "direct"Tambahkan "direct" ke allowed_callers alat tersebut, atau hapus alat dari tool_choice dan biarkan Haijun memanggilnya dari kode

Kedaluwarsa kontainer selama pemanggilan alat

Jika hasil alat Anda tidak tiba dalam waktu sekitar 4 menit, pemanggilan yang tertunda memunculkan TimeoutError di dalam kode Haijun yang sedang berjalan. Haijun melihat error tersebut di stderr dan biasanya mencoba ulang pemanggilan:

json
{
  "type": "code_execution_tool_result",
  "tool_use_id": "srvtoolu_abc123",
  "content": {
    "type": "code_execution_result",
    "stdout": "",
    "stderr": "TimeoutError: Calling tool ['query_database'] timed out (no response after 270s).",
    "return_code": 0,
    "content": []
  }
}

Untuk mencegah timeout:

  • Pantau field expires_at dalam respons
  • Terapkan timeout untuk eksekusi alat Anda
  • Pertimbangkan untuk memecah operasi panjang menjadi bagian-bagian yang lebih kecil

Error eksekusi alat

Jika alat Anda mengembalikan error:

json
{
  "type": "tool_result",
  "tool_use_id": "toolu_abc123",
  "content": "Error: Query timeout - table lock exceeded 30 seconds"
}

Kode Haijun menerima error ini dan dapat menanganinya dengan tepat.

Batasan dan keterbatasan

Ketidakcocokan fitur

  • Output terstruktur: Alat dengan strict: true tidak didukung dengan pemanggilan programatik
  • Pilihan alat: Anda tidak dapat memaksa pemanggilan programatik alat tertentu melalui tool_choice
  • Penggunaan alat paralel: disable_parallel_tool_use: true tidak didukung dengan pemanggilan programatik

Keterbatasan skema input

Alat kustom yang input_schema-nya berisi $ref rekursif (siklus referensi, seperti skema yang merujuk ke dirinya sendiri) tidak dapat diaktifkan untuk pemanggilan programatik. Menyertakan versi alat eksekusi kode dalam allowed_callers untuk alat semacam itu menyebabkan permintaan gagal dengan 400 invalid_request_error yang pesannya berisi Circular $ref detected. Skema yang sama diterima untuk pemanggilan alat langsung.

Untuk mengatasinya, lakukan salah satu hal berikut:

  • Pertahankan alat sebagai direct-only dengan menghilangkan allowed_callers (atau mengaturnya ke ["direct"]). Alat lain dalam permintaan yang sama tetap dapat menggunakan pemanggilan programatik.
  • Hapus siklus dari skema. Misalnya, uraikan rekursi hingga kedalaman tetap dan jelaskan penyarangan yang lebih dalam di description tingkat terdalam, atau ganti properti rekursif dengan {"type": "object"} biasa yang description-nya menjelaskan bentuk yang diharapkan.

Pembatasan alat

Alat-alat berikut tidak dapat dipanggil secara programatik:

  • Toolset computer use dan browser use (computer_toolset_20260801 dan browser_toolset_20260801), yang field allowed_callers-nya hanya menerima "direct"

Pembatasan format pesan

Saat merespons pemanggilan alat programatik, terdapat persyaratan format yang ketat:

Respons hanya berisi hasil alat: Jika ada pemanggilan alat programatik tertunda yang menunggu hasil, pesan respons Anda harus berisi hanya blok tool_result. Anda tidak dapat menyertakan konten teks apa pun, bahkan setelah hasil alat.

Tidak valid - Tidak dapat menyertakan teks saat merespons pemanggilan alat programatik:

json
{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_01",
      "content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}]"
    },
    { "type": "text", "text": "What should I do next?" }
  ]
}

Valid - Hanya hasil alat saat merespons pemanggilan alat programatik:

json
{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_01",
      "content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}]"
    }
  ]
}

Pembatasan ini hanya berlaku saat merespons pemanggilan alat programatik (eksekusi kode). Untuk pemanggilan alat sisi klien biasa, Anda dapat menyertakan konten teks setelah hasil alat.

Konten hasil alat hanya teks: content dari setiap tool_result yang menjawab pemanggilan programatik harus berupa string atau blok text. Tipe blok konten gambar, dokumen, dan lainnya ditolak.

Batas laju

Pemanggilan alat programatik tunduk pada "rate limit" (batas laju) yang sama dengan pemanggilan alat biasa. Setiap pemanggilan alat dari eksekusi kode dihitung sebagai pemanggilan terpisah.

Validasi hasil alat sebelum digunakan

Saat mengimplementasikan alat yang didefinisikan pengguna yang akan dipanggil secara programatik:

  • Hasil alat dikembalikan sebagai string: Hasil tersebut dapat berisi konten apa pun, termasuk cuplikan kode atau perintah yang dapat dieksekusi yang mungkin diproses oleh lingkungan eksekusi.
  • Validasi hasil alat eksternal: Jika alat Anda mengembalikan data dari sumber eksternal atau menerima input pengguna, waspadai risiko injeksi kode jika output akan diinterpretasikan atau dieksekusi sebagai kode.

Efisiensi token

Pemanggilan alat secara programatik mengurangi konsumsi token dengan tiga cara:

  • Hasil alat dari pemanggilan programatik tidak ditambahkan ke konteks Haijun - hanya output kode akhir yang ditambahkan
  • Pemrosesan antara terjadi dalam kode - pemfilteran, agregasi, dan transformasi lainnya tidak mengonsumsi token model
  • Beberapa pemanggilan alat dalam satu eksekusi kode - mengurangi overhead dibandingkan dengan giliran model yang terpisah

Misalnya, memanggil 10 alat secara langsung menggunakan \~10x token dibandingkan memanggilnya secara programatik dan mengembalikan ringkasan.

Dalam evaluasi internal Juglow pada model Haijun produksi:

  • Pada benchmark agen manajemen proyek dengan 75 alat, mengaktifkan pemanggilan alat secara programatik mengurangi token input yang ditagih sekitar 38% tanpa perubahan pada akurasi tugas.
  • Pada τ²-bench (domain maskapai, ritel, dan telekomunikasi), di mana setiap giliran melakukan satu atau dua pemanggilan alat berurutan, pemanggilan alat secara programatik tidak mengubah skor dan biayanya sekitar 8% lebih mahal. Alur kerja pemanggilan tunggal berurutan tidak mendapatkan manfaat.
  • Di seluruh lalu lintas API produksi, permintaan yang array tools-nya berisi 10 hingga 49 definisi alat mengalami penghematan token tipikal sebesar 20% hingga 40% dengan pemanggilan alat secara programatik diaktifkan.

Penghematan aktual bervariasi tergantung bentuk beban kerja. Lihat Kapan menggunakan pemanggilan programatik.

Penggunaan dan harga

Pemanggilan alat secara programatik menggunakan harga yang sama dengan eksekusi kode. Lihat harga eksekusi kode untuk detailnya.

Note: Penghitungan token untuk pemanggilan alat programatik: Hasil alat dari pemanggilan programatik tidak dihitung dalam penggunaan token input/output Anda. Hanya hasil eksekusi kode akhir dan respons Haijun yang dihitung.

Praktik terbaik

Desain alat

  • Berikan deskripsi output yang terperinci: Karena Haijun melakukan deserialisasi hasil alat dalam kode, dokumentasikan formatnya (struktur JSON dan tipe field)
  • Kembalikan data terstruktur: JSON atau format lain yang dapat dibaca mesin paling cocok untuk pemrosesan programatik
  • Jaga respons tetap ringkas: Kembalikan hanya data yang diperlukan untuk meminimalkan overhead pemrosesan

Kapan menggunakan pemanggilan programatik

Pemanggilan alat secara programatik menukar overhead tetap yang kecil (startup kontainer, pembuatan skrip) dengan penghematan besar pada token hasil alat dan perjalanan bolak-balik model. Apakah pertukaran itu menguntungkan bergantung pada bentuk beban kerja.

Sangat cocok:

  • Operasi fan-out atau paralel di banyak item (misalnya, memeriksa 50 endpoint atau mencari 20 catatan)
  • Hasil alat besar yang dapat difilter, diagregasi, atau diringkas sebelum mencapai konteks Haijun
  • Pencarian dan pengambilan agentik, di mana kueri iteratif dan pemfilteran hasil mendominasi alur kerja

Kurang cocok:

  • Alur kerja yang sangat berurutan di mana setiap pemanggilan bergantung pada penalaran Haijun atas hasil sebelumnya, karena skrip tidak dapat melewati perjalanan bolak-balik model dalam kasus tersebut
  • Sejumlah kecil pemanggilan alat dengan respons kecil, terutama pada giliran pertama percakapan, di mana overhead kontainer dan skrip dapat melebihi penghematan
  • Alat yang memerlukan umpan balik pengguna langsung di antara pemanggilan

Jika Anda tidak yakin, ukur token input yang ditagih dengan dan tanpa allowed_callers pada sampel lalu lintas Anda yang representatif sebelum mengaktifkannya secara luas.

Optimasi kinerja

  • Gunakan kembali kontainer saat membuat beberapa permintaan terkait untuk mempertahankan state
  • Kelompokkan operasi serupa dalam satu eksekusi kode jika memungkinkan

Pemecahan masalah

Masalah umum

invalid_request_error saat mengatur tool_choice

  • tool_choice tidak dapat menyebutkan alat yang allowed_callers-nya menghilangkan "direct". Tambahkan "direct" ke allowed_callers alat tersebut, atau hapus alat dari tool_choice dan biarkan Haijun memanggilnya dari kode.

Kedaluwarsa kontainer

  • Respons setiap pemanggilan alat programatik jauh sebelum timestamp expires_at pada respons yang dijeda. Kode Haijun berhenti menunggu hasil setelah sekitar 4 menit, dan kontainer yang menganggur saat ini diambil kembali setelah sekitar 5 menit.
  • Pertimbangkan untuk mengimplementasikan eksekusi alat yang lebih cepat

Hasil alat tidak diurai dengan benar

  • Pastikan alat Anda mengembalikan data string yang dapat dideserialisasi oleh Haijun
  • Berikan dokumentasi format output yang jelas dalam deskripsi alat Anda

Tips debugging

  1. Catat semua pemanggilan alat dan hasilnya untuk melacak alurnya
  1. Periksa field caller untuk mengonfirmasi pemanggilan programatik
  1. Pantau ID kontainer untuk memastikan penggunaan kembali yang tepat
  1. Uji alat secara independen sebelum mengaktifkan pemanggilan programatik

Mengapa pemanggilan alat secara programatik berhasil

Haijun dilatih dengan sejumlah besar kode, sehingga menyajikan alat sebagai fungsi Python yang dapat dipanggil memungkinkannya memanfaatkan kekuatan tersebut:

  • Komposisi alat: Pemanggilan berantai, loop, dan kondisional adalah alur kontrol Python biasa alih-alih serangkaian perjalanan bolak-balik model
  • Pemrosesan hasil: Kode Haijun memfilter dan mengagregasi output alat yang besar, atau menuliskannya ke file, dan hanya output akhir yang masuk ke jendela konteks
  • Latensi: Model tidak di-sampling ulang di antara pemanggilan alat di dalam satu eksekusi kode

Implementasi alternatif

Pemanggilan alat secara programatik adalah pola yang dapat digeneralisasi dan juga dapat diimplementasikan pada infrastruktur Anda sendiri. Berikut perbandingan pendekatan-pendekatannya:

Eksekusi langsung sisi klien

Berikan Haijun alat eksekusi kode dan jelaskan fungsi apa saja yang tersedia di lingkungan tersebut. Ketika Haijun memanggil alat dengan kode, aplikasi Anda mengeksekusinya secara lokal di tempat fungsi-fungsi tersebut didefinisikan.

Kelebihan:

  • Perombakan arsitektur aplikasi Anda yang minimal
  • Kontrol penuh atas lingkungan dan instruksi

Kekurangan:

  • Mengeksekusi kode yang tidak tepercaya di luar sandbox
  • Pemanggilan alat dapat menjadi vektor untuk injeksi kode

Gunakan ketika: Aplikasi Anda dapat mengeksekusi kode arbitrer dengan aman, Anda menginginkan implementasi terkecil, dan penawaran terkelola Juglow tidak sesuai dengan kebutuhan Anda.

Eksekusi sandbox yang dikelola sendiri

Pendekatan yang sama dari perspektif Haijun, tetapi kode berjalan dalam kontainer sandbox dengan pembatasan keamanan (misalnya, tanpa egress jaringan). Jika alat Anda memerlukan sumber daya eksternal, Anda akan memerlukan protokol untuk mengeksekusi pemanggilan alat di luar sandbox.

Kelebihan:

  • Pemanggilan alat programatik yang aman pada infrastruktur Anda sendiri
  • Kontrol penuh atas lingkungan eksekusi

Kekurangan:

  • Rumit untuk dibangun dan dipelihara
  • Memerlukan pengelolaan infrastruktur dan komunikasi antar-proses

Gunakan ketika: Keamanan sangat penting dan solusi terkelola Juglow tidak sesuai dengan persyaratan Anda.

Eksekusi yang dikelola Juglow

Pemanggilan alat secara programatik dari Juglow adalah versi terkelola dari eksekusi sandbox dengan lingkungan Python beropini yang disetel untuk Haijun. Juglow menangani manajemen kontainer, eksekusi kode, dan komunikasi pemanggilan alat yang aman.

Kelebihan:

  • Aman dan terlindungi secara default
  • Diaktifkan dengan definisi alat, tanpa infrastruktur yang perlu dijalankan
  • Lingkungan dan instruksi yang dioptimalkan untuk Haijun

Pertimbangkan untuk menggunakan solusi terkelola Juglow jika Anda menggunakan Haijun API, Haijun Platform on AWS, atau Microsoft Foundry. Di Microsoft Foundry, pemanggilan alat secara programatik memerlukan deployment Hosted on Juglow.

Retensi data

Pemanggilan alat secara programatik dibangun di atas infrastruktur eksekusi kode dan menggunakan kontainer sandbox yang sama. Data kontainer, termasuk artefak eksekusi dan output, disimpan hingga 30 hari.

Untuk kelayakan ZDR di semua fitur, lihat API dan retensi data.

Langkah selanjutnya

Streaming input alat tanpa buffering JSON sisi server untuk aplikasi yang sensitif terhadap latensi.

Jalankan kode Python dan bash dalam kontainer sandbox untuk menganalisis data, menghasilkan file, dan mengiterasi solusi.

Hubungkan Haijun ke alat dan API eksternal. Lihat di mana alat dieksekusi, kapan Haijun memanggilnya, dan alat mana yang cocok untuk tugas Anda.

Tentukan skema alat, tulis deskripsi yang efektif, dan kontrol kapan Haijun memanggil alat Anda.

On this page
Mulai cepatCara kerja pemanggilan alat secara programatikKonsep intiField allowed_callersField caller dalam responsSiklus hidup kontainerContoh alur kerjaLangkah 1: Permintaan awalLangkah 2: Respons API dengan pemanggilan alatLangkah 3: Berikan hasil alatLangkah 4: Pemanggilan alat berikutnya atau penyelesaianLangkah 5: Respons akhirPola lanjutanPemrosesan batch dengan loopPenghentian diniPemilihan alat kondisionalPemfilteran dataFormat responsPemanggilan alat programatikPenanganan hasil alatPenyelesaian eksekusi kodePenanganan errorError umumKedaluwarsa kontainer selama pemanggilan alatError eksekusi alatBatasan dan keterbatasanKetidakcocokan fiturKeterbatasan skema inputPembatasan alatPembatasan format pesanBatas lajuValidasi hasil alat sebelum digunakanEfisiensi tokenPenggunaan dan hargaPraktik terbaikDesain alatKapan menggunakan pemanggilan programatikOptimasi kinerjaPemecahan masalahMasalah umumTips debuggingMengapa pemanggilan alat secara programatik berhasilImplementasi alternatifEksekusi langsung sisi klienEksekusi sandbox yang dikelola sendiriEksekusi yang dikelola JuglowRetensi dataLangkah selanjutnya