CodeSpeakとは?Kotlin作者によるLLM向け新言語

Ashley Innocent

Ashley Innocent

13 3月 2026

CodeSpeakとは?Kotlin作者によるLLM向け新言語

要約

CodeSpeakは、Kotlinの制作者によって作成された、大規模言語モデル(LLM)との通信のための形式仕様言語です。曖昧な自然言語のプロンプトを使用する代わりに、CodeSpeakは誤解を減らし、一貫性を向上させ、ソフトウェア開発タスクにおけるLLMとの対話をより予測可能にする構造化された構文を提供します。

はじめに

「ユーザー管理のためのREST APIを生成してください。」このプロンプトをLLMに送ると、コードが返ってきます。しかし、それはあなたが望んだものでしょうか?認証は含まれていますか?レート制限は?入力検証は?LLMが仮定を立てた結果、あなたは機能をリリースする代わりに、AIが生成したコードをデバッグすることになります。

この曖昧性の問題は、ChatGPTが登場して以来、LLMベースの開発を悩ませてきました。自然言語は柔軟ですが、その柔軟性が不整合を生み出します。同じプロンプトでも、実行ごとに、モデルごとに、あるいは温度設定によって異なる結果が生じる可能性があります。

そこで登場するのが、Kotlinの制作者が手掛けた形式仕様言語、CodeSpeakです。LLMがあなたの英語を正しく解釈してくれることを期待する代わりに、曖昧さを排除する構造化された仕様を記述します。プロンプトのためのTypeScriptと考えれば分かりやすいでしょう。LLMとのコミュニケーションに型安全性と構造を追加します。

💡
APIを構築していて、LLMが生成したコードから一貫性のあるテスト可能な結果が必要な場合、ApidogはAIコーディングツールと連携し、API仕様を検証し、エンドポイントをテストし、デプロイ前に問題を特定します。CodeSpeakは生成を予測可能にし、Apidogはその動作を保証します。

ボタン

このガイドでは、CodeSpeakとは何か、自然言語プロンプトとの比較、そしてAPI開発ワークフローでどのように使用するかを学びます。実際の構文例を見て、形式仕様と自然言語のどちらを使うべきかを理解し、既存のAPIテストツールとCodeSpeakを統合する方法を発見するでしょう。

CodeSpeakとは?

CodeSpeakは、LLMが高い精度で解釈できる形式仕様を記述するために設計されたドメイン固有言語(DSL)です。JetBrainsのKotlinリードデザイナーであるDmitry Jemerovによって作成されたCodeSpeakは、根本的な問題に取り組んでいます。それは、自然言語が正確なソフトウェア仕様には曖昧すぎるという問題です。

核となる問題

LLMに「ユーザー認証システムを作成してください」と指示すると、モデルは以下を推測しなければなりません。

それぞれの推測点において、あなたが意図したものとLLMが生成したものとの間にずれが生じる可能性があります。CodeSpeakは、仕様を明示的にすることで、これらの推測点を排除します。

CodeSpeakがプロンプトとどう異なるか

従来のプロンプト:

Create a REST API endpoint for user login that accepts email and password,
returns a JWT token, and handles invalid credentials gracefully.

CodeSpeakの仕様:

endpoint POST /auth/login {
  request {
    body {
      email: string @format(email) @required
      password: string @minLength(8) @required
    }
  }

  response 200 {
    body {
      token: string @format(jwt)
      expiresIn: number @unit(seconds)
    }
  }

  response 401 {
    body {
      error: string @enum("invalid_credentials", "account_locked")
    }
  }
}

CodeSpeak版はより長いですが、曖昧さはありません。LLMは何を生成すべきかを正確に理解しています。

主な機能

  1. 型安全性: 変数には明示的な型(string、number、boolean、object、array)があります。
  2. 制約: 組み込みのバリデータ(@required、@minLength、@format、@range)
  3. 構造: リクエスト、レスポンス、データモデルの明確な階層
  4. 構成可能性: 再利用可能なコンポーネントと型定義
  5. 決定性: 同じ仕様は、実行ごとに一貫した出力を生成します。

API開発におけるCodeSpeakの重要性

API開発には正確さが求められます。検証ルールが欠けていたり、ステータスコードが間違っていたり、エラーメッセージが曖昧だったりすると、クライアントとの統合が破綻する可能性があります。LLMを使用してAPIコードを生成する場合、その正確さはさらに重要になります。

曖昧さの代償

この実際のシナリオを考えてみましょう。開発者がLLMに「ユーザーエンドポイントにページネーションを追加してください」とプロンプトを出します。LLMはpagelimitパラメータを使用するコードを生成します。しかし、既存のAPIはoffsetcountを使用しています。これにより、エンドポイント間で不整合が生じ、クライアントの期待を裏切ってしまいます。

CodeSpeakを使えば、ページネーションのパターンを一度だけ指定できます。

pagination {
  style: offset-based
  parameters {
    offset: number @default(0) @min(0)
    count: number @default(20) @min(1) @max(100)
  }
}

このページネーション仕様を使用するすべてのエンドポイントは一貫したものになります。

APIチームへのメリット

CodeSpeakと自然言語プロンプトの比較

自然言語の代わりにCodeSpeakを使うべきなのはいつでしょうか?答えは、精度の要件とイテレーションのコストによって異なります。

自然言語を使うべき時

自然言語プロンプトは、以下の状況でうまく機能します。

自然言語は記述が迅速であり、LLMに可能性を探らせたいような自由形式の質問に適しています。

CodeSpeakを使うべき時

CodeSpeakは、以下の状況でより優れています。

他のシステムが依存するコードを生成する場合は、CodeSpeakを使用してください。

比較表

側面 自然言語 CodeSpeak
精度 低い - 解釈が必要 高い - 明示的な仕様
一貫性 実行ごとに異なる 決定的な出力
学習曲線 なし - 英語を書くだけ 中程度 - 構文を学ぶ必要あり
冗長性 簡潔 より冗長
最適用途 探索、説明 本番コード、API
エラー率 高い - 曖昧さの問題 低い - 仕様検証
イテレーション速度 最初の草稿は速い 記述は遅いが、洗練は速い
ドキュメント プロンプトに暗黙的に含まれる 仕様がドキュメントとして機能

ハイブリッドアプローチ

どちらか一方を選ぶ必要はありません。多くのチームは両方を使用しています。

  1. 設計には自然言語: 「JWTトークンを使用したユーザー認証システムを設計してください」
  2. 実装にはCodeSpeak: 各エンドポイントの形式仕様を記述
  3. 洗練には自然言語: 「ログインエンドポイントにレート制限を追加してください」
  4. 確定にはCodeSpeak: レート制限ルールで仕様を更新

このハイブリッドアプローチにより、自然言語の速度と形式仕様の精度を両立できます。

CodeSpeakの仕組み

CodeSpeakはあなたとLLMの間に位置します。あなたがCodeSpeakの仕様を記述し、LLMがそれを解釈して、その仕様に合致するコードを生成します。

コンパイルモデル

CodeSpeakは伝統的な意味でのコンパイルはされません。そうではなく、LLMが理解するように訓練された構造化された形式です。契約書のようなものだと考えてください。

  1. 仕様を記述する: CodeSpeak構文で何を望むかを定義します。
  2. LLMが仕様を解析する: モデルが構造と制約を理解します。
  3. LLMがコードを生成する: 出力が仕様に一致します。
  4. 検証する: 生成されたコードが仕様を満たしているか確認します。

型システム

CodeSpeakはシンプルながら強力な型システムを使用しています。

プリミティブ型

複合型

型修飾子

制約システム

制約は型に検証ルールを追加します。

文字列制約

数値制約

配列制約

構成と再利用

CodeSpeakは再利用可能なコンポーネントの定義をサポートしています。

type User {
  id: string @format(uuid) @required
  email: string @format(email) @required
  name: string @minLength(1) @maxLength(100) @required
  createdAt: string @format(iso8601) @required
}

type PaginatedResponse<T> {
  data: array<T> @required
  pagination: object {
    offset: number @required
    count: number @required
    total: number @required
  } @required
}

endpoint GET /users {
  response 200 {
    body: PaginatedResponse<User>
  }
}

この構成モデルにより、仕様はDRY(Don’t Repeat Yourself - 繰り返しを避ける)に保たれ、保守が容易になります。

Apidogを使ったAPIテストのためのCodeSpeakの使用

CodeSpeakは正確なAPI仕様を生成します。Apidogは、それらの仕様を自動テストに変換します。両者がどのように連携するかを見てみましょう。

ワークフローの概要

  1. CodeSpeak仕様の記述: APIエンドポイントを形式的に定義します。
  2. コードの生成: LLMを使用して仕様から実装を作成します。
  3. Apidogへのインポート: CodeSpeak仕様をOpenAPI形式に変換します。
  4. テストの生成: Apidogが仕様からテストケースを作成します。
  5. 検証の実行: 実装が仕様に一致しているかを確認します。

CodeSpeakからOpenAPIへの変換

CodeSpeakの仕様はOpenAPI 3.0にきれいにマッピングされます。

CodeSpeak

endpoint POST /users {
  request {
    body {
      email: string @format(email) @required
      name: string @minLength(1) @required
    }
  }
  response 201 {
    body {
      id: string @format(uuid)
      email: string
      name: string
    }
  }
}

OpenAPIの等価物

paths:
  /users:
    post:
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email, name]
              properties:
                email:
                  type: string
                  format: email
                name:
                  type: string
                  minLength: 1
      responses:
        '201':
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    format: uuid
                  email:
                    type: string
                  name:
                    type: string

シンプルなコンバータスクリプトを作成するか、LLMを使用してCodeSpeakをOpenAPIに変換できます。

Apidogでのテスト

OpenAPI仕様をApidogに読み込んだら:

仕様のインポート: 設定 → インポート → OpenAPI 3.0

テストケースの生成: Apidogは各エンドポイントのテストを自動生成します。

テストデータの追加: 制約に基づいて有効および無効な入力を定義します。

検証の実行: API実装に対して実行し、レスポンスが仕様に一致するか確認します。

Apidogの強みは、API実装が仕様に合致していることを検証することです。CodeSpeakは仕様が正確であることを保証します。

例: ログインエンドポイントのテスト

CodeSpeak仕様

endpoint POST /auth/login {
  request {
    body {
      email: string @format(email) @required
      password: string @minLength(8) @required
    }
  }

  response 200 {
    body {
      token: string @format(jwt) @required
      expiresIn: number @min(1) @required
    }
  }

  response 401 {
    body {
      error: string @enum("invalid_credentials") @required
    }
  }

  response 422 {
    body {
      error: string @enum("validation_error") @required
      fields: array<string> @required
    }
  }
}

Apidogテストケース

  1. 有効なログイン: 正しいメールアドレス/パスワードを送信し、JWTを含む200を期待
  2. 無効なメール形式: 不正な形式のメールアドレスを送信し、422を期待
  3. 短いパスワード: 7文字のパスワードを送信し、422を期待
  4. 誤った認証情報: 有効な形式だが誤ったパスワードを送信し、401を期待
  5. 不足しているフィールド: 空のボディを送信し、422を期待

Apidogはこれらのテストケースを仕様から自動的に生成します。あなたはテストデータを提供するだけです。

CodeSpeakの構文と例

一般的なAPIパターンのCodeSpeak構文の実際の例を見てみましょう。

基本的なエンドポイント定義

endpoint GET /health {
  response 200 {
    body {
      status: string @enum("ok", "degraded", "down") @required
      timestamp: string @format(iso8601) @required
    }
  }
}

これは、ステータスとタイムスタンプを返すヘルスチェックエンドポイントを定義しています。

CRUD操作

作成 (Create)

endpoint POST /products {
  request {
    headers {
      Authorization: string @pattern("^Bearer .+") @required
    }
    body {
      name: string @minLength(1) @maxLength(200) @required
      price: number @min(0) @required
      category: string @enum("electronics", "clothing", "food") @required
      inStock: boolean @default(true)
    }
  }

  response 201 {
    body {
      id: string @format(uuid) @required
      name: string @required
      price: number @required
      category: string @required
      inStock: boolean @required
      createdAt: string @format(iso8601) @required
    }
  }

  response 401 {
    body {
      error: string @enum("unauthorized") @required
    }
  }
}

読み取り (Read)

endpoint GET /products/:id {
  parameters {
    id: string @format(uuid) @required
  }

  response 200 {
    body {
      id: string @format(uuid) @required
      name: string @required
      price: number @required
      category: string @required
      inStock: boolean @required
      createdAt: string @format(iso8601) @required
      updatedAt: string @format(iso8601) @required
    }
  }

  response 404 {
    body {
      error: string @enum("not_found") @required
    }
  }
}

更新 (Update)

endpoint PATCH /products/:id {
  parameters {
    id: string @format(uuid) @required
  }

  request {
    headers {
      Authorization: string @pattern("^Bearer .+") @required
    }
    body {
      name: string @minLength(1) @maxLength(200) @optional
      price: number @min(0) @optional
      inStock: boolean @optional
    }
  }

  response 200 {
    body {
      id: string @format(uuid) @required
      name: string @required
      price: number @required
      inStock: boolean @required
      updatedAt: string @format(iso8601) @required
    }
  }

  response 404 {
    body {
      error: string @enum("not_found") @required
    }
  }
}

削除 (Delete)

endpoint DELETE /products/:id {
  parameters {
    id: string @format(uuid) @required
  }

  request {
    headers {
      Authorization: string @pattern("^Bearer .+") @required
    }
  }

  response 204 {}

  response 404 {
    body {
      error: string @enum("not_found") @required
    }
  }
}

ページネーションとフィルタリング

endpoint GET /products {
  query {
    offset: number @default(0) @min(0) @optional
    limit: number @default(20) @min(1) @max(100) @optional
    category: string @enum("electronics", "clothing", "food") @optional
    minPrice: number @min(0) @optional
    maxPrice: number @min(0) @optional
    inStock: boolean @optional
  }

  response 200 {
    body {
      data: array<object {
        id: string @format(uuid) @required
        name: string @required
        price: number @required
        category: string @required
        inStock: boolean @required
      }> @required
      pagination: object {
        offset: number @required
        limit: number @required
        total: number @required
      } @required
    }
  }
}

ネストされたリソース

endpoint GET /users/:userId/orders {
  parameters {
    userId: string @format(uuid) @required
  }

  query {
    status: string @enum("pending", "shipped", "delivered", "cancelled") @optional
  }

  response 200 {
    body {
      data: array<object {
        id: string @format(uuid) @required
        userId: string @format(uuid) @required
        status: string @enum("pending", "shipped", "delivered", "cancelled") @required
        items: array<object {
          productId: string @format(uuid) @required
          quantity: number @min(1) @required
          price: number @min(0) @required
        }> @required
        total: number @min(0) @required
        createdAt: string @format(iso8601) @required
      }> @required
    }
  }
}

ファイルアップロード

endpoint POST /products/:id/image {
  parameters {
    id: string @format(uuid) @required
  }

  request {
    headers {
      Authorization: string @pattern("^Bearer .+") @required
      Content-Type: string @enum("multipart/form-data") @required
    }
    body {
      image: file @mimeType("image/jpeg", "image/png") @maxSize(5242880) @required
    }
  }

  response 200 {
    body {
      imageUrl: string @format(url) @required
    }
  }

  response 413 {
    body {
      error: string @enum("file_too_large") @required
    }
  }
}

CodeSpeakのベストプラクティス

型から始める

エンドポイントを記述する前に、データモデルを定義します。

type Product {
  id: string @format(uuid) @required
  name: string @minLength(1) @maxLength(200) @required
  price: number @min(0) @required
  category: string @enum("electronics", "clothing", "food") @required
  inStock: boolean @required
  createdAt: string @format(iso8601) @required
  updatedAt: string @format(iso8601) @required
}

endpoint GET /products/:id {
  response 200 {
    body: Product
  }
}

これにより、仕様はDRYに保たれ、変更が容易になります。

固定値にはEnumを使用する

値が制約されている場合に自由形式の文字列を使用しないでください。

悪い例

status: string @required

良い例

status: string @enum("pending", "approved", "rejected") @required

Enumはタイプミスを防ぎ、有効な値を明示的にします。

コメントでドキュメント化する

CodeSpeakはコメントをサポートしています。

// ユーザー認証エンドポイント
// レート制限: IPアドレスごとに1分あたり5リクエスト
endpoint POST /auth/login {
  request {
    body {
      // 有効なメール形式である必要があります
      email: string @format(email) @required

      // 最低8文字、数字と特殊文字を含む必要があります
      password: string @minLength(8) @required
    }
  }

  response 200 {
    body {
      // JWTトークンは24時間有効です
      token: string @format(jwt) @required
      expiresIn: number @default(86400) @required
    }
  }
}

コメントは、他の開発者が仕様を理解するのに役立ちます。

仕様をバージョン管理する

CodeSpeakの仕様をコードと一緒にバージョン管理下に保存します。

/api-specs
  /v1
    auth.codespeak
    users.codespeak
    products.codespeak
  /v2
    auth.codespeak
    users.codespeak

これにより、APIが時間とともにどのように進化するかを追跡できます。

生成前に検証する

コードを生成する前に、LLMを使用してCodeSpeakの仕様を検証します。

プロンプト: 「このCodeSpeak仕様にエラー、不整合、または欠落している制約がないか確認してください: [仕様を貼り付け]」

LLMは次のような問題を検出できます。

コードだけでなく仕様をテストする

CodeSpeakの仕様自体を検証するテストを記述します。

制限事項と考慮事項

CodeSpeakは完璧ではありません。トレードオフを以下に示します。

学習曲線

CodeSpeakは新しい構文を学ぶ必要があります。あなたのチームは次の時間を必要とします。

開発者がCodeSpeakに慣れるまで1〜2週間の期間を見積もりましょう。

冗長性

CodeSpeakの仕様は、自然言語プロンプトよりも長くなります。シンプルなエンドポイントでも、CodeSpeakでは20行になるのに対し、英語では2行で済むかもしれません。

この冗長性が重要な点であり、明示的であることを強制します。しかし、最初の草案作成は遅くなります。

LLMのサポート

すべてのLLMがCodeSpeakを同等に理解できるわけではありません。コードで訓練されたモデル(GPT-4、Claude、Codexなど)は、汎用モデルよりも適切に処理します。

CodeSpeakにコミットする前に、あなたのLLMでテストしてください。

メンテナンスのオーバーヘッド

APIが変更されるたびに、CodeSpeakの仕様を更新する必要があります。これは、コードを変更するだけの作業に比べて追加の作業です。

利点は、仕様がドキュメントとして機能し、必要に応じてコードを再生成できることです。

万能薬ではない

CodeSpeakは曖昧さを減らしますが、LLMのすべてのエラーを排除するわけではありません。モデルは依然として、次のようなことを起こす可能性があります。

依然としてコードレビュー、テスト、検証が必要です。CodeSpeakは仕様をより明確にするだけです。

実際のユースケース

ユースケース1: チーム間のAPI一貫性

問題: あるフィンテック企業には、マイクロサービスを構築する5つのチームがあります。各チームはLLMを使用してAPIコードを生成していますが、エンドポイントに一貫性がありません。あるチームはページネーションにpage/sizeを使用し、別のチームはoffset/limitを使用し、さらに別のチームはcursorを使用しています。

解決策: プラットフォームチームは、一般的なパターンのCodeSpeakテンプレートを作成します。

// Standard pagination pattern
type Pagination {
  offset: number @default(0) @min(0)
  limit: number @default(20) @min(1) @max(100)
}

// Standard error response
type ErrorResponse {
  error: string @required
  message: string @required
  requestId: string @format(uuid) @required
}

すべてのチームは、CodeSpeakの仕様でこれらのテンプレートを使用します。これにより、すべてのAPIエンドポイントが同じパターンに従うようになります。

結果: 開発者がどのエンドポイントからも何を期待すべきかを知っているため、クライアントとの統合時間が40%短縮されます。

ユースケース2: 検証付きの迅速なプロトタイピング

問題: あるeコマーススタートアップは、2週間で20のAPIエンドポイントをプロトタイプ化する必要があります。彼らはLLMを使用してコードを迅速に生成していますが、仕様が曖昧なためバグがすり抜けてしまいます。

解決策: チームはまずすべての20のエンドポイントについてCodeSpeakの仕様を記述します。彼らは2時間の会議で仕様をレビューし、次のような問題を特定します。

仕様を修正した後、CodeSpeakからコードを生成します。仕様をApidogにインポートし、テストスイートを自動的に生成します。

結果: 以前のLLMが生成したコードよりもバグが60%少なく、すべての20エンドポイントを期日通りにリリースしました。

ユースケース3: 仕様からのAPIドキュメント生成

問題: あるSaaS企業のAPIドキュメントは常に古くなっています。開発者はコードを変更しても、ドキュメントの更新を忘れてしまいます。

解決策: 彼らはCodeSpeakの仕様を真実の源として記述します。APIを変更する必要がある場合、次のようにします。

  1. CodeSpeakの仕様を更新する
  2. 仕様からコードを再生成する
  3. 仕様からドキュメントを自動生成する

ドキュメントは、コードを生成するのと同じ仕様から派生しているため、常に正確です。

結果: APIの混乱に関する顧客サポートチケットが50%減少しました。

結論

CodeSpeakは、LLMとの対話に型安全性と構造をもたらします。API開発においては、これは次のことを意味します。

すべてのタスクにCodeSpeakを使用する必要はありません。自然言語は探索や高レベル設計には依然として優れています。しかし、本番APIコードを生成する際には、CodeSpeakはエラーを削減し、イテレーションを加速させます。

主要なポイント

ボタン

よくある質問

CodeSpeakはプログラミング言語ですか?

いいえ、CodeSpeakは仕様言語であり、プログラミング言語ではありません。CodeSpeakを直接コンパイルしたり実行したりすることはありません。代わりに、CodeSpeakを使って何を望むかを記述し、LLMがその仕様から実際のコード(Python、JavaScript、Goなど)を生成します。

LLMを使ったコーディングのためにCodeSpeakを学ぶ必要がありますか?

いいえ、自然言語プロンプトを使い続けることができます。CodeSpeakはオプションであり、本番コードのために正確で一貫した結果が必要な場合に最も役立ちます。探索、プロトタイピング、または一度限りのスクリプトには、自然言語で十分です。

どのLLMがCodeSpeakをサポートしていますか?

CodeSpeakは、GPT-4、Claude Opus、GitHub Copilotのようなコードに特化したモデルで最も効果を発揮します。これらのモデルは構造化されたコードで訓練されており、汎用モデルよりも形式構文をよく理解しています。互換性を確認するために、CodeSpeakの例を使って特定のLLMをテストしてください。

既存のOpenAPI仕様をCodeSpeakに変換できますか?

はい、OpenAPIとCodeSpeakは密接にマッピングされます。コンバータスクリプトを作成するか、LLMを使用してOpenAPI YAMLをCodeSpeak構文に変換できます。変換はほとんど機械的であり、型、制約、エンドポイントは直接変換されます。

CodeSpeakとOpenAPIの比較

OpenAPIは既存のAPIをドキュメント化するための仕様形式です。CodeSpeakはLLMに何を生成すべきかを指示するための言語です。両者は異なる目的を持っていますが、補完的です。CodeSpeakからOpenAPIの仕様を生成し、Apidogのようなツールを使って実装をテストすることができます。

CodeSpeakはオープンソースですか?

2026年3月現在、CodeSpeakは新しく発表されたプロジェクトです。ライセンス情報とコミュニティリソースについては、CodeSpeak公式ウェブサイトをご確認ください。言語設計は公開されており、構造化された仕様を理解する任意のLLMと併用して使用を開始できます。

CodeSpeakはすべてのLLMエラーを防げますか?

いいえ、CodeSpeakは仕様の曖昧さを減らしますが、LLMは依然としてバグのあるコードを生成したり、エッジケースを見落としたり、セキュリティ上の問題を引き起こしたりする可能性があります。コードレビュー、テスト、検証は依然として必要です。CodeSpeakは「何を」より明確にしますが、「どのように」が完璧であることを保証するものではありません。

CodeSpeakの仕様を作成するにはどれくらいの時間がかかりますか?

シンプルなエンドポイントの場合、5〜10分かかります。ネストされたオブジェクト、複数のエラーケース、検証ルールを含む複雑なエンドポイントでは、20〜30分かかるかもしれません。これは自然言語プロンプトよりも遅いですが、曖昧なLLMの出力をデバッグするよりも高速です。

ApidogでAPIデザイン中心のアプローチを取る

APIの開発と利用をよりシンプルなことにする方法を発見できる