Puzzlet allows you to collaborate on prompts while maintaining type safety in a production environment. This includes type generation from remote environments, local development, versioning, and integration with the Puzzlet platform.

Example

Here’s a prompt with schema definitions:

math/addition.prompt.mdx
---
name: math-addition
metadata:
  model:
    name: gpt-4o
    settings:
      schema:
        type: "object"
        properties:
          sum:
            type: "number"
            description: "The sum of the two numbers"
          explanation:
            type: "string"
            description: "Step by step explanation"
        required: ["sum", "explanation"]
input_schema:
  type: "object"
  properties:
    num1:
      type: "number"
      description: "First number to add"
    num2:
      type: "number"
      description: "Second number to add"
  required: ["num1", "num2"]
---

<System>You are a helpful math assistant that performs addition.</System>
<User>What is the sum of {props.num1} and {props.num2}?</User>

Running generate-types will create:

puzzlet.types.ts
// Auto-generated types from Puzzlet
// Do not edit this file directly

interface Math$AdditionIn {
  /** First number to add */
  num1: number;
  /** Second number to add */
  num2: number;
}

interface Math$AdditionOut {
  /** The sum of the two numbers */
  sum: number;
  /** Step by step explanation */
  explanation: string;
}

interface Math$Addition {
  input: Math$AdditionIn;
  output: Math$AdditionOut;
}

export default interface PuzzletTypes {
  "math/addition.prompt.mdx": Math$Addition
}

Generating Types

Puzzlet provides multiple ways to generate types from your prompts:

Local Development
# Generate types from a running Puzzlet server
npx @puzzlet/cli generate-types --local 9002 > puzzlet.types.ts

Using Generated Types

The Puzzlet SDK is fully type-safe when using generated types:

import PuzzletTypes from './puzzlet.types';
import { Puzzlet } from '@puzzlet/sdk';
import { createTemplateRunner } from "@puzzlet/agentmark";

const puzzlet = new Puzzlet<PuzzletTypes>({
  apiKey: process.env.PUZZLET_API_KEY!,
  appId: process.env.PUZZLET_APP_ID!,
}, createTemplateRunner);

// Initialize tracing for observability
const tracer = puzzlet.initTracing();

const run = async () => {
  // Load prompt with type safety
  const prompt = await puzzlet.fetchPrompt("math/addition.prompt.mdx");
  
  // Run with type checking and telemetry
  const result = await prompt.run({
    num1: 5,
    num2: 3
  }, {
    telemetry: {
      functionId: 'example-function',
      metadata: { userId: 'user-123' }
    }
  });
  
  // Type-safe access to results
  const sum = result.result.sum;
  console.log(result.result.explanation);  // Also type-safe
}

Best Practices

  1. Development:

    • Use --local during development
    • Keep types in sync with your prompts
  2. CICD (coming soon):

    • Run type checking against the Puzzlet platform
    • Check for any diffs between Puzzlet and your branch, and fail if there are any

Further Reading