Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/yohangr3/agentelanggrafh/llms.txt

Use this file to discover all available pages before exploring further.

The WebSocket endpoint at /ws/chat gives clients a live window into the LangGraph pipeline. Instead of waiting for the full pipeline to finish, the server emits a node_start / node_end event for each processing stage — understanding, planning, execution, presentation — and then delivers a final response event with the complete result payload. This makes it possible to render meaningful progress indicators while the agent works.
Use wss:// (TLS) in all production environments. Plain ws:// is only appropriate for local development.

Connection URL

EnvironmentURL
Local developmentws://localhost:8000/ws/chat
Productionwss://api.example.com/ws/chat
No query parameters or subprotocols are required for the initial HTTP upgrade.

Authentication Handshake

WebSocket connections cannot carry an Authorization HTTP header after the initial upgrade in most browser environments, so authentication is performed as the first message on the socket. The server enforces a 10-second timeout (_AUTH_TIMEOUT_SECONDS = 10). If the auth message is not received within that window the server sends an error event with error_code: "AUTH_TIMEOUT" and closes the connection.
1

Connect

Open the WebSocket connection to wss://api.example.com/ws/chat.
2

Send the auth message

Immediately send a JSON message with type: "auth" and your Cognito JWT:
{
  "type": "auth",
  "token": "<cognito_id_token>"
}
3

Receive auth_success or error

On success the server responds with:
{
  "type": "auth_success",
  "user_id": "a1b2c3d4-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
On failure the server sends an error event (see Error Events) and closes the connection.
4

Start chatting

Send chat or feedback messages. The server remains connected and processes multiple turns in the same session.
If the first message is not {"type": "auth", ...} the server immediately sends AUTH_REQUIRED and closes the connection. Always send the auth message before any chat message.

Client → Server Messages

chat

Send a natural language question to the agent pipeline.
type
string
required
Must be "chat".
message
string
required
The natural language question (same constraints as the REST API: 1–2 000 characters).
session_id
string
Session identifier for multi-turn history. Omit or pass an empty string to generate a new UUID session for this turn. The active session_id is echoed back in every response event.
confirmed
boolean | null
HITL confirmation flag. Set to true when re-sending a message after receiving a confirmation_required event. Defaults to false.
file_id
string
Optional ID of a previously uploaded file (from POST /api/upload). When provided the pipeline routes the turn through the analyze_file node.
{
  "type": "chat",
  "message": "¿Cuáles son los costos de producción por centro de costos?",
  "session_id": "session-abc123",
  "confirmed": null
}

feedback

Submit thumbs-up / thumbs-down feedback on a completed query result. Feedback is persisted to DynamoDB for query quality tracking.
type
string
required
Must be "feedback".
query_id
string
required
The query_log_id value from the response event you are rating.
timestamp
string
required
The query_timestamp value from the same response event. Used as the DynamoDB sort key.
feedback
string
required
"up" for a positive rating, "down" for a negative rating.
{
  "type": "feedback",
  "query_id": "qlog-7f3a....",
  "timestamp": "2024-03-15T10:30:00.000000+00:00",
  "feedback": "up"
}
The server acknowledges with:
{
  "type": "feedback_received",
  "query_id": "qlog-7f3a...."
}

Server → Client Events

The server sends a stream of typed JSON objects during each pipeline run. Events arrive in this sequence:
node_start (understand) → node_end (understand) →
node_start (plan) → node_end (plan) →
... → node_start (present) → node_end (present) →
response  ─ or ─  confirmation_required  ─ or ─  error

node_start

Emitted when the pipeline enters a processing node. Use this to drive progress indicators in your UI.
type
string
Always "node_start".
node
string
Internal node identifier. See Node Labels below.
label
string
Human-readable Spanish label suitable for display in a loading state. Present only when the outer conversation graph path is active. In the legacy single-graph path this field is omitted — always guard with an existence check before reading.
timestamp
string
ISO 8601 UTC timestamp of when the node started.
{
  "type": "node_start",
  "node": "understand",
  "label": "Analizando tu consulta",
  "timestamp": "2024-03-15T10:30:00.123456+00:00"
}

node_end

Emitted when a node completes successfully.
type
string
Always "node_end".
node
string
Internal node identifier matching the preceding node_start.
timestamp
string
ISO 8601 UTC timestamp of when the node finished.
{
  "type": "node_end",
  "node": "understand",
  "timestamp": "2024-03-15T10:30:00.891234+00:00"
}

response

The final event of a successful pipeline run. Contains the complete structured response.
type
string
Always "response".
data
object
{
  "type": "response",
  "data": {
    "response": "Los costos de producción por centro de costos en Q1 2024 fueron...",
    "sql": "SELECT cebe, SUM(importe) AS total FROM t_costos WHERE periodo = '2024-Q1' GROUP BY cebe",
    "row_count": 12,
    "session_id": "session-abc123",
    "display_mode": "chart_primary",
    "chart_type": "bar",
    "kpis": { "total": 4820000, "average": 401667 },
    "suggestions": ["¿Cómo se compara con Q2?", "¿Qué centro de costos tuvo más variación?"],
    "query_log_id": "qlog-7f3a1234",
    "query_timestamp": "2024-03-15T10:30:02.000000+00:00"
  }
}

confirmation_required

Emitted when the HITL gate is triggered. No SQL has been executed. Prompt the user to confirm, then resend the original chat message with confirmed: true.
type
string
Always "confirmation_required".
message
string
Human-readable explanation of why confirmation is needed.
session_id
string
The active session ID. Include this when resending the confirmed request.
{
  "type": "confirmation_required",
  "message": "Esta consulta escaneará más de 2 millones de registros. ¿Deseas continuar?",
  "session_id": "session-abc123"
}

Error Events

type
string
Always "error".
error_code
string
Machine-readable error code. See table below.
message
string
Human-readable error description.
error_codeCauseConnection closed?
AUTH_TIMEOUTNo auth message received within 10 secondsYes
AUTH_REQUIREDFirst message was not {"type": "auth", ...}Yes
AUTH_INVALID_TOKENJWT is invalid, expired, or signature verification failedYes
TENANT_MISMATCHUser’s tenant does not match the expected instance tenantYes
GRAPH_ERRORUnhandled error in the LangGraph pipelineNo — connection stays open
INTERNAL_ERRORUnexpected server error in the WebSocket handlerNo

Pipeline Node Labels

These are all nodes that emit node_start / node_end events, sourced directly from _NODE_LABELS in src/api/websocket.py:
nodelabel (displayed to user)Description
understandAnalizando tu consultaIntent classification and slot extraction
clarifyVerificando informaciónAsking clarifying questions for missing parameters
planPreparando consulta SQLSchema linking and SQL generation
executeEjecutando consultaRunning the validated SQL query against the database
presentPreparando respuestaBuilding charts, KPIs, and narrative response
analyze_fileAnalizando archivoProcessing an uploaded Excel/CSV file
viz_changeCambiando visualizaciónUpdating chart type based on user request
discuss_dataAnalizando los datosFollow-up analysis on previously retrieved data
general_respondGenerando respuestaHandling general conversational turns

JSON Serialization Notes

The server applies recursive sanitisation before sending any response event. This is important when consuming data in typed languages:
Python typeSerialised as
Decimal (whole)integerDecimal("42")42
Decimal (fractional)floatDecimal("3.14")3.14
datetimeISO 8601 string — "2024-03-15T10:30:00+00:00"
dateISO 8601 date string — "2024-03-15"
timeISO 8601 time string — "10:30:00"
This sanitisation exists because SAP/ERP database columns frequently return Decimal and datetime types that are not natively JSON-serialisable.

Code Examples

// Full auth + multi-turn chat flow
const WS_URL = "wss://api.example.com/ws/chat";
const TOKEN  = "eyJraWQ..."; // JWT from AWS Cognito / Amplify

function createChatSocket() {
  const ws = new WebSocket(WS_URL);

  ws.addEventListener("open", () => {
    console.log("Connected — sending auth");
    ws.send(JSON.stringify({ type: "auth", token: TOKEN }));
  });

  ws.addEventListener("message", (event) => {
    const msg = JSON.parse(event.data);

    switch (msg.type) {
      case "auth_success":
        console.log("Authenticated as", msg.user_id);
        // Now safe to send chat messages
        sendChat(ws, "¿Cuánto vendimos por región en Q1?", "session-001");
        break;

      case "node_start":
        // Update your loading indicator
        console.log(`⏳ ${msg.label}`);
        updateProgressUI(msg.node, msg.label);
        break;

      case "node_end":
        console.log(`✅ Node done: ${msg.node}`);
        break;

      case "response":
        console.log("Final response:", msg.data.response);
        renderResponse(msg.data);
        break;

      case "confirmation_required":
        console.log("HITL:", msg.message);
        if (confirm(msg.message)) {
          // Resend the original message with confirmed = true
          sendChat(ws, currentMessage, msg.session_id, true);
        }
        break;

      case "feedback_received":
        console.log("Feedback recorded for", msg.query_id);
        break;

      case "error":
        console.error(`[${msg.error_code}] ${msg.message}`);
        if (["AUTH_TIMEOUT", "AUTH_REQUIRED", "AUTH_INVALID_TOKEN", "TENANT_MISMATCH"].includes(msg.error_code)) {
          ws.close();
        }
        break;
    }
  });

  ws.addEventListener("close", (event) => {
    console.log("Disconnected", event.code, event.reason);
  });

  return ws;
}

function sendChat(ws, message, sessionId, confirmed = false) {
  ws.send(JSON.stringify({
    type: "chat",
    message,
    session_id: sessionId,
    confirmed,
  }));
}

function sendFeedback(ws, queryLogId, queryTimestamp, rating) {
  ws.send(JSON.stringify({
    type: "feedback",
    query_id: queryLogId,
    timestamp: queryTimestamp,
    feedback: rating, // "up" or "down"
  }));
}

function updateProgressUI(node, label) {
  const el = document.getElementById("progress-label");
  if (el) el.textContent = label;
}

function renderResponse(data) {
  // data.display_mode drives what to render
  // data.response  → narrative text
  // data.chart_config → pass to echarts.setOption()
  // data.query_results + data.column_names → render table
  // data.kpis → render KPI cards
}

// Start the connection
const socket = createChatSocket();

Build docs developers (and LLMs) love