DEV Community

Cover image for What Is CodeSpeak? Kotlin Creator's New Language for LLMs
Wanda
Wanda

Posted on • Originally published at apidog.com

What Is CodeSpeak? Kotlin Creator's New Language for LLMs

TL;DR

CodeSpeak is a formal specification language—created by Kotlin’s creator—for communicating with Large Language Models (LLMs). Unlike natural language prompts, CodeSpeak uses structured syntax to minimize ambiguity, ensure consistent output, and make LLM-driven software development more predictable.

Try Apidog today

Introduction

When you prompt an LLM with “Generate a REST API for user management,” you might get back unexpected code. Did it include authentication, rate limiting, or input validation? Probably not exactly as you intended. The LLM makes assumptions, making debugging and iteration tedious.

This ambiguity is a core problem for LLM-based development. Natural language is flexible, but that flexibility leads to inconsistent results—across runs, models, or even temperature settings.

CodeSpeak solves this by letting you write structured specifications, not English prompts. It’s like TypeScript for prompts: you get type safety and clarity, reducing misinterpretation.

💡 If you need reliable, testable results from LLM-generated code, Apidog integrates with AI coding tools to validate API specs, test endpoints, and catch issues before deployment. CodeSpeak makes generation predictable. Apidog ensures it works.

In this guide, you’ll see how CodeSpeak works, how to use it for API development, syntax examples, and how to integrate it with your API test automation (like Apidog).

What Is CodeSpeak?

CodeSpeak is a DSL for writing formal specifications that LLMs interpret with high accuracy. Created by Dmitry Jemerov, Kotlin’s lead designer, CodeSpeak addresses the ambiguity of natural language in software specifications.

CodeSpeak Syntax Example

The Core Problem

Prompting an LLM with “create a user authentication system” forces the model to infer:

  • The authentication method (JWT/session/OAuth)
  • Password requirements
  • Token expiration
  • Error handling
  • Database schema
  • API endpoint structure

Each guess can diverge from your intent. CodeSpeak removes these guess points with explicit specs.

How CodeSpeak Differs from Prompts

Traditional prompt:

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

CodeSpeak spec:

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")
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

The CodeSpeak version is explicit—no ambiguity for the LLM.

Key Features

  1. Type Safety: Explicit types for all variables
  2. Constraints: Built-in validators (@required, @minLength, etc.)
  3. Structure: Clear hierarchy for requests, responses, and models
  4. Composability: Reusable type definitions
  5. Determinism: Same spec yields same output every time

Why CodeSpeak Matters for API Development

API work requires precision. A missing rule or ambiguous error message can break clients. With LLMs generating API code, precision is even more critical.

The Cost of Ambiguity

If you prompt “add pagination to the users endpoint,” an LLM might use page/limit while your standard is offset/count—leading to inconsistency.

With CodeSpeak, specify pagination once:

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

All endpoints using this stay consistent.

Benefits for API Teams

  • Consistency: All endpoints follow the same patterns
  • Faster Code Review: Review the spec, not just generated code
  • Automated Testing: CodeSpeak maps directly to API test cases. Apidog can import OpenAPI and generate test suites
  • Less Debugging: Specs document intent, reducing “why did it do that?”
  • Version Control: Specs are text—easy to diff and track

CodeSpeak vs Natural Language Prompts

When should you use CodeSpeak instead of English? It depends on how much precision you need.

When to Use Natural Language

Best for:

  • Exploratory tasks: “Show me ways to implement rate limiting”
  • High-level architecture: “Design a microservice e-commerce platform”
  • Code explanation/brainstorming

Natural language is fast for open-ended or brainstorming tasks.

When to Use CodeSpeak

Best for:

  • Production code generation
  • API contracts
  • Data models
  • Validation rules
  • Consistent, repeatable patterns

If code will be deployed or used by others, use CodeSpeak.

Comparison Table

Aspect Natural Language CodeSpeak
Precision Low, requires guessing High, explicit
Consistency Varies by run Deterministic
Learning Curve None Moderate
Verbosity Concise Verbose
Best For Exploration Production code, APIs
Error Rate Higher Lower (spec checked)
Iteration Fast draft Slower to write
Documentation Implicit Spec = docs

Hybrid Approach

Use both! For example:

  1. Design in natural language (“Design user authentication with JWT”)
  2. Implement with CodeSpeak (write specs per endpoint)
  3. Iterate using natural language (“Add rate limiting”)
  4. Lock in with CodeSpeak (update spec)

How CodeSpeak Works

You write a CodeSpeak spec, the LLM interprets it, and generates code to match.

The Compilation Model

It's not compiled in the traditional sense. Instead:

  1. Write the spec
  2. LLM parses the spec
  3. LLM generates code
  4. You validate output

Type System

Primitive Types:

  • string, number, boolean, null

Complex Types:

  • object, array, enum, union

Type Modifiers:

  • @required, @optional, @nullable, @default(value)

Constraint System

Add validation to types.

String Constraints:

  • @minLength(n), @maxLength(n), @pattern(regex), @format(type)

Number Constraints:

  • @min(n), @max(n), @multipleOf(n), @integer

Array Constraints:

  • @minItems(n), @maxItems(n), @uniqueItems

Composition and Reuse

Define reusable components:

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>
  }
}
Enter fullscreen mode Exit fullscreen mode

Using CodeSpeak for API Testing with Apidog

CodeSpeak gives you precise API specs. Apidog turns those specs into automated tests.

Workflow Overview

  1. Write CodeSpeak spec: Formal API definition
  2. Generate code: Use LLM to implement
  3. Import to Apidog: Convert CodeSpeak to OpenAPI
  4. Generate tests: Apidog builds test cases
  5. Run validation: Verify implementation matches spec

Converting CodeSpeak to OpenAPI

CodeSpeak maps directly to 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
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

OpenAPI Equivalent:

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
Enter fullscreen mode Exit fullscreen mode

You can script or prompt an LLM to convert CodeSpeak → OpenAPI.

Testing in Apidog

  1. Import the spec: Settings → Import → OpenAPI 3.0

Import Spec

  1. Generate test cases: Apidog auto-generates endpoint tests

Generated Tests

  1. Add test data: Define valid/invalid inputs per constraints

Test Data

  1. Run tests and Validate responses: Execute and check spec compliance

Run Tests

Apidog validates your implementation against the spec. CodeSpeak ensures your spec is unambiguous.

Example: Testing a Login Endpoint

CodeSpeak Spec:

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
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Auto-generated Apidog Test Cases:

  1. Valid login: Correct email/password → expect 200 with JWT
  2. Invalid email format: Malformed email → expect 422
  3. Short password: 7-chars → expect 422
  4. Wrong credentials: Valid format, wrong password → 401
  5. Missing fields: Empty body → 422

You define the test data; Apidog generates and runs the tests.

CodeSpeak Syntax and Examples

Basic Endpoint Definition

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

CRUD Operations

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
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Pagination and Filtering

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
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Nested Resources

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
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

File Upload

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
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Best Practices for CodeSpeak

Start with Types

Define data models up front:

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
  }
}
Enter fullscreen mode Exit fullscreen mode

Use Enums for Fixed Values

Avoid free-form strings:

Bad:

status: string @required
Enter fullscreen mode Exit fullscreen mode

Good:

status: string @enum("pending", "approved", "rejected") @required
Enter fullscreen mode Exit fullscreen mode

Document with Comments

Add comments for clarity:

// User authentication endpoint
// Rate limit: 5 requests per minute per IP
endpoint POST /auth/login {
  request {
    body {
      // Must be a valid email format
      email: string @format(email) @required

      // Minimum 8 characters, must include number and special char
      password: string @minLength(8) @required
    }
  }

  response 200 {
    body {
      // JWT token valid for 24 hours
      token: string @format(jwt) @required
      expiresIn: number @default(86400) @required
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Version Your Specs

Store specs in version control beside your code:

/api-specs
  /v1
    auth.codespeak
    users.codespeak
    products.codespeak
  /v2
    auth.codespeak
    users.codespeak
Enter fullscreen mode Exit fullscreen mode

Validate Before Generating

Prompt your LLM to review your CodeSpeak spec for errors before code generation:

Prompt: “Review this CodeSpeak spec for errors, inconsistencies, or missing constraints: [paste spec]”

Catch missing fields, naming mismatches, invalid constraints, or missing error responses.

Test the Spec, Not Just the Code

Validate your CodeSpeak specs:

  • Are all required fields marked?
  • Does every endpoint have error responses?
  • Are constraints realistic?
  • Do response types match requests where needed?

Limitations and Considerations

Learning Curve

CodeSpeak requires learning syntax and conventions. Budget a week or two for your team to get comfortable.

Verbosity

Specs are more verbose than natural language, but this forces necessary explicitness.

LLM Support

Not all LLMs handle CodeSpeak equally. Code-focused models (GPT-4, Claude, Copilot) work best. Test with your LLM before committing.

Maintenance Overhead

You must update specs with API changes. The upside: the same spec serves as documentation and can regenerate code.

Not a Silver Bullet

CodeSpeak reduces ambiguity, but LLMs can still make mistakes:

  • Inefficient code
  • Missed edge cases
  • Security bugs
  • Logic errors

Still use code review and testing—CodeSpeak just makes intent unambiguous.

Real-World Use Cases

Use Case 1: API Consistency Across Teams

Problem: Multiple teams use LLMs for API code; endpoints are inconsistent (pagination params, error formats, etc).

Solution: Platform team creates CodeSpeak templates for common patterns:

// Standard pagination
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
}
Enter fullscreen mode Exit fullscreen mode

All teams use these in their specs, ensuring consistency.

Result: Client integration time drops by 40% due to predictable endpoints.

Use Case 2: Rapid Prototyping with Validation

Problem: Startup needs to prototype 20 endpoints in 2 weeks. LLM-generated code is buggy due to vague specs.

Solution: Write and review CodeSpeak specs for all endpoints. Catch issues (e.g., missing auth, inconsistent ID formats, no rate limiting) in review. Generate code and tests via Apidog.

Result: Shipped all endpoints on time with 60% fewer bugs.

Use Case 3: API Documentation from Specs

Problem: API docs are always out-of-date.

Solution: Specs are the source of truth. Update spec, regenerate code and docs from it.

Result: API confusion tickets drop by 50%.

Conclusion

CodeSpeak adds type safety and structure to LLM workflows. For API devs, this means:

  • Consistency: Uniform endpoint patterns
  • Precision: No ambiguity
  • Testability: Specs → test cases
  • Documentation: Specs = docs
  • Maintainability: Explicit, trackable changes

Use CodeSpeak for production, natural language for exploration. The verbosity is a feature: it enforces clarity.

Key Takeaways:

  • CodeSpeak is a formal LLM spec language
  • It eliminates ambiguity in API specs
  • Use for production code; use natural language for exploration
  • Specs integrate with tools like Apidog for automated testing
  • Verbosity enforces explicit design

CodeSpeak Example

FAQ

Is CodeSpeak a programming language?

No. CodeSpeak is a specification language. You don’t compile it; you use it to describe what you want, and an LLM generates real code from it.

Do I need to learn CodeSpeak to use LLMs for coding?

No. Natural language prompts still work. CodeSpeak is optional—best when you need precise, consistent results. For prototyping or exploration, natural language is fine.

Which LLMs support CodeSpeak?

Works best with code-focused models like GPT-4, Claude Opus, or GitHub Copilot. Test your LLM with CodeSpeak examples to confirm compatibility.

Can I convert existing OpenAPI specs to CodeSpeak?

Yes. OpenAPI and CodeSpeak map closely. You can script or prompt an LLM to convert YAML to CodeSpeak—types, constraints, endpoints map directly.

How does CodeSpeak compare to OpenAPI?

OpenAPI documents existing APIs. CodeSpeak tells LLMs what to generate. They’re complementary: generate OpenAPI from CodeSpeak, then use tools like Apidog to test implementation.

Is CodeSpeak open source?

As of March 2026, CodeSpeak is newly announced. Check the official CodeSpeak website for licensing and community resources.

Can CodeSpeak prevent all LLM errors?

No. It reduces ambiguity, but LLMs can still produce buggy code, miss edge cases, or add security issues. Code review and testing are still necessary.

How long does it take to write a CodeSpeak spec?

A basic endpoint: 5-10 minutes. Complex endpoints: 20-30 minutes. Slower than English prompts, but faster than debugging unclear LLM output.

Top comments (0)