claude-skills/

Anthropic公式スキル・プラグインの日本語ディレクトリ

last sync 22h ago
スキルOfficialdevelopment

🔧output-error-missing-schemas

プラグイン
outputai

説明

スキルの説明文(日本語訳): Output SDK ステップにおける、欠落したスキーマ定義を修正します。 次のような場合に使用: - 型エラーが発生している - ステップの境界で未定義のプロパティが検出される - バリデーションに失敗している - ステップの入力/出力が適切に型付けされていない

原文を表示

Fix missing schema definitions in Output SDK steps. Use when seeing type errors, undefined properties at step boundaries, validation failures, or when step inputs/outputs aren't being properly typed.

ユースケース

  • 型エラーが発生している
  • ステップの境界で未定義のプロパティが検出される
  • バリデーションに失敗している
  • ステップの入力/出力が適切に型付けされていない

本文(日本語訳)

スキーマ定義の欠落を修正する

概要

このスキルは、inputSchema または outputSchema の明示的な定義が欠けているステップに起因する問題の診断と修正を支援します。 スキーマはステップ間における型安全性・バリデーション・適切なデータシリアライゼーションのために不可欠です。

次のような場合に使用

  • ステップの境界で型エラーが発生している
  • ステップの入力/出力でプロパティが undefined になっている
  • ステップ間でデータを受け渡す際にバリデーションエラーが起きている
  • 互換性のない型に関する TypeScript エラーが出ている
  • 予期しないデータ形状に関するランタイムエラーが発生している

根本原因

明示的なスキーマが定義されていないステップは、以下の問題を引き起こします。

  • ランタイムで入力データのバリデーションが行われない
  • TypeScript の型推論が機能しない
  • データのシリアライズ/デシリアライズが正しく行われない可能性がある
  • undefined や不正な形式のデータが検知されないまま通過してしまう

症状

inputSchema が欠落している場合

// 誤り: 入力バリデーションなし
export const processData = step( {
  name: 'processData',
  // inputSchema: 欠落!
  outputSchema: z.object( { result: z.string() } ),
  fn: async input => {
    return { result: input.value };  // input.value が undefined になるかもしれない!
  }
} );

outputSchema が欠落している場合

// 誤り: 出力バリデーションなし
export const fetchData = step( {
  name: 'fetchData',
  inputSchema: z.object( { id: z.string() } ),
  // outputSchema: 欠落!
  fn: async input => {
    return { data: await getFromApi( input.id ) };  // 出力形状が検証されない
  }
} );

両方のスキーマが欠落している場合

// 誤り: バリデーションが一切ない
export const transformData = step( {
  name: 'transformData',
  // スキーマなし!
  fn: async input => {
    return transform( input );
  }
} );

解決策

すべてのステップに inputSchemaoutputSchema の両方を必ず定義してください。

完全なステップ定義の例

import { z, step } from '@outputai/core';

export const processData = step( {
  name: 'processData',
  inputSchema: z.object( {
    id: z.string(),
    value: z.number(),
    optional: z.string().optional()
  } ),
  outputSchema: z.object( {
    result: z.string(),
    processedAt: z.number()
  } ),
  fn: async input => {
    // input は完全に型付けされている: { id: string, value: number, optional?: string }
    return {
      result: `Processed ${input.id}`,
      processedAt: Date.now()
    };
    // output は outputSchema に対してバリデーションされる
  }
} );

スキーマ定義のベストプラクティス

分かりやすいスキーマを定義する

// 良い例: 明確で説明的なスキーマ
inputSchema: z.object( {
  userId: z.string().uuid(),
  email: z.string().email(),
  age: z.number().int().positive()
} )

オプショナルフィールドを適切に扱う

inputSchema: z.object( {
  required: z.string(),
  optional: z.string().optional(),
  withDefault: z.string().default( 'fallback' )
} )

スキーマの合成を活用する

// 再利用可能なスキーマを定義する
const userSchema = z.object( {
  id: z.string(),
  name: z.string()
} );

const addressSchema = z.object( {
  street: z.string(),
  city: z.string()
} );

// ステップ内で合成する
inputSchema: z.object( {
  user: userSchema,
  address: addressSchema
} )

配列とネストされたオブジェクトを扱う

inputSchema: z.object( {
  items: z.array( z.object( {
    id: z.string(),
    quantity: z.number()
  } ) ),
  metadata: z.record( z.string() )
} )

スキーマが未定義のステップを見つける

コードベースを以下のコマンドで検索してください。

# ステップ定義を検索する
grep -rn "step({" src/workflows/

# inputSchema のないステップを探す
grep -A5 "step({" src/workflows/ | grep -B2 "fn:"

# スキーマの有無を確認する
grep -rn "inputSchema:" src/workflows/
grep -rn "outputSchema:" src/workflows/

各ステップの定義を確認し、両方のスキーマが存在することを検証してください。

明示的なスキーマを定義するメリット

  1. ランタイムバリデーション: データのエラーを早期に検出できる
  2. 型安全性: ステップ関数内で TypeScript の完全な型推論が利用できる
  3. ドキュメントとしての役割: スキーマが期待するデータ形状を明示する
  4. シリアライゼーション: ステップ間で適切なデータシリアライゼーションを保証する
  5. エラーメッセージ: データが不正な場合に明確なバリデーションエラーを提供する

よくあるスキーマのパターン

API レスポンスを扱うステップ

export const fetchUser = step( {
  name: 'fetchUser',
  inputSchema: z.object( {
    userId: z.string()
  } ),
  outputSchema: z.object( {
    user: z.object( {
      id: z.string(),
      name: z.string(),
      email: z.string()
    } ).nullable(),  // 取得できなかった場合に対応
    found: z.boolean()
  } ),
  fn: async input => {
    const user = await api.getUser( input.userId );
    return { user, found: user !== null };
  }
} );

データ変換ステップ

export const transformData = step( {
  name: 'transformData',
  inputSchema: z.object( {
    raw: z.array( z.unknown() )
  } ),
  outputSchema: z.object( {
    processed: z.array( z.object( {
      id: z.string(),
      value: z.number()
    } ) ),
    count: z.number()
  } ),
  fn: async input => {
    const processed = input.raw.map( transformItem );
    return { processed, count: processed.length };
  }
} );

出力が不要なステップ(Void Output)

意味のあるデータを返さないステップの場合:

export const logEvent = step( {
  name: 'logEvent',
  inputSchema: z.object( {
    event: z.string(),
    data: z.record( z.unknown() )
  } ),
  outputSchema: z.object( {
    logged: z.literal( true )
  } ),
  fn: async input => {
    await logger.log( input.event, input.data );
    return { logged: true };
  }
} );

確認手順

スキーマを追加した後、以下を確認してください。

  1. TypeScript チェック: npm run output:worker:build が型エラーなしに通ること
  2. ランタイムテスト: npx output workflow run <name> '<input>' が正しくバリデーションされること
  3. 不正入力テスト: 無効なデータを渡し、バリデーションエラーが表示されることを確認する

関連する問題

  • Zod のインポートに関する問題は output-error-zod-import を参照してください
  • スキーマを定義しているにもかかわらず型の不一致が起きる場合は、スキーマが実際のデータと一致しているか確認してください
原文(English)を表示

Fix Missing Schema Definitions

Overview

This skill helps diagnose and fix issues caused by steps that lack explicit inputSchema or outputSchema definitions. Schemas are essential for type safety, validation, and proper data serialization between steps.

When to Use This Skill

You're seeing:

  • Type errors at step boundaries
  • Undefined properties in step inputs/outputs
  • Validation failures when passing data between steps
  • TypeScript errors about incompatible types
  • Runtime errors about unexpected data shapes

Root Cause

Steps without explicit schemas:

  • Don't validate input data at runtime
  • Don't provide TypeScript type inference
  • May serialize/deserialize data incorrectly
  • Can pass undefined or malformed data silently

Symptoms

Missing Input Schema

// WRONG: No input validation
export const processData = step( {
  name: 'processData',
  // inputSchema: missing!
  outputSchema: z.object( { result: z.string() } ),
  fn: async input => {
    return { result: input.value };  // input.value might be undefined!
  }
} );

Missing Output Schema

// WRONG: No output validation
export const fetchData = step( {
  name: 'fetchData',
  inputSchema: z.object( { id: z.string() } ),
  // outputSchema: missing!
  fn: async input => {
    return { data: await getFromApi( input.id ) };  // Output shape not validated
  }
} );

Both Schemas Missing

// WRONG: No validation at all
export const transformData = step( {
  name: 'transformData',
  // No schemas!
  fn: async input => {
    return transform( input );
  }
} );

Solution

Always define both inputSchema and outputSchema for every step:

Complete Step Definition

import { z, step } from '@outputai/core';

export const processData = step( {
  name: 'processData',
  inputSchema: z.object( {
    id: z.string(),
    value: z.number(),
    optional: z.string().optional()
  } ),
  outputSchema: z.object( {
    result: z.string(),
    processedAt: z.number()
  } ),
  fn: async input => {
    // input is fully typed: { id: string, value: number, optional?: string }
    return {
      result: `Processed ${input.id}`,
      processedAt: Date.now()
    };
    // output is validated against outputSchema
  }
} );

Schema Definition Best Practices

Use Descriptive Schemas

// Good: Clear, descriptive schema
inputSchema: z.object( {
  userId: z.string().uuid(),
  email: z.string().email(),
  age: z.number().int().positive()
} )

Handle Optional Fields

inputSchema: z.object( {
  required: z.string(),
  optional: z.string().optional(),
  withDefault: z.string().default( 'fallback' )
} )

Use Schema Composition

// Define reusable schemas
const userSchema = z.object( {
  id: z.string(),
  name: z.string()
} );

const addressSchema = z.object( {
  street: z.string(),
  city: z.string()
} );

// Compose in step
inputSchema: z.object( {
  user: userSchema,
  address: addressSchema
} )

Handle Arrays and Nested Objects

inputSchema: z.object( {
  items: z.array( z.object( {
    id: z.string(),
    quantity: z.number()
  } ) ),
  metadata: z.record( z.string() )
} )

Finding Steps Without Schemas

Search your codebase:

# Find step definitions
grep -rn "step({" src/workflows/

# Look for steps without inputSchema
grep -A5 "step({" src/workflows/ | grep -B2 "fn:"

# Check if schemas are present
grep -rn "inputSchema:" src/workflows/
grep -rn "outputSchema:" src/workflows/

Review each step definition to ensure both schemas are present.

Benefits of Explicit Schemas

  1. Runtime Validation: Catches data errors early
  2. Type Safety: Full TypeScript inference in step functions
  3. Documentation: Schemas document expected data shapes
  4. Serialization: Ensures proper data serialization between steps
  5. Error Messages: Clear validation errors when data is wrong

Common Schema Patterns

API Response Steps

export const fetchUser = step( {
  name: 'fetchUser',
  inputSchema: z.object( {
    userId: z.string()
  } ),
  outputSchema: z.object( {
    user: z.object( {
      id: z.string(),
      name: z.string(),
      email: z.string()
    } ).nullable(),  // Handle not found
    found: z.boolean()
  } ),
  fn: async input => {
    const user = await api.getUser( input.userId );
    return { user, found: user !== null };
  }
} );

Transformation Steps

export const transformData = step( {
  name: 'transformData',
  inputSchema: z.object( {
    raw: z.array( z.unknown() )
  } ),
  outputSchema: z.object( {
    processed: z.array( z.object( {
      id: z.string(),
      value: z.number()
    } ) ),
    count: z.number()
  } ),
  fn: async input => {
    const processed = input.raw.map( transformItem );
    return { processed, count: processed.length };
  }
} );

Void Output Steps

For steps that don't return meaningful data:

export const logEvent = step( {
  name: 'logEvent',
  inputSchema: z.object( {
    event: z.string(),
    data: z.record( z.unknown() )
  } ),
  outputSchema: z.object( {
    logged: z.literal( true )
  } ),
  fn: async input => {
    await logger.log( input.event, input.data );
    return { logged: true };
  }
} );

Verification

After adding schemas:

  1. TypeScript check: npm run output:worker:build should pass without type errors
  2. Runtime test: npx output workflow run <name> '<input>' should validate correctly
  3. Invalid input test: Pass invalid data and verify validation errors appear

Related Issues

  • For Zod import issues, see output-error-zod-import
  • For type mismatches despite schemas, verify schema matches actual data

原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。