{"$id":"https://geoagents.chinmayasahu.com/spec/v1.json","title":"GeoAgents document (geoagents/v1)","$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"spec":{"type":"string","const":"geoagents/v1"},"experience":{"type":"object","properties":{"id":{"type":"string","maxLength":64},"title":{"type":"string","minLength":1,"maxLength":100},"description":{"default":"","type":"string","maxLength":2000},"kind":{"default":"collection","type":"string","enum":["tour","collection","hunt"]},"order":{"default":"any","description":"`sequence`: each stop unlocks after the previous one","type":"string","enum":["any","sequence"]},"language":{"default":"en-IN","type":"string","minLength":2,"maxLength":35},"cover":{"default":"📍","description":"Emoji shown on cards","type":"string","maxLength":16},"agents":{"default":[],"maxItems":200,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","maxLength":64},"name":{"type":"string","minLength":1,"maxLength":60},"role":{"default":"","description":"Short description, e.g. \"Local historian\"","type":"string","maxLength":80},"place":{"default":"","description":"Name of the place the agent stands at","type":"string","maxLength":120},"avatar":{"default":{},"type":"object","properties":{"emoji":{"default":"🧭","type":"string","minLength":1,"maxLength":16},"color":{"default":"#ffb703","type":"string","pattern":"^#[0-9a-fA-F]{6}$"}}},"anchor":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"circle"},"lat":{"type":"number","minimum":-90,"maximum":90,"description":"Latitude, WGS84 degrees"},"lng":{"type":"number","minimum":-180,"maximum":180,"description":"Longitude, WGS84 degrees"},"radius":{"type":"number","minimum":5,"maximum":5000,"description":"Metres"},"elevation":{"description":"Metres above sea level. Only enforced when the visitor's device reports a usable altitude.","type":"number","minimum":-500,"maximum":9000},"elevationTolerance":{"description":"± metres around `elevation` (default 15).","type":"number","minimum":1,"maximum":500},"floor":{"description":"Building floor (0 = ground). Matched only when the floor is known, e.g. from a QR code.","type":"integer","minimum":-20,"maximum":200}},"required":["type","lat","lng","radius"]},{"type":"object","properties":{"type":{"type":"string","const":"polygon"},"points":{"minItems":3,"maxItems":200,"type":"array","items":{"type":"object","properties":{"lat":{"type":"number","minimum":-90,"maximum":90,"description":"Latitude, WGS84 degrees"},"lng":{"type":"number","minimum":-180,"maximum":180,"description":"Longitude, WGS84 degrees"}},"required":["lat","lng"]}},"elevation":{"description":"Metres above sea level. Only enforced when the visitor's device reports a usable altitude.","type":"number","minimum":-500,"maximum":9000},"elevationTolerance":{"description":"± metres around `elevation` (default 15).","type":"number","minimum":1,"maximum":500},"floor":{"description":"Building floor (0 = ground). Matched only when the floor is known, e.g. from a QR code.","type":"integer","minimum":-20,"maximum":200}},"required":["type","points"]},{"type":"object","properties":{"type":{"type":"string","const":"route"},"points":{"minItems":2,"maxItems":500,"type":"array","items":{"type":"object","properties":{"lat":{"type":"number","minimum":-90,"maximum":90,"description":"Latitude, WGS84 degrees"},"lng":{"type":"number","minimum":-180,"maximum":180,"description":"Longitude, WGS84 degrees"}},"required":["lat","lng"]}},"width":{"type":"number","minimum":5,"maximum":500,"description":"Corridor width in metres"},"elevation":{"description":"Metres above sea level. Only enforced when the visitor's device reports a usable altitude.","type":"number","minimum":-500,"maximum":9000},"elevationTolerance":{"description":"± metres around `elevation` (default 15).","type":"number","minimum":1,"maximum":500},"floor":{"description":"Building floor (0 = ground). Matched only when the floor is known, e.g. from a QR code.","type":"integer","minimum":-20,"maximum":200}},"required":["type","points","width"]},{"type":"object","properties":{"type":{"type":"string","const":"code"},"kind":{"type":"string","enum":["qr","beacon"]},"code":{"type":"string","minLength":1,"maxLength":200},"lat":{"description":"Where to draw it on a map","type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180,"description":"Longitude, WGS84 degrees"},"elevation":{"description":"Metres above sea level. Only enforced when the visitor's device reports a usable altitude.","type":"number","minimum":-500,"maximum":9000},"elevationTolerance":{"description":"± metres around `elevation` (default 15).","type":"number","minimum":1,"maximum":500},"floor":{"description":"Building floor (0 = ground). Matched only when the floor is known, e.g. from a QR code.","type":"integer","minimum":-20,"maximum":200}},"required":["type","kind","code"]}]},"persona":{"default":"","description":"Who the agent is and how it talks","type":"string","maxLength":4000},"goal":{"default":"","description":"What the agent wants the visitor to get out of the visit","type":"string","maxLength":1000},"rules":{"default":"","description":"Extra rules from the creator","type":"string","maxLength":2000},"knowledge":{"default":"","description":"Facts the agent can draw on (plain text or Markdown)","type":"string","maxLength":40000},"sources":{"default":"","description":"Attribution for the knowledge","type":"string","maxLength":1000},"language":{"default":"en-IN","description":"BCP-47 language tag the agent starts in","type":"string","minLength":2,"maxLength":35},"voice":{"default":{},"type":"object","properties":{"rate":{"default":1,"type":"number","minimum":0.5,"maximum":2},"pitch":{"default":1,"type":"number","minimum":0,"maximum":2},"name":{"description":"Preferred voice name, if the device has it","type":"string","maxLength":120}}},"greeting":{"default":"","type":"string","maxLength":500},"returningGreeting":{"default":"","type":"string","maxLength":500},"farewell":{"default":"","type":"string","maxLength":300},"backupLines":{"default":[],"description":"Scripted replies used when AI is unavailable","maxItems":20,"type":"array","items":{"type":"string","maxLength":400}},"remote":{"default":"allowed","type":"string","enum":["allowed","onsite_only"]},"triggers":{"default":{},"type":"object","properties":{"dwellSeconds":{"default":20,"description":"Seconds inside before a `dwell` event","type":"integer","minimum":0,"maximum":3600},"cooldownMinutes":{"default":30,"description":"Minutes before the agent greets the same visitor again","type":"integer","minimum":0,"maximum":10080},"activeHours":{"description":"Local time windows when the agent is awake. Omit for always.","maxItems":14,"type":"array","items":{"type":"object","properties":{"days":{"minItems":1,"maxItems":7,"type":"array","items":{"type":"integer","minimum":0,"maximum":6},"description":"0 = Sunday"},"from":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},"to":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"}},"required":["days","from","to"]}}}}},"required":["name","anchor"]}}},"required":["title"]}},"required":["spec","experience"]}