SpyBara
Go Premium

agent-sdk/structured-outputs.md 2026-11-12 23:02 UTC to 2026-11-13 02:58 UTC

No changes for this document in this history range.

2026
Tue 10 21:57

Dapatkan output terstruktur dari agen

Kembalikan JSON yang divalidasi dari alur kerja agen menggunakan JSON Schema, Zod, atau Pydantic. Dapatkan data terstruktur yang aman tipe setelah penggunaan alat multi-putaran.

Output terstruktur memungkinkan Anda menentukan bentuk data yang tepat yang ingin Anda kembalikan dari agen. Agen dapat menggunakan alat apa pun yang diperlukan untuk menyelesaikan tugas, dan Anda tetap mendapatkan JSON yang divalidasi sesuai dengan skema Anda di akhir. Tentukan JSON Schema untuk struktur yang Anda butuhkan, dan SDK memvalidasi output terhadapnya, meminta ulang jika tidak cocok. Jika validasi tidak berhasil dalam batas percobaan ulang, hasilnya adalah kesalahan bukan data terstruktur; lihat Penanganan kesalahan.

Untuk keamanan tipe penuh, gunakan Zod (TypeScript) atau Pydantic (Python) untuk menentukan skema Anda dan dapatkan objek yang sangat diketik kembali.

Mengapa output terstruktur?

Agent mengembalikan teks bentuk bebas secara default, yang cocok untuk percakapan tetapi tidak ketika Anda perlu menggunakan output tersebut secara terprogram. Output terstruktur memberi Anda data bertipe yang dapat Anda teruskan langsung ke logika aplikasi, basis data, atau komponen UI Anda.

Bayangkan sebuah aplikasi resep di mana agent mencari di web dan membawa kembali resep. Tanpa output terstruktur, Anda mendapatkan teks bentuk bebas yang perlu Anda parsing sendiri. Dengan output terstruktur, Anda mendefinisikan bentuk yang Anda inginkan dan mendapatkan data bertipe yang dapat Anda gunakan langsung di aplikasi Anda.

[accordion] Tanpa output terstruktur

Here's a classic chocolate chip cookie recipe!

**Chocolate Chip Cookies**
Prep time: 15 minutes | Cook time: 10 minutes

Ingredients:
- 2 1/4 cups all-purpose flour
- 1 cup butter, softened
...

Untuk menggunakan ini di aplikasi Anda, Anda perlu mem-parsing judulnya, mengonversi "15 minutes" menjadi angka, memisahkan bahan dari instruksi, dan menangani format yang tidak konsisten di berbagai respons.

[accordion] Dengan output terstruktur

{
  "name": "Chocolate Chip Cookies",
  "prep_time_minutes": 15,
  "cook_time_minutes": 10,
  "ingredients": [
    { "item": "all-purpose flour", "amount": 2.25, "unit": "cups" },
    { "item": "butter, softened", "amount": 1, "unit": "cup" }
    // ...
  ],
  "steps": ["Preheat oven to 375°F", "Cream butter and sugar" /* ... */]
}

Data bertipe yang dapat Anda gunakan langsung di UI Anda.

Mulai cepat

Untuk menggunakan output terstruktur, definisikan JSON Schema yang menjelaskan bentuk data yang Anda inginkan, lalu teruskan ke query() melalui opsi outputFormat (TypeScript) atau opsi output_format (Python). Ketika agent selesai, pesan hasil menyertakan field structured_output dengan data tervalidasi yang sesuai dengan skema Anda.

Sebelum menjalankan contoh di halaman ini, instal Claude Agent SDK dengan mengikuti mulai cepat. Contoh di bawah ini meminta agent untuk meneliti Anthropic dan mengembalikan nama perusahaan, tahun didirikan, dan kantor pusat sebagai output terstruktur.

import { query } from "@anthropic-ai/claude-agent-sdk";

// Definisikan bentuk data yang ingin Anda terima kembali
const schema = {
  type: "object",
  properties: {
    company_name: { type: "string" },
    founded_year: { type: "number" },
    headquarters: { type: "string" }
  },
  required: ["company_name"]
};

try {
  for await (const message of query({
    prompt: "Research Anthropic and provide key company information",
    options: {
      outputFormat: {
        type: "json_schema",
        schema: schema
      }
    }
  })) {
    // Pesan hasil berisi structured_output dengan data tervalidasi
    if (message.type === "result" && message.subtype === "success" && !message.is_error && message.structured_output) {
      console.log(message.structured_output);
      // { company_name: "Anthropic", founded_year: 2021, headquarters: "San Francisco, CA" }
    }
  }
} catch (error) {
  // query() sekali jalan akan melempar error setelah menghasilkan hasil error, seperti
  // error_max_structured_output_retries; lihat bagian Penanganan error.
  console.error(`Session ended with an error: ${error}`);
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

# Definisikan bentuk data yang ingin Anda terima kembali
schema = {
    "type": "object",
    "properties": {
        "company_name": {"type": "string"},
        "founded_year": {"type": "number"},
        "headquarters": {"type": "string"},
    },
    "required": ["company_name"],
}


async def main():
    try:
        async for message in query(
            prompt="Research Anthropic and provide key company information",
            options=ClaudeAgentOptions(
                output_format={"type": "json_schema", "schema": schema}
            ),
        ):
            # Pesan hasil berisi structured_output dengan data tervalidasi
            if (
                isinstance(message, ResultMessage)
                and not message.is_error
                and message.structured_output
            ):
                print(message.structured_output)
                # {'company_name': 'Anthropic', 'founded_year': 2021, 'headquarters': 'San Francisco, CA'}
    except Exception as error:
        # query() sekali jalan akan memunculkan error setelah menghasilkan hasil error, seperti
        # error_max_structured_output_retries; lihat bagian Penanganan error.
        print(f"Session ended with an error: {error}")


asyncio.run(main())

Skema yang aman tipe dengan Zod dan Pydantic

Alih-alih menulis JSON Schema dengan tangan, Anda dapat menggunakan Zod (TypeScript) atau Pydantic (Python) untuk menentukan skema Anda. Perpustakaan ini menghasilkan JSON Schema untuk Anda dan memungkinkan Anda mengurai respons menjadi objek yang sepenuhnya diketik yang dapat Anda gunakan di seluruh basis kode Anda dengan pelengkapan otomatis dan pemeriksaan tipe.

Contoh di bawah ini menentukan skema untuk rencana implementasi fitur dengan ringkasan, daftar langkah (masing-masing dengan tingkat kompleksitas), dan risiko potensial. Agen merencanakan fitur dan mengembalikan objek FeaturePlan yang diketik. Anda kemudian dapat mengakses properti seperti plan.summary dan mengulangi plan.steps dengan keamanan tipe penuh.

SDK memvalidasi skema dengan JSON Schema draft-07, jadi skema yang mendeklarasikan versi yang lebih baru ditolak. Zod menargetkan draft 2020-12 secara default, jadi teruskan target: "draft-7" saat mengonversi skema Anda.

import { z } from "zod";
import { query } from "@anthropic-ai/claude-agent-sdk";

// Define schema with Zod
const FeaturePlan = z.object({
  feature_name: z.string(),
  summary: z.string(),
  steps: z.array(
    z.object({
      step_number: z.number(),
      description: z.string(),
      estimated_complexity: z.enum(["low", "medium", "high"])
    })
  ),
  risks: z.array(z.string())
});

type FeaturePlan = z.infer<typeof FeaturePlan>;

// Convert to JSON Schema using the draft-07 target the SDK expects
const schema = z.toJSONSchema(FeaturePlan, { target: "draft-7" });

// Use in query
try {
  for await (const message of query({
    prompt:
      "Plan how to add dark mode support to a React app. Break it into implementation steps.",
    options: {
      outputFormat: {
        type: "json_schema",
        schema: schema
      }
    }
  })) {
    if (message.type === "result" && message.subtype === "success" && !message.is_error && message.structured_output) {
      // Validate and get fully typed result
      const parsed = FeaturePlan.safeParse(message.structured_output);
      if (parsed.success) {
        const plan: FeaturePlan = parsed.data;
        console.log(`Feature: ${plan.feature_name}`);
        console.log(`Summary: ${plan.summary}`);
        plan.steps.forEach((step) => {
          console.log(`${step.step_number}. [${step.estimated_complexity}] ${step.description}`);
        });
      }
    }
  }
} catch (error) {
  // A single-shot query() throws after yielding an error result, such as
  // error_max_structured_output_retries; see the Error handling section.
  console.error(`Session ended with an error: ${error}`);
}
import asyncio
from pydantic import BaseModel
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage


class Step(BaseModel):
    step_number: int
    description: str
    estimated_complexity: str  # 'low', 'medium', 'high'


class FeaturePlan(BaseModel):
    feature_name: str
    summary: str
    steps: list[Step]
    risks: list[str]


async def main():
    try:
        async for message in query(
            prompt="Plan how to add dark mode support to a React app. Break it into implementation steps.",
            options=ClaudeAgentOptions(
                output_format={
                    "type": "json_schema",
                    "schema": FeaturePlan.model_json_schema(),
                }
            ),
        ):
            if (
                isinstance(message, ResultMessage)
                and not message.is_error
                and message.structured_output
            ):
                # Validate and get fully typed result
                plan = FeaturePlan.model_validate(message.structured_output)
                print(f"Feature: {plan.feature_name}")
                print(f"Summary: {plan.summary}")
                for step in plan.steps:
                    print(
                        f"{step.step_number}. [{step.estimated_complexity}] {step.description}"
                    )
    except Exception as error:
        # A single-shot query() raises after yielding an error result, such as
        # error_max_structured_output_retries; see the Error handling section.
        print(f"Session ended with an error: {error}")


asyncio.run(main())

Konfigurasi format output

Opsi outputFormat (TypeScript) atau output_format (Python) menerima objek dengan:

  • type: Atur ke "json_schema" untuk output terstruktur
  • schema: Objek JSON Schema yang menentukan struktur output Anda. Anda dapat menghasilkan ini dari skema Zod dengan z.toJSONSchema(schema, { target: "draft-7" }) atau model Pydantic dengan .model_json_schema()

SDK mendukung fitur JSON Schema standar termasuk semua tipe dasar (object, array, string, number, boolean, null), enum, const, required, objek bersarang, dan definisi $ref. Untuk daftar lengkap fitur yang didukung dan batasan, lihat Batasan JSON Schema.

Skema yang bukan JSON Schema yang valid gagal dijalankan saat startup dengan kesalahan yang menyebutkan masalahnya. Sebelum v2.1.205, skema yang tidak valid secara diam-diam diabaikan dan agen mengembalikan teks yang tidak terstruktur.

Kata kunci format, seperti "format": "email", diterima sebagai anotasi dan tidak diberlakukan oleh validator SDK. Sebelum v2.1.205, skema apa pun yang berisi format dianggap tidak valid.

Contoh: agent pelacak TODO

Contoh ini menunjukkan cara kerja output terstruktur dengan penggunaan tool multi-langkah. Agent perlu menemukan komentar TODO dalam codebase, lalu mencari informasi git blame untuk masing-masing komentar tersebut. Agent secara mandiri memutuskan tool mana yang akan digunakan (Grep untuk mencari, Bash untuk menjalankan perintah git) dan menggabungkan hasilnya menjadi satu respons terstruktur.

Skema ini menyertakan field opsional (author dan date) karena informasi git blame mungkin tidak tersedia untuk semua file. Agent mengisi apa yang dapat ditemukannya dan menghilangkan sisanya.

import { query } from "@anthropic-ai/claude-agent-sdk";

// Definisikan struktur untuk ekstraksi TODO
const todoSchema = {
  type: "object",
  properties: {
    todos: {
      type: "array",
      items: {
        type: "object",
        properties: {
          text: { type: "string" },
          file: { type: "string" },
          line: { type: "number" },
          author: { type: "string" },
          date: { type: "string" }
        },
        required: ["text", "file", "line"]
      }
    },
    total_count: { type: "number" }
  },
  required: ["todos", "total_count"]
};

// Agent menggunakan Grep untuk menemukan TODO, Bash untuk mendapatkan info git blame
try {
  for await (const message of query({
    prompt: "Find all TODO comments in this codebase and identify who added them",
    options: {
      outputFormat: {
        type: "json_schema",
        schema: todoSchema
      }
    }
  })) {
    if (message.type === "result" && message.subtype === "success" && !message.is_error && message.structured_output) {
      const data = message.structured_output as { total_count: number; todos: Array<{ file: string; line: number; text: string; author?: string; date?: string }> };
      console.log(`Found ${data.total_count} TODOs`);
      data.todos.forEach((todo) => {
        console.log(`${todo.file}:${todo.line} - ${todo.text}`);
        if (todo.author) {
          console.log(`  Added by ${todo.author} on ${todo.date}`);
        }
      });
    }
  }
} catch (error) {
  // query() sekali jalan akan melempar error setelah menghasilkan hasil error, seperti
  // error_max_structured_output_retries; lihat bagian Penanganan error.
  console.error(`Session ended with an error: ${error}`);
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

# Definisikan struktur untuk ekstraksi TODO
todo_schema = {
    "type": "object",
    "properties": {
        "todos": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "text": {"type": "string"},
                    "file": {"type": "string"},
                    "line": {"type": "number"},
                    "author": {"type": "string"},
                    "date": {"type": "string"},
                },
                "required": ["text", "file", "line"],
            },
        },
        "total_count": {"type": "number"},
    },
    "required": ["todos", "total_count"],
}


async def main():
    # Agent menggunakan Grep untuk menemukan TODO, Bash untuk mendapatkan info git blame
    try:
        async for message in query(
            prompt="Find all TODO comments in this codebase and identify who added them",
            options=ClaudeAgentOptions(
                output_format={"type": "json_schema", "schema": todo_schema}
            ),
        ):
            if (
                isinstance(message, ResultMessage)
                and not message.is_error
                and message.structured_output
            ):
                data = message.structured_output
                print(f"Found {data['total_count']} TODOs")
                for todo in data["todos"]:
                    print(f"{todo['file']}:{todo['line']} - {todo['text']}")
                    if "author" in todo:
                        print(f"  Added by {todo['author']} on {todo['date']}")
    except Exception as error:
        # query() sekali jalan akan memunculkan exception setelah menghasilkan hasil error, seperti
        # error_max_structured_output_retries; lihat bagian Penanganan error.
        print(f"Session ended with an error: {error}")


asyncio.run(main())

Mengenali panggilan tool StructuredOutput

Saat Anda menetapkan outputFormat di TypeScript atau output_format di Python, aliran pesan Anda membawa panggilan tool bernama StructuredOutput yang tidak pernah Anda definisikan. Claude Code menambahkan tool ini ke sesi, dan agent memanggilnya untuk mengembalikan jawabannya. Pesan init sistem mencantumkannya dalam array tools, dan setiap panggilan tiba sebagai dua blok:

  • Blok tool_use bernama StructuredOutput, yang inputnya adalah objek yang dihasilkan agent untuk skema Anda
  • Blok tool_result yang berbunyi Structured output provided successfully

Ketika objek tersebut tidak cocok dengan skema Anda, tool_result justru membawa is_error: true dan agent memanggil StructuredOutput lagi, sehingga aliran Anda dapat berisi beberapa panggilan untuk satu kueri. Baca data yang telah divalidasi dari structured_output pada pesan hasil, bukan dari blok tool_use, dan lihat Penanganan kesalahan untuk hasil yang Anda dapatkan ketika tidak ada upaya yang berhasil.

Jika aplikasi Anda menampilkan atau mencatat panggilan tool, lewati panggilan yang bernama StructuredOutput agar mekanisme ini tidak muncul sebagai langkah yang dipilih oleh agent. Blok tool_result tidak membawa nama tool, hanya tool_use_id dari panggilan yang dijawabnya, jadi cocokkan nilai tersebut dengan id dari setiap panggilan yang Anda lewati.

Penanganan error

Pembuatan output terstruktur dapat gagal ketika agent tidak dapat menghasilkan JSON valid yang sesuai dengan skema Anda. Hal ini biasanya terjadi ketika skema terlalu kompleks untuk tugas tersebut, tugas itu sendiri ambigu, atau agent mencapai batas retry saat mencoba memperbaiki error validasi. Hal ini juga dapat terjadi tanpa kegagalan validasi apa pun: sebuah model fallback dapat menarik kembali output yang sudah selesai di tengah stream, dan jika tidak ada retry yang menggantikannya, eksekusi berakhir dengan error yang sama. Periksa daftar errors pada pesan hasil error untuk membedakan kedua penyebab tersebut sebelum melakukan debugging pada skema Anda.

Periksa subtype pada pesan hasil:

Subtype Arti
success Eksekusi berakhir tanpa subtype error
error_max_structured_output_retries Tidak ada output valid yang tersisa setelah beberapa kali percobaan (kegagalan validasi, atau penarikan kembali akibat model fallback tanpa retry yang berhasil)

Subtype success dengan sendirinya tidak berarti eksekusi menghasilkan jawaban. Anggap hasil sebagai kegagalan ketika is_error pada hasil bernilai true atau structured_output tidak ada:

  • is_error pada hasil bernilai true: misalnya, permintaan model terakhir berakhir dengan error API atau penolakan. Jangan gunakan nilai structured_output pada hasil seperti itu.
  • structured_output tidak ada: untuk menemukan penyebabnya, lihat structured_output is None but the result says success

Contoh di bawah ini menerapkan pemeriksaan tersebut:

import { query } from "@anthropic-ai/claude-agent-sdk";

const contactSchema = {
  type: "object",
  properties: {
    name: { type: "string" },
    email: { type: "string" }
  },
  required: ["name"]
};

try {
  for await (const msg of query({
    prompt: "Extract contact info from the document",
    options: {
      outputFormat: {
        type: "json_schema",
        schema: contactSchema
      }
    }
  })) {
    if (msg.type === "result") {
      if (msg.subtype === "success" && !msg.is_error && msg.structured_output) {
        // Gunakan output yang telah divalidasi
        console.log(msg.structured_output);
      } else if (msg.subtype === "error_max_structured_output_retries") {
        console.error("Could not produce valid output");
      } else {
        console.error("Run ended with an error or without a structured output");
      }
    }
  }
} catch (error) {
  // query() sekali jalan akan melempar error setelah menghasilkan hasil error. Jika
  // kegagalannya berupa hasil error, cabang subtype error di atas telah
  // dijalankan; kegagalan koneksi atau proses tidak menghasilkan pesan hasil.
  console.log(`Session ended with an error: ${error}`);
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

contact_schema = {
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "email": {"type": "string"},
    },
    "required": ["name"],
}


async def main():
    try:
        async for message in query(
            prompt="Extract contact info from the document",
            options=ClaudeAgentOptions(
                output_format={"type": "json_schema", "schema": contact_schema}
            ),
        ):
            if isinstance(message, ResultMessage):
                if (
                    message.subtype == "success"
                    and not message.is_error
                    and message.structured_output
                ):
                    # Gunakan output yang telah divalidasi
                    print(message.structured_output)
                elif message.subtype == "error_max_structured_output_retries":
                    print("Could not produce valid output")
                else:
                    print("Run ended with an error or without a structured output")
    except Exception as error:
        # query() sekali jalan akan memunculkan error setelah menghasilkan hasil error. Jika
        # kegagalannya berupa hasil error, cabang subtype error di atas telah
        # dijalankan; kegagalan koneksi atau proses tidak menghasilkan pesan hasil.
        print(f"Session ended with an error: {error}")


asyncio.run(main())

Tips untuk menghindari error:

  • Jaga agar skema tetap terfokus. Skema yang bersarang dalam dengan banyak field wajib lebih sulit dipenuhi. Mulailah dengan yang sederhana dan tambahkan kompleksitas sesuai kebutuhan.
  • Sesuaikan skema dengan tugas. Jika tugas mungkin tidak memiliki semua informasi yang diperlukan oleh skema Anda, jadikan field tersebut opsional.
  • Gunakan prompt yang jelas. Prompt yang ambigu membuat agent lebih sulit mengetahui output apa yang harus dihasilkan.

Sumber daya terkait

  • Dokumentasi JSON Schema: pelajari sintaks JSON Schema untuk menentukan skema kompleks dengan objek bersarang, array, enum, dan batasan validasi
  • API Structured Outputs: gunakan output terstruktur dengan Claude API secara langsung untuk permintaan satu putaran tanpa penggunaan alat
  • Custom tools: berikan agen Anda alat khusus untuk dipanggil selama eksekusi sebelum mengembalikan output terstruktur