Use the Terrain Agent
Send a map-aware prompt and consume a server-sent event stream containing agent text, tool activity, confirmation requests, and map refresh notifications.
/api/terrain-analysis/chat/streamIdentify the map and scenario context.
The request requires a map_id, scenario_id, and snapshot_order. Terrain tools can become usable incrementally, but each tool still needs its own source and phase dependencies. For the complete source bundle, wait for analysis_ready: true. Terrain summaries additionally needterrain_summary; road-network tools need terrain_road_graph.
viewport_bbox_wgs84, map_zoom, and cursor coordinates help the agent reason about what the user is viewing. Bounding boxes use [west, south, east, north].POST the prompt and read the response as SSE.
This is not a normal JSON response and cannot use the browser's native EventSource, because the stream is opened with a POST body. Disable client buffering and process events as they arrive.
export BLUE_SCENARIO_ID="YOUR_SCENARIO_ID"
curl --no-buffer --request POST "$BLUE_API_URL/api/terrain-analysis/chat/stream" \
--header "Authorization: Bearer $BLUE_API_KEY" \
--header "Accept: text/event-stream" \
--header "Content-Type: application/json" \
--data '{
"map_id": "'"$BLUE_MAP_ID"'",
"scenario_id": "'"$BLUE_SCENARIO_ID"'",
"snapshot_order": 0,
"prompt": "Summarize mobility constraints in the area of operations.",
"flow_id": "client-flow-123"
}'ready or message. For each message, parse thedata value as JSON and switch on its inner type.event: ready
data:
event: message
data: {"type":"tool_called","tool":"get_viewport_summary","args":{},"call_id":"call_123"}
event: message
data: {"type":"tool_output","tool":"get_viewport_summary","output":{"cells":[]},"call_id":"call_123","flow_id":"client-flow-123"}
event: message
data: {"type":"token_stream","content":"The area","stream_type":"text_delta"}
event: message
data: {"type":"final_message","content":"The area contains..."}Handle the events your client needs.
| Inner type | Meaning | Client behavior |
|---|---|---|
token_stream | A final-answer text delta. | Append content to the visible answer. |
final_message | The complete final answer. | Use content as the authoritative completed text. |
tool_called | The agent started a tool. | Optionally show activity keyed by call_id. |
tool_output | A tool returned data. | Match it to tool_called using call_id. |
confirmation_request | A proposed action needs a yes/no decision. | Pause that flow and collect a user decision. |
asset_refresh | A tool changed map-layer data. | Reload the listed layer_types for the supplied map. |
output_started / reasoning_created | Progress signals. | Use for UI state; no data mutation is required. |
Continue gated actions with a second stream request.
When the stream emits confirmation_request, preserve its request_id and copy the complete payload.request_payload object without rebuilding it. After the user chooses, POST to the same streaming endpoint withconfirmation_response. Reuse your flow_id to correlate the continuation.
{
"map_id": "MAP_UUID",
"scenario_id": "SCENARIO_UUID",
"snapshot_order": 0,
"prompt": "",
"flow_id": "client-flow-123",
"confirmation_response": {
"request_id": "REQUEST_ID_FROM_EVENT",
"decision": "yes",
"request_payload": {
"type": "tool_confirmation_gate",
"tool_name": "TOOL_FROM_EVENT",
"gate_id": "GATE_ID_FROM_EVENT",
"tool_args": {}
}
}
}- Use
decision: "yes"to approve ordecision: "no"to reject. - The prompt may be empty when
confirmation_responseis present. - Disconnecting the HTTP stream cancels that streaming run, so treat network interruption as incomplete.