Example

Complete example
# PersonSkill.adl

skill PersonSkill "1.0.0"

use wg.core.PhoneNumber "1.0.0"
use VideoSkill.Datapoint "1.0.0" as VideoDatapoint

# ============================================
# Types
# ============================================

/// 5-digit US zip code
type ZipCode : string {
  minLen = 5
  maxLen = 5
  regex  = "^[0-9]{5}$"
}

/// Short display name
type ShortName : string {
  maxLen = 32
}

/// Case-insensitive identifier
type Tag : string {
  maxLen = 64
  caseInsensitive = true
}

/// Supported UI theme colors
enum Color : string {
  /// Corporate blue
  blue  = "blue"
  /// Alert/error red
  red   = "red"
  /// Success green
  green = "green"
}

enum Priority : int {
  low    = 0
  medium = 1
  high   = 2
}

/// Base entity with common identity fields
object Entity {
  /// Unique identifier
  id          guid     @readonly
  created     time     @readonly
}

/// A person in the system
object Person : Entity {
  /// Full legal name
  name        string
  /// Age in years
  age         int
  avatar      data?
  tags        string[]
  metadata    value{}
  nicknames   string{ShortName}
  zip         ZipCode
  addresses   Address[#]
  /// Datapoint properties with known keys
  props       value{symbolpath} {
    state       int
    statetext   string
    statevalue  float
  }
}

/// Sensor measurement with sparse transmission
@sparse
object Measurement {
  /// Measured value
  value    float
  unit     string
  source   string
}

/// Object with keyword-spelled field names (valid bare, section 2.4)
object LegacyConfig {
  type      string
  `error`   string   # escaping remains legal, equivalent to bare "error"
  mode      int
}

/// Action to perform in the current context
union AppAction {
  tag ActionType string

  /// Server-side backend operation
  BackendOperation {
    Data string
  }

  /// Call a specific number or person
  CallNumber {
    Person guid
    Field  int
    Phone  string
  }

  /// Complete the event in the current context
  CompleteEvent {}
}

# ============================================
# Errors
# ============================================

# Global errors — implicit on every function in this skill
@global
error Auth.Unauthorized

error Data.NotFound {
  Type string
  Id   string
}

error Data.Forbidden {
  Type string
  Id   string
}

error Data.Validation {
  Type              string
  Id                string
  ValidationResult  ErrorDataValidationResult[]
}

# ============================================
# Services
# ============================================

/// Service for managing persons
service PersonService {
  /// Retrieves a person by ID
  /// @param id Unique person identifier
  /// @return The person, or null if not found
  /// @error Data.NotFound No person exists with the given ID
  /// @error Data.Forbidden Caller lacks read permission
  func GetPerson(id: guid) -> Person? | Data.NotFound, Data.Forbidden

  /// Search for persons
  func FindPersons(query: string, maxResults: int?) -> Person[]

  /// Delete a person
  func DeletePerson(id: guid) -> void | Data.NotFound, Data.Forbidden

  /// Fired when a person's data changes
  notify PersonChanged(person: Person)

  /// Fired when a person is deleted
  notify PersonDeleted(id: guid)
}

# System-level functions with absolute wire names
service {
  func core.system.Ping() -> bool
  func core.system.GetVersion() -> string
}

# ============================================
# Versioned additions
# ============================================

/// Email and phone support
since "1.1.0" object Person {
  /// Primary contact email
  email string?
  /// Phone number
  phone PhoneNumber?
}

since "1.1.0" union AppAction {
  /// Play the specified sound
  PlaySound {
    File string
  }
}

since "1.1.0" service PersonService {
  /// Look up person by email
  func GetPersonByEmail(
    email: string,
    /// Include change history in response
    since "1.2.0" includeHistory: bool?,
  ) -> Person | Data.NotFound

  /// Update a person's data
  /// @error Data.Validation One or more properties are invalid
  func UpdatePerson(person: Person) -> void | Data.NotFound, Data.Validation
}

/// @deprecated Use GetPerson instead
since "1.0.0" until "1.3.0" service PersonService {
  func GetPersonLegacy(id: int) -> Person
}

# ============================================
# Concepts
# ============================================

/// A managed person entity
concept person.managed {
  is general.identifiable

  property fullName string

  /// Look up this person
  command Lookup -> Person
  /// Deactivate this person
  command Deactivate

  /// The person is currently active
  state IsActive bool

  event Modified
  event Deactivated
}
Last modified September 25, 2026