The get_location tool returns geographic data. All actions return the same unified shape so you never have to case-split on the source:

{
  source: 'gps' | 'ip' | 'coords' | 'latest' | 'history',
  city: string | null,
  region: string | null,
  country: string | null,
  timezone: string | null,
  lat: number | null,
  lon: number | null,
  ip: string | null,       // echoed back when you pass an IP, or the caller's IP on 'me'/'gps'
  accuracy: number | null, // meters; populated only for GPS
}

Fields the action can't populate are null. Pick what you need; nothing is hidden behind the action name.

Actions

Action When to use
me (default) "Where am I?" - tries GPS if the user's browser advertised the capability, otherwise falls back to IP geo. The right default 95% of the time.
ip Look up any IP. If ip param is omitted, uses the caller's IP.
coords Reverse-geocode an arbitrary lat+lng into city/region/country.
gps Force a live GPS round-trip to the user's browser. Fails clearly if no socket session or permission denied.
latest Most recent stored location for this user (from the user_locations table).
history Past stored locations - paginate with count (default 10, max 1000) or hours.

Examples

GPS specifics

GPS only works when:

  1. The user is in a live browser session (socket-connected - not REST-only, not a workflow).
  2. Their browser has the Geolocation API (navigator.geolocation) - essentially all modern browsers.
  3. They haven't previously denied permission (the client advertises gpsPermission on connect via the Permissions API).

If any of those fails for action: 'me', the tool silently falls back to IP geo so you still get an answer. For action: 'gps', you get a clear error instead of a fallback - use it when GPS specifically is required (navigation, high-accuracy fitness tracking, etc.).

Always pass a reason when calling GPS-capable actions - some clients show it to the user in the permission prompt.

IP geo specifics

IP lookup uses the platform's local Geo DB (no network latency, no rate limits). Private IPs (10.*, 192.168.*, 172.16-31.*, 127.0.0.1) return an error - there's no useful answer for those.

User-side usage (outside the agent)

End users query their own location directly without going through the agent:


Calling location from a deployed app

Everything above is the agent-side get_location tool. A deployed app resolves a user's location through the app-scoped HTTP service instead - see app-location for the /services/location/* endpoints, the frontend and serverless-function patterns, and the X-Forwarded-For gotcha.