Skip to content

TypeSpec Schema Guide

The AgentSchema specification is defined using TypeSpec, a language for defining APIs and data models. All schema changes start here.

  • Directoryagentschema-emitter/lib/model/
    • main.tsp entry point - imports all other files
    • core.tsp base templates (Named<>, Id<>)
    • agent.tsp AgentDefinition, PromptAgent, Workflow
    • manifest.tsp AgentManifest
    • model.tsp Model, ModelOptions
    • connection.tsp Connection types
    • template.tsp Template, Format, Parser
    • properties.tsp Property, PropertySchema
    • tools.tsp Tool base and FunctionTool
    • Directorytools/ specialized tools
      • file.tsp
      • mcp.tsp
      • openapi.tsp
      • web.tsp
      • interpreter.tsp

Every model needs:

  1. A namespace AgentSchema; declaration
  2. Documentation with @doc()
  3. Sample values with @sample() for test generation
import "agentschema-emitter";
namespace AgentSchema;
/**
* Description of the model (used in generated docs).
*/
model MyModel {
@doc("Description of this property")
@sample(#{ name: "example-name" })
name: string;
@doc("An optional property")
@sample(#{ count: 42 })
count?: int32;
}

The @sample decorator is required for test generation. It provides example values that:

  • Generate test cases in all runtime libraries
  • Validate serialization/deserialization roundtrips
  • Document expected usage
// Simple values
@sample(#{ myString: "hello" })
@sample(#{ myNumber: 42 })
@sample(#{ myBool: true })
// Arrays
@sample(#{ tags: #["tag1", "tag2"] })
// Objects
@sample(#{ metadata: #{ key: "value" } })
TypeSpecC#PythonTypeScriptGo
stringstringstrstringstring
int32intintnumberint32
int64longintnumberint64
float32floatfloatnumberfloat32
float64doublefloatnumberfloat64
booleanboolboolbooleanbool
string[]IList<string>list[str]string[][]string
Record<unknown>IDictionary<string, object>dict[str, Any]Record<string, unknown>map[string]any

Use @abstract and @discriminator for type hierarchies:

@abstract
@discriminator("kind")
model Tool {
@doc("Type discriminator")
@sample(#{ kind: "function" })
kind: string;
@doc("Tool description")
@sample(#{ description: "A helpful tool" })
description?: string;
}
model FunctionTool extends Tool {
@doc("Type discriminator")
@sample(#{ kind: "function" })
kind: "function";
@doc("Function name")
@sample(#{ name: "myFunction" })
name: string;
}

Allow models to be initialized from scalar values:

@shorthand(string, #{ input: "{value}" })
model Binding {
@doc("The input property to bind")
@sample(#{ input: "myInput" })
input: string;
}

This allows:

# Full form
binding:
input: myInput
# Shorthand form
binding: myInput
@doc("Temperature setting")
@sample(#{ temperature: 0.7 })
temperature?: float32 = 0.7;
alias ApiType = "chat" | "responses" | string;
@doc("API type")
@sample(#{ apiType: "chat" })
apiType?: ApiType;
@doc("Model configuration")
@sample(#{ model: #{ id: "gpt-4" } })
model?: Model;

Always regenerate and test:

Terminal window
cd agentschema
npm run generate
# Test all runtimes
cd ../runtime/csharp && dotnet test
cd ../python/agentschema && uv run pytest tests/
cd ../../typescript/agentschema && npm test
cd ../../go/agentschema && go test ./...

Ensure you have import "agentschema-emitter"; at the top of your file.

Check that your file is imported in main.tsp.

  • Verify @sample values are valid for the property type
  • Check that required properties have samples
  • Ensure discriminator values match in child classes