Geocoder.ca Skills for AI Agents. October-23-2026:
AI coding agents are now writing a lot of geocoding code, and left to themselves they guess: they invent parameters, forget to ask for JSON, treat confidence scores as decoration and fall over on the first rate limit. So we published geolytica-skills, an open-source (MIT) set of agent skills that tells them how Geocoder.ca and Geocode.xyz actually work.
There are three skills:
The routing rule is built in: Canada or USA goes to Geocoder.ca, everything else to Geocode.xyz. Each skill also carries Python, Node.js, Perl, PHP and command-line references, which the agent loads only when it needs them, and a small wrapper script that reads your token from the environment, so it never appears in the commands the agent runs.
/plugin marketplace add geocode-xyz/geolytica-skills
/plugin install geolytica@geolytica-skills
Then put your keys in the environment the agent runs in (for example in ~/.zshrc):
export GEOCODER_CA_AUTH=your_geocoder_ca_token
export GEOCODE_XYZ_AUTH=your_geocode_xyz_key
Without a key, requests go to the free throttled port: fine for a quick look, but often busy. Using Gemini CLI, Codex or another agent? The skills are plain Markdown; see install.md. Agents that discover APIs on their own can also find us through the API catalog, the OpenAPI spec and llms.txt.
I installed the plugin and typed plain English, or sometimes just pasted an address. Nobody told the agent which service to use.
| # | Input | Service | Result | Conf. |
|---|---|---|---|---|
| 1 | 350 5th Ave, New York | Geocoder.ca | Empire State Building, NY 10118-0691 | 1.0 |
| 2 | 751 FAIR OKS AVENUE PASADNA CA | Geocoder.ca | 751 N Fair Oaks Ave, Pasadena, CA 91103-3069 | 1.0 |
| 3 | Metcalfe & Wellington, Ottawa | Geocoder.ca | Intersection in front of Parliament Hill | 0.9 |
| 4 | 1 Random St, Toronto | Geocoder.ca | 1 Random St, Toronto, ON M9B 2J3 | 1.0 |
| 5 | Avenue FR DE LA JOSNIERE 13 LE DORAT | Geocode.xyz | 13 Avenue de la Josnière, 87210 Le Dorat, France | 1.0 |
| 6 | 5 Adne Edle Street, London | Geocode.xyz | 5 Threadneedle Street, London EC3V 3NG | 1.0 |
| 7 | 20 Bökenbusch 27777 | Geocode.xyz | Bökenbusch 20, 27777 Ganderkesee, Germany | 0.7 |
| 8 | 4 日本橋三丁目, 中央区 JP 103-0027 | Geocode.xyz | Nihonbashi 3-chōme, Chūō-ku, Tokyo | 0.6 |
| 9 | 415 C'WEALTH AVE WEST Singapore | Geocode.xyz | 415 Commonwealth Avenue West, Singapore 120415 | 0.8 |
| 10 | 55.68028,12.59005 (reverse) | Geocode.xyz | Nyhavn 29, 1051 Copenhagen, Denmark | 1.0 |
| 11 | A paragraph about Vienna (geoparse) | Geocode.xyz | 1 Albertinaplatz, Vienna | 1.0 |
| 12 | 1435 prince (autocomplete) | Geocoder.ca | Six matching Canadian addresses | n/a |
The Empire State Building came back exactly: 40.748369, -73.984853, ZIP+4, time zone and area codes. The Pasadena address had two typos, no direction and no ZIP:
| Input | Returned |
|---|---|
| FAIR OKS AVENUE | N Fair Oaks Ave |
| PASADNA | Pasadena |
| (no ZIP) | 91103-3069 |
The added N is the important part: Pasadena has both North and South Fair Oaks, and 751 is on the north side. Because the skill tells the agent to ask for standard=1, the cleaned components come back as separate fields, ready to store.
For “Metcalfe & Wellington, Ottawa” the agent added ON on its own (there is more than one Ottawa) and got the corner in front of Parliament Hill, 45.423477, -75.697944. Intersections come back as street1/street2 rather than stnumber/staddress, and the street names carry trailing spaces, so trim them before storing. The postal code returned, K1A 0A3, is the nearest building's (the Parliament buildings), not the intersection's.
“1 Random St, Toronto” sounded made up and came back at confidence 1. The agent was suspicious, reran it with strictmode=1, got the same answer (there really is a Random St, in Etobicoke) and still suggested checking it on a map: confidence measures how well the input matched the data, not whether the data is right. The response also carried Dissemination_Area.dauid, the Statistics Canada census area, which you can use for a censusdatafromdauid= lookup.
region=FR and got 13 Avenue de la Josnière, 87210 Le Dorat (46.21766, 1.07657). In Geocode.xyz responses prov is the country code, not a province; the skill says so.region=UK (not GB) and, despite confidence 1, flagged the correction for a human to confirm, since it's a big jump from what was typed.{} instead of an empty string; normalize those before writing CSV or a database.55.68028,12.59005 with moreinfo=1 came back as Nyhavn 29, 1051 Copenhagen at distance 0.000 km, plus elevation, time zone, the nearest intersection 45 m away and the municipality from OpenStreetMap. The geocode/geonumber fields identify the 10 m × 10 m cell the point is in, which makes a compact location ID.
Given a paragraph from a Vienna travel guide, the agent used scantext= with region=AT and found Albertinaplatz in the 1st district, with MentionIndices pointing back to the right spot in the text. Vague mentions (“train stations”, the unnamed airport) were correctly left out.
This test also caught a bug in the skill's own wrapper scripts: geoparsing failed on every stock Mac, because macOS still ships bash 3.2, which treats an empty array as unset under set -u. The agent traced it, fixed both scripts, tested under bash 3.2 and opened a pull request, merged the same day.
“1435 prince” returned six full addresses with postal codes across six provinces, including Rue Prince-Philip in Brossard. Then I asked for a working demo page. The agent loaded the autocomplete skill, downloaded our JavaScript widget, read its source and built a form that suggests addresses as you type, then geocodes the chosen one into separate fields:


Reading the widget's source also turned up several bugs: the search text was rebuilt from key codes (so pasting didn't work) and wasn't URL-encoded, the widget replaced your <input> with one that had a random ID, Enter didn't pick a suggestion, and the styling assumed Bootstrap. The agent worked around all of them in the demo, and kept the token out of the page files by serving it from the environment.
We have since fixed all of them in v1.0.0 of the widget. The search text now comes straight from the field, so paste, browser autofill and mobile keyboards work, and it is URL-encoded. Your <input> keeps its id, name, classes and listeners. Enter picks the highlighted suggestion and Escape closes the list. The widget ships its own small stylesheet, with a dark mode, so Bootstrap is no longer needed. While we were in there we also fixed a few things the agent hadn't hit: addresses are now HTML-escaped before being shown, a single result is no longer split into one suggestion per character, and a slow response can no longer overwrite a newer one. It is a drop-in replacement; existing new autocomplete({...}) calls keep working.
Try it yourself in our autocomplete demo, which is the form the agent built: suggestions as you type, then the chosen address geocoded into separate fields.
region=FR, region=UK, ON for Ottawa).geoit=XML&json=1); every value comes back as a string.prov is the country code in Geocode.xyz, empty fields can be {}, intersections use street1/street2.more field: it holds unit numbers and PO boxes the geocoder didn't use.In one session the agent geocoded addresses in seven countries, in Latin script and kanji, reverse geocoded Copenhagen, pulled a street out of a paragraph about Vienna, built a working autocomplete form, found and fixed a bug in the skill's own tooling, and flagged four bugs in our widget that are now fixed.
Get it at github.com/geocode-xyz/geolytica-skills, and get a token at geocoder.ca (free non-commercial tier; plans at geocoder.ca/pricing) or a key at geocode.xyz. Pull requests and feedback welcome.
Enjoy!