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
- "Where is the user right now?" →
action: 'me' - "What city is IP 8.8.8.8 in?" →
action: 'ip', ip: '8.8.8.8' - "Reverse-geocode 37.77, -122.41" →
action: 'coords', lat: 37.77, lng: -122.41 - "Force a fresh GPS fix for navigation" →
action: 'gps', reason: 'to show nearby coffee shops' - "When was the user last in a different city?" →
action: 'history', hours: 168
GPS specifics
GPS only works when:
- The user is in a live browser session (socket-connected - not REST-only, not a workflow).
- Their browser has the Geolocation API (
navigator.geolocation) - essentially all modern browsers. - They haven't previously denied permission (the client advertises
gpsPermissionon 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:
- Web CLI:
/location(me),/location 8.8.8.8(IP),/location 37.77 -122.41(reverse geocode),/location latest,/location history [count] - Local CLI:
gipity location [...]- same auto-detect pattern,--jsonfor structured output - REST (user-scoped):
GET /location/me,POST /location/ip,POST /location/coords,GET /location/latest,GET /location/history- all return the unified shape. Auth: user JWT (Authorization: Bearer <token>).
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.