Skip to main content
AgentMark provides type safety through JSON Schema definitions in your prompt files. agentmark generate-types compiles those schemas to TypeScript types you can pass to createAgentMark<T>() for compile-time validation and IDE autocomplete.

Defining types

Define input and output types in your prompt files using JSON Schema:
math/addition.prompt.mdx
---
name: math/addition
object_config:
  model_name: openai/gpt-5
  schema:
    type: object
    properties:
      answer:
        type: number
        description: "The sum of the two numbers"
    required: [answer]
input_schema:
  type: object
  properties:
    a:
      type: number
      description: "First number to add"
    b:
      type: number
      description: "Second number to add"
  required: [a, b]
---

<System>You compute sums.</System>
<User>What is {props.a} + {props.b}?</User>

Generating types

Generate TS types with the CLI:
agentmark generate-types --root-dir ./agentmark > agentmark.types.ts
For the prompt above, the generator emits:
agentmark.types.ts
// Auto-generated types from AgentMark
// Do not edit this file directly

interface Math$AdditionIn {
  a: number;
  b: number;
}

interface Math$AdditionOut {
  answer: number;
}

type Math$Addition = {
  kind: 'object';
  input:  Math$AdditionIn;
  output: Math$AdditionOut;
};

export default interface AgentmarkTypes {
  "math/addition.prompt.mdx": Math$Addition,
  "math/addition.prompt": Math$Addition,
  "math/addition": Math$Addition
}
Note two things:
  1. The wrapper (Math$Addition) is a type alias, while Math$AdditionIn / Math$AdditionOut are interfaces.
  2. Each prompt gets three key aliases: the full path with .prompt.mdx, the path ending in .prompt, and the bare name. Any of the three resolves to the same type when you call loadTextPrompt / loadObjectPrompt.

Using generated types

Pass the generated AgentmarkTypes interface as the generic parameter to createAgentMark<AgentmarkTypes>({ loader }). TypeScript then type-checks prompt names, props, and outputs on the neutral render. The client returns AgentMark’s neutral shape ({ messages, object_config } for object prompts); you pass that to your own model call or an executor.
import type AgentmarkTypes from "./agentmark.types";
import { createAgentMark } from "@agentmark-ai/prompt-core";

// `loader` from your client setup — see Client config.
const client = createAgentMark<AgentmarkTypes>({ loader });

// TypeScript enforces correct types from the prompt's input_schema
const prompt = await client.loadObjectPrompt("math/addition.prompt.mdx");
const { messages, object_config } = await prompt.format({
  props: {
    a: 5,   // must be number per input_schema
    b: 3,
  },
});

// You own the model call — e.g. with the Vercel AI SDK:
import { generateObject, jsonSchema } from "ai";
import { openai } from "@ai-sdk/openai";

const result = await generateObject({
  model: openai(object_config.model_name.replace(/^openai\//, "")),
  messages,
  schema: jsonSchema(object_config.schema),
});
const answer: number = result.object.answer;  // typed as Math$AdditionOut.answer

Benefits

  1. Compile-time safety: TypeScript flags prop-shape mismatches before runtime.
  2. IDE support: autocomplete and inline descriptions on props and outputs.
  3. Consistent interfaces: the same AgentmarkTypes drives both the loader and the caller.
  4. Documentation: JSON Schema descriptions flow through to TS JSDoc comments.

Best practices

  1. Define both input_schema and object_config.schema (when the prompt is an object prompt) in your prompt files.
  2. Use descriptive property names and add description fields; they become JSDoc comments.
  3. Mark required properties using required.
  4. Regenerate types after any schema edit: agentmark generate-types --root-dir ./agentmark > agentmark.types.ts.
  5. Commit agentmark.types.ts to version control so CI type-checks the contract.

Have questions?

Reach out any time: