Atlas Agent (NL control)
Atlas Agent
Atlas resolves a free-text command into a structured, executable action your client runs against the map. Under the hood it is a tool-calling AI agent: it understands natural language in any language (first-class English and Arabic, including Jordanian dialect), picks the right action, and — for factual questions — grounds its answer in live Navvo data (real places, ratings, and current traffic) rather than guessing. One endpoint covers search, navigation, pins, layer/style control, day-plan itineraries, fleet optimization, and grounded conversational answers.
The response contract is unchanged and backward-compatible — you still switch on action exactly as before. Replies come back in the same language the user wrote in. Atlas is resilient: if the primary model is briefly unavailable it automatically falls back to a local model and a deterministic parser, so the endpoint keeps working. Provider health is tracked across the whole platform, so a primary that is failing is skipped straight away — an outage costs one fast fallback rather than a timeout on every request — and every request has a fixed overall time limit.
Atlas only states facts that came from Navvo's own data in the same conversation: places, distances, routes, traffic. Where that data does not cover something — opening hours, for example — the reply says so instead of guessing, so treat a reply that declines a detail as a correct answer, not an error.
Scope required: places.
Authentication: Atlas requires an identified caller — either a signed-in Navvo user (Bearer token, as on navvo.io) or your API key (x-api-key). Anonymous requests receive 401.
"model": "navvo-ai". The underlying engine is a Navvo implementation detail and may change without notice — never depend on a specific model name.message contains Arabic script, every reply — including the deterministic-fallback confirmations and the "service busy" static messages — comes back in Arabic. English (or any non-Arabic-script) messages get the English strings.history you send, and replies for the chat AI endpoints are stored server-side for up to 30 days and then deleted. Say so in your app's privacy notice. Don't send secrets in message/context/history.POST /ai/atlas
| Field | Type | Notes |
|---|---|---|
message | string | required — the user's natural-language command, up to 8,000 characters (longer → 400) |
context | string | optional — short conversation/context hint, up to 32,000 characters (longer → 400). The Navvo map sends the live camera, visible street names and nearby businesses here so Atlas answers about what the user sees |
userName | string | optional — display name of your signed-in end user; Atlas addresses them by first name |
history | array | optional — prior turns for multi-turn context, max 12 items of { role, content } where role is "user" or "assistant" and content is a string (max 2000 chars). Oldest first. Omitting it (or []) is identical to the previous single-turn behavior. Over-limit / bad roles / over-long content → 400. |
{
"message": "take me to the second one",
"context": "Camera: 31.95,35.91 z15 …",
"history": [
{ "role": "user", "content": "find pharmacies near Abdoun" },
{ "role": "assistant", "content": "Here's what I found for \"pharmacies near Abdoun\"." }
]
}
Both POST /ai/atlas and POST /ai/assistant accept history with the same rules.
curl -s -X POST "https://navvo.io/api/v1/ai/atlas" \
-H "x-api-key: $NAVVO_API_KEY" -H "content-type: application/json" \
-d '{ "message": "plan a 3 hour trip with cafes and museums" }'
Every response has a reply (a short human sentence, in the user's language), an action, a model (always navvo-ai), and unavailable. The other fields depend on the action:
action | Extra fields | Meaning — what your client should do |
|---|---|---|
search | query | run a place search for query and show results |
directions | query | start routing to query |
navigate | query | start turn-by-turn guidance to query immediately ("start navigation to…", "drive me to…") |
pin | query | drop a pin at query |
locate | query | center/zoom the map on query |
control | target, value | toggle a layer/style/panel — target e.g. traffic/satellite/3d/transit/weather; value is on/off/toggle |
itinerary | timeBudgetMin, interests | build a day plan — call POST /itinerary/auto with these + the user's location |
optimize_fleet | — | optimize the user's delivery stops — call the fleet optimizer |
report_incident | incidentType (accident/hazard/police/camera/closure/jam), query (legacy duplicate) | hands-free crowd incident report — file it at the user's location via POST /incidents ("there's an accident ahead"). Prefer the new incidentType field (present only on this action; defaults to hazard); query still mirrors it for older clients. |
answer | — | open-ended — reply is a conversational answer |
Planning examples
// "plan a 3 hour trip with cafes and museums"
{ "action": "itinerary", "timeBudgetMin": 180, "interests": ["cafe","museum"],
"reply": "Planning a 3-hour itinerary around cafe, museum near you." }
// "what can I do in 90 minutes near here"
{ "action": "itinerary", "timeBudgetMin": 90, "interests": [], "reply": "Planning a 1.5-hour itinerary near you." }
// "optimize my deliveries"
{ "action": "optimize_fleet", "reply": "Optimizing your stops into the fastest route order." }
Duration is parsed from the text (3 hours, 90 minutes, half-day → 240, afternoon → 240); interests are matched against a category vocabulary (cafe, restaurant, museum, park, shopping, historic, art, market, nature, …).
Other examples
{ "action": "directions", "query": "the airport", "reply": "Routing you to the airport." } // "directions to the airport"
{ "action": "search", "query": "cafes", "reply": "Here's what I found for \"cafes\"." } // "find cafes nearby"
{ "action": "control", "target": "traffic", "value": "on", "reply": "Turning on traffic." } // "turn on traffic"
What Atlas answers
Atlas is a map assistant. It answers questions about places and businesses, directions, navigation, traffic, parking, the map and its layers, trips and day plans, Navvo itself, and the place or area the user is in or looking at, including its history and what it is known for. Anything else, such as poems, homework, general trivia, sports results or unrelated code, gets one friendly sentence in the user's language saying what Atlas can help with. Requests to drop these rules are declined the same way.
// "write me a poem about love"
{ "action": "answer", "query": "", "reply": "I can only help with places, routes, traffic and the map. Try asking me to find a place, plan a route or check the traffic near you." }
// "tell me about the history of the area I am in" (context: the user is in Amman)
{ "action": "answer", "reply": "Amman, historically known as Rabbath Ammon, was the capital of the Ammonite kingdom..." }
A decline is an ordinary answer, so show reply as you would any other answer.
Grounded answers
For factual questions Atlas fetches real Navvo data before replying — it never invents places, ratings, coordinates, or traffic:
// "is there a pharmacy near me?" → answered from live place search
{ "action": "answer", "reply": "Yes — the closest is Airport Bridge Pharmacy (4.8), with Airport Pharmacy nearby too." }
// "كيف حالة السير الآن؟" (how is traffic now?) → answered from live traffic, in Arabic
{ "action": "answer", "reply": "لا توجد تقارير مرور حية في منطقتك الآن. أخبرني باسم الشارع وسأتحقق لك." }
// "what will traffic be like tomorrow at 8?" → answered from analysed (expected) traffic, never as live
{ "action": "answer", "reply": "Tomorrow at 08:00 traffic around you is usually moderate, mostly because it is the first workday of the week. It is expected to be lightest between 10:00 and 12:00." }
Questions about usual or expected traffic, another time ("tomorrow at 8", "on Friday evening", "during Ramadan"), what-if weather ("if it rains") or the best time to leave are answered from analysed traffic, in the user's local time. Those replies always present the result as typical or expected traffic, never as a live reading.
places — the records an answer was built from
When Atlas consulted the place index to answer, the response also carries places: the records
it was shown. This is additive and optional — omit it and nothing changes — but it is what lets a
client show its work instead of asking the user to trust a sentence. For an Arabic message, name is the
place's Arabic name when Navvo has one (otherwise the English name), so the reply and the records match.
Traffic questions about a named road or area are looked up near the user's position when you send one.
| Field | Type | Notes |
|---|---|---|
slug | string | the place's Navvo slug — use it to open, route to, or save the record |
name | string | |
category | string | null | |
rating | number | null | |
lat / lng | number | null | plot these; a client with a map should |
// "is there a pharmacy near me?"
{
"action": "answer",
"reply": "Yes — the closest is Airport Bridge Pharmacy (4.8), with Airport Pharmacy nearby too.",
"places": [
{ "slug": "airport-bridge-pharmacy-1a2b3c", "name": "Airport Bridge Pharmacy",
"category": "pharmacy", "rating": 4.8, "lat": 31.7226, "lng": 35.9932 }
]
}
The field is absent, not [], when no lookup happened — so presence is a reliable signal that an
answer has something to plot. It can also appear alongside an action (a search whose reply was
informed by a lookup first).
action: "answer". Because the schema is unchanged, existing integrations need no code changes.Quests (crowd data)
Gamified, crowd-sourced data improvement — surface nearby data-gap micro-tasks, collect answers into the moderation queue, and award contributor points.
Users & Sync
Accounts, profiles, saved places, history, and live location sharing — the personal-data API for building a signed-in consumer app on Navvo.