構造化出力

このトピックでは、JSON を使用してエージェントワークフローからスキーマ検証済みの JSON を返す方法について説明します。エージェントはタスクを完了するために必要な任意のツールを使用でき、検証に成功すると、スキーマに一致する構造化データが結果に含まれます。

必要な構造の JSON スキーマ を定義すると、SDK が定義されたスキーマに基づいてモデルの最終出力を検証します。

構造化出力を使用する理由

エージェントはデフォルトで自由形式のテキストを返します。これは会話のユースケースでは機能しますが、出力をプログラムで使用する必要がある場合は機能しません。構造化出力には、アプリケーションロジック、データベース、または UI コンポーネントに直接渡すことができる型付きデータが含まれています。

コードベースを分析するエージェントについて考えてみましょう。構造化出力がないと、ご自分で解析する必要のある自由形式のテキストが取得されます。構造化出力を使用すると、必要な形状を定義し、直接使用できる型付きデータを取得できます。

構造化出力なし

構造化出力あり

This codebase uses Python and
TypeScript. It has 42 files
and the main entry point is...
{ "languages": ["Python", "TypeScript"],
  "file_count": 42,
  "entry_point": "src/main.ts" }

クイックスタート

JSON スキーマを outputFormat (TypeScript)または output_format (Python)のオプションに渡します。検証に成功すると、結果メッセージにスキーマに一致するデータが格納されている structured_output フィールドが含まれます。再試行後にエージェントがスキーマを満たすことができない場合は、SDK が代わりにエラー結果を返します。

import { query } from "cortex-code-agent-sdk";

const schema = {
  type: "object",
  properties: {
    company_name: { type: "string" },
    founded_year: { type: "number" },
    headquarters: { type: "string" },
  },
  required: ["company_name"],
};

for await (const message of query({
  prompt: "Research Snowflake and provide key company information",
  options: {
    cwd: process.cwd(),
    outputFormat: { type: "json_schema", schema },
  },
})) {
  if (message.type === "result" && message.structured_output) {
    console.log(message.structured_output);
    // { company_name: "Snowflake", founded_year: 2012, headquarters: "Bozeman, MT" }
  }
}

ZodとPydanticによる型セーフなスキーマ

JSON スキーマを手動で記述する代わりに、`Zod<https://zod.dev/>`_ (TypeScript)または Pydantic (Python)を使用してスキーマを定義します。これらのライブラリは JSONスキーマを生成します。オートコンプリートと型チェックを使用して、応答を完全に型付けされたオブジェクトに解析できます。

import { z } from "zod";
import { query } from "cortex-code-agent-sdk";

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

const schema = z.toJSONSchema(FeaturePlan);

for await (const message of query({
  prompt: "Plan how to add dark mode support to a React app.",
  options: {
    cwd: process.cwd(),
    outputFormat: { type: "json_schema", schema },
  },
})) {
  if (message.type === "result" && message.structured_output) {
    const parsed = FeaturePlan.safeParse(message.structured_output);
    if (parsed.success) {
      const plan: FeaturePlan = parsed.data;
      console.log(`Feature: ${plan.feature_name}`);
      plan.steps.forEach((step) => {
        console.log(`${step.step_number}. [${step.estimated_complexity}] ${step.description}`);
      });
    }
  }
}

例: TODO 追跡エージェント

この例では、マルチステップツール使用の構造化出力を示しています。エージェントは、組み込みツール(Grep、Bash)を使用してコードベースで TODO コメントを見つけ、結果を構造化データとして返します。author などのオプションフィールドは、git責任情報が利用できない可能性があるケースを処理します。

import { query } from "cortex-code-agent-sdk";

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"],
};

for await (const message of query({
  prompt: "Find all TODO comments in this codebase and identify who added them",
  options: {
    cwd: process.cwd(),
    outputFormat: { type: "json_schema", schema: todoSchema },
  },
})) {
  if (message.type === "result" && message.structured_output) {
    const data = message.structured_output;
    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}`);
      }
    });
  }
}

例: SQL クエリ結果

Cortex Codeには、Snowflake SQL ツールが組み込まれています。これらを構造化出力と組み合わせて、型付きのクエリ結果を取得できます。

import { query } from "cortex-code-agent-sdk";

const schema = {
  type: "object",
  properties: {
    top_customers: {
      type: "array",
      items: {
        type: "object",
        properties: {
          name: { type: "string" },
          total_revenue: { type: "number" },
          order_count: { type: "number" },
        },
        required: ["name", "total_revenue", "order_count"],
      },
    },
    query_used: { type: "string" },
  },
  required: ["top_customers", "query_used"],
};

for await (const message of query({
  prompt: "Find the top 5 customers by revenue from the ORDERS table",
  options: {
    cwd: process.cwd(),
    connection: "my-connection",
    outputFormat: { type: "json_schema", schema },
  },
})) {
  if (message.type === "result" && message.structured_output) {
    const { top_customers, query_used } = message.structured_output;
    console.log(`Query: ${query_used}`);
    top_customers.forEach((c) => {
      console.log(`${c.name}: $${c.total_revenue} (${c.order_count} orders)`);
    });
  }
}

出力形式の構成

outputFormat (TypeScript)または output_format (Python)の各オプションは、次のフィールドを持つオブジェクトを受け入れます。

フィールド

説明

type

"json_schema"

必須です。json_schema のみがサポートされています。

schema

JSON スキーマオブジェクト

出力構造を定義します。.model_json_schema()z.toJSONSchema() またはPydanticを使用してZodから生成します。

サポートされている標準 JSON スキーマ機能: すべての基本型(objectarraystringnumberbooleannull)、enumconstrequired、ネストされたオブジェクト、および $ref 定義。

エラー処理

エージェントがスキーマに一致する有効な JSON を生成できない場合は、構造化出力の生成に失敗する可能性があります。この問題が発生すると、結果メッセージにどのような問題が発生したかを示す subtype が表示されます。

サブタイプ

意味

success

出力が生成され、正常に検証されました

error_max_structured_output_retries

複数回試行した後に、エージェントが有効な出力を生成できませんでした

for await (const msg of query({
  prompt: "Extract contact info from the document",
  options: {
    cwd: process.cwd(),
    outputFormat: { type: "json_schema", schema: contactSchema },
  },
})) {
  if (msg.type === "result") {
    if (msg.subtype === "success" && msg.structured_output) {
      console.log(msg.structured_output);
    } else if (msg.subtype === "error_max_structured_output_retries") {
      console.error("Could not produce valid output");
    }
  }
}

Tip

エラーを回避するためのヒント:

  • スキーマに焦点を当てます。 多くの必須フィールドを持つ深くネストされたスキーマは、要件を満たすことが困難です。シンプルな状態から始めて、必要に応じて複雑さを追加します。

  • スキーマをタスクに一致させる。 スキーマが必要とするすべての情報がタスクにない可能性がある場合は、これらのフィールドをオプションにします。

  • 明確なプロンプトを使用する。 あいまいなプロンプトは、エージェントがどのような出力を生成する必要があるかを把握するのを困難にします。