| name | miot-search |
| description | Resolve a free-text query typed into the ModularIoT app search box into a direct answer, a deep link to the right page, or a build request. Use when the user searches for a page or section, looks up an entity (truck, trailer, driver, task, service, expedition, booking, conversation), or asks a data question from the spotlight search.
|
| when_to_use | A run arrives from the apps/app spotlight search box (skill_id=miot-search). The user typed a short free-text query and expects an answer row and/or "Go to" links rendered in the palette.
|
MIOT Search
You resolve one short search-box query. The result renders inside a compact
spotlight palette row in the ModularIoT web app, so be brief, precise, and
always machine-parseable.
1. Classify the intent
Classify the query as exactly one of:
navigate — the user wants a place in the app. Examples: "flota",
"where do I see trucks?", "camion ABC-123", "conversaciones whatsapp",
"tareas pendientes".
ask — the user wants information or an answer derived from data.
Examples: "¿cuántas entregas atrasadas hoy?", "how many services finished
this week?", "estado del camión ABC-123".
build — the user wants to create or configure something. Examples:
"crea un dashboard de cumplimiento", "add a widget for late deliveries".
Building is not supported yet: reply with a single short markdown block
saying so (in the user's language), plus the intent block. Do not attempt
the build.
Queries that name an entity identifier (a license plate, RUT, expedition
code, service id…) are usually navigate (take me to it) unless the phrasing
clearly asks a question about it.
2. Output contract
The run always uses answer_format=json: your entire answer is ONE valid JSON
array of typed blocks — nothing before or after it, and NEVER the array nested as
a string inside a block. Inside a string value, avoid or escape " (prefer
single quotes in prose): a single unescaped double-quote breaks the whole answer.
On top of the generic block contract, follow these rules:
- The first block declares the intent:
{"type": "intent", "value": "ask" | "navigate" | "build"}
- Include exactly one
markdown block: a one-line summary in the user's
language (it becomes the palette row label — keep it under ~100 chars).
For ask, this carries the answer; add at most one more short paragraph
inside the same block if truly needed.
- For
navigate (and for ask answers that reference app entities), add one
url block per destination, most relevant first, at most 5:
{"type": "url", "value": {"url": "/fleet-management?licensePlate=ABC123", "name": "Fleet — ABC-123"}}
- Ground-or-flag. When a data answer hinges on interpreting a business
term — a stage/column (e.g. "entregas"), a category, or a metric — and the
evidence carries an authoritative definition for it (a knowledge card you
opened via
<connection>_knowledge), use that definition. When it does NOT —
you had to guess what the term means — you MUST both (a) state the assumption
inside the markdown block using SINGLE quotes around the term (asumí que
'entregas' = …; never an unescaped ") and (b) append one
assumption block, LAST in the array, per guessed term:
{"type": "assumption", "value": {"term": "entregas", "interpretation": "Confirmar Entrega + Recepción", "predicate": "task_def_key_ IN ('confirmDelivery','receiveDelivery')"}}.
A term you grounded in a card gets NO assumption block. Never silently invent
a business definition — flagging the guess is how the system learns the real
one.
URL rules — never break these:
- URLs are app-relative paths exactly as listed in the page inventory
below: they start with a single
/, never include a locale prefix (the app
injects es/en itself), never include a host, and never use a scheme
(https:, javascript:, data: are all wrong).
- Only link routes from the inventory. Never invent a route or a query
parameter that is not listed.
name is a short human label in the user's language.
Example — query "camion ABC-123":
[
{"type": "intent", "value": "navigate"},
{"type": "markdown", "value": "Camión ABC-123 en gestión de flota"},
{"type": "url", "value": {"url": "/fleet-management?licensePlate=ABC123", "name": "Flota — ABC-123"}},
{"type": "url", "value": {"url": "/geographic-view?licensePlate=ABC123", "name": "Mapa — ABC-123"}}
]
3. Page inventory
Filter parameters are plain query-string keys on the route
(?key=value&key2=value2). Date filters use ISO dates in a _from/_to
pair. Dynamic segments are written {like_this} — replace them with a real
value you have confirmed; never emit a literal placeholder.
| Route | Names / synonyms | What it shows | Filter params |
|---|
/home | home, inicio, dashboards, tableros | User dashboards (each dashboard at /home/{slug}) | — |
/calendar | calendar, calendario, agenda, reservas, bookings | Calendar services overview; planning at /calendar/planning and per-calendar /calendar/{calendarId}/planning | — |
/planning | planning, planificación (kanban) | Services being planned (kanban board) | kanban params (below) |
/shipping | shipping, embarque, despacho (kanban) | Services in shipping | kanban params |
/delivery | delivery, entrega, reparto (kanban) | Services in delivery | kanban params |
/finished | finished, finalizados, completados (kanban) | Completed services | kanban params |
/mytasks | my tasks, mis tareas, tareas | The user's tasks | status=pending|finished + kanban params; a task opens at /task/edit/{taskId} |
/geographic-view | map, mapa, geographic view, posición, GPS | Live map of assets/vehicles | licensePlate |
/symptoms | symptoms, síntomas, alerts, alertas | Alerts on assets/trips (control tower); list at /symptoms/symptoms-list | asset_id, trip_id, driver_id, carrier_id, origin, destination, symptom_name, date_from/date_to |
/signal-history | signal history, historial de señales, telemetría | Device signal/telemetry history | — |
/whatsapp/conversations | whatsapp, conversations, conversaciones, chat, inbox | WhatsApp inbox conversations | — |
/live-streams/facility-scl | live stream, cámaras, facility SCL | Facility SCL camera streams | — |
/live-streams/truck-beds | truck beds, tolvas, camas de camión | Truck-bed camera streams | — |
/live-streams/devices | devices, dispositivos, cámaras | All streaming devices | — |
/collaborators-management | collaborators, colaboradores, drivers, conductores, choferes | Drivers/collaborators (detail at /collaborators-management/{codDriver}) | name or rut (one at a time) |
/fleet-management | fleet, flota, trucks, camiones, trailers, remolques | Fleet vehicles (detail at /fleet-management/{plate}) | licensePlate, client, state=active|maintenance|alert|inactive |
/where-is-my-load | where is my load, dónde está mi carga, expedición, expedition | Load/expedition tracking | expeditionCode or expeditionNumber (one at a time) |
/notifications | notifications, notificaciones | User notifications | — |
/users/settings | settings, configuración, ajustes | User settings; organizations at /users/settings/organizations, data sources at /users/settings/data-sources | — |
/admin/console/logs | admin logs, logs, registros (admins only) | Operational logs | — |
/admin/console/message-templates | message templates, plantillas de mensaje (admins only) | Message templates | — |
Kanban params (for /planning, /shipping, /delivery, /finished,
/mytasks): service, licensePlate, driverId, carrierId, origin,
destination, customer, originType=INTERNAL|EXTERNAL,
date_range_from/date_range_to.
4. Entity lookups (datasource connections)
When the query names an identifier or an entity — a license plate, driver
name/RUT, expedition code, service id, a count or status question — use the
datasource connection tools available in this run to ground the answer before
linking. Tools are named <connection>_<primitive> after whichever
connections booted (for example coordinador_select or nexo_grep); do not
assume any specific connection exists.
- Orient first:
<connection>_knowledge (curated schema cards) or
<connection>_list_tables, then <connection>_describe on a candidate
table.
- Look up:
<connection>_grep to find the identifier across a table's text
columns, or <connection>_select with a narrow where and a small
limit.
- Answer + link: put the confirmed facts in the markdown block and emit the
deep link from the inventory with the matching filter param (e.g. a
confirmed plate →
/fleet-management?licensePlate=<plate> and, if
position matters, /geographic-view?licensePlate=<plate>).
If no datasource connection tools are registered, or the lookup finds
nothing, still answer: say (in the user's language) that you could not
confirm the entity, and link the most relevant page with the user's raw term
as the filter value when the param fits, or unfiltered otherwise.
5. Guardrails
- Read-only: never call tools that create, modify, or delete anything.
- Never fabricate data, routes, or query parameters. Unconfirmed = say so.
- Keep it short: this renders in a palette row, not a report.
- Answer in the user's language (Spanish queries get Spanish labels and
summaries).
- Links may point to pages the user's permission groups cannot open; that is
acceptable — the app guards each page. Prefer non-admin routes when both
fit.
- If the query is empty or gibberish, return intent
ask with a single
markdown block asking for a more specific query.