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 REST Chat API is the synchronous interface to the ERP Financial Agent pipeline. Each POST /chat request runs the full LangGraph pipeline — schema linking, SQL generation, execution, and analysis — and returns a complete structured response. For streaming progress events while the pipeline runs, use the WebSocket API instead.

Authentication

All /chat requests require an Authorization header containing a Bearer JWT token issued by AWS Cognito. The backend validates the token’s signature against your Cognito User Pool’s JWKS endpoint, checks the issuer, and (when configured) validates the audience against COGNITO_CLIENT_ID.
Authorization: Bearer <cognito_id_token>
Obtain tokens via AWS Amplify on the frontend or directly through the Cognito token endpoint. The backend does not expose a token-generation endpoint.
The authenticated user’s identity is derived from the JWT sub claim. The cognito:groups, custom:tenantId, and custom:data_scope claims drive RBAC and multi-tenant data isolation — ensure your Cognito User Pool attributes are configured accordingly.

Rate Limiting

Rate limiting is enforced per authenticated user (keyed on user_id from the JWT). Unauthenticated requests fall back to IP-based limiting.
WindowLimit
Per minute20 requests
Per hour200 requests
When the limit is exceeded the API returns 429 Too Many Requests. The Retry-After header indicates when the window resets.

POST /chat

Process a natural language question through the full agent pipeline and return a structured response with narrative text, generated SQL, optional visualisation config, KPIs, and download links.

Request

Authorization
string
required
Bearer JWT token from AWS Cognito.Example: Bearer eyJraWQ...
X-Correlation-ID
string
Optional trace ID propagated through logs and LangSmith. A UUID is generated automatically if omitted.
message
string
required
Natural language question in any language supported by your LLM. Must be between 1 and 2 000 characters.Example: "¿Cuánto vendimos por región en el primer trimestre?"
session_id
string | null
Session identifier for multi-turn conversation history. Must match the pattern ^[a-zA-Z0-9_-]{1,128}$.Omit (or pass null) to let the server generate a new UUID session. The assigned session ID is always returned in the response so you can pass it back on the next turn.
confirmed
boolean
Human-in-the-loop confirmation flag. Defaults to false.When the pipeline detects an expensive or ambiguous query it returns confirmation_required: true instead of executing. Resend the identical request body with confirmed: true to proceed.

Response

response
string
required
Narrative answer in plain text or Markdown. Always present.
session_id
string
required
Session ID for this conversation. Echo this value in subsequent requests to maintain context.
confirmation_required
boolean
required
true when the pipeline has triggered the Human-in-the-Loop gate. When this is true, the other data fields are empty — resend with confirmed: true to execute.
sql
string | null
The SQL query that was generated and executed against the ERP database. null for conversational turns that did not require a query.
row_count
integer | null
Number of rows returned by the SQL query. null when no query was executed.
intent
string | null
Classified top-level intent of the user’s message (e.g. ventas, costos, general).
analysis_intent
string | null
Sub-intent that controls which result components are populated. One of:
  • query — data table only
  • chart — chart + table
  • analysis — full experience: KPIs + chart + table + exports
chart_config
object | null
kpis
object | null
executive_summary
string | null
Markdown-formatted executive summary of the analysis. Present when analysis_intent is analysis.
exports
object | null
confirmation_message
string | null
Human-readable explanation of why confirmation is required (e.g. “This query will scan 5 million rows. Do you want to proceed?”). Only present when confirmation_required is true.

Error Responses

StatusCodeDescription
401 UnauthorizedMissing, expired, or invalid JWT token.
422 Unprocessable EntityRequest body failed Pydantic validation (e.g. message too long, invalid session_id format).
429 Too Many RequestsRate limit exceeded. Check the Retry-After header.
500 Internal Server ErrorUnhandled error in the agent pipeline. The detail field contains context.
503 Service UnavailableLangGraph pipeline is still initialising at startup. Retry after a few seconds.

HITL Confirmation Flow

Some queries trigger a Human-in-the-Loop gate before execution — for example, queries that scan large tables or perform destructive-looking aggregations. The flow is:
1

Send your question normally

POST to /chat with confirmed omitted or set to false.
2

Receive a confirmation prompt

The response has confirmation_required: true and a confirmation_message explaining what the agent wants to do. No SQL has been executed yet.
3

Confirm and execute

Resend the same message and session_id with confirmed: true. The pipeline will proceed to SQL execution.
Always preserve the same session_id when confirming a HITL gate. Sending a different session or omitting it creates a new session and the pipeline will not recognise the pending confirmation.

Code Examples

# Basic chat request
curl -X POST https://api.example.com/chat \
  -H "Authorization: Bearer $COGNITO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "¿Cuánto vendimos por región en el primer trimestre?",
    "session_id": "session-abc123"
  }'

# Confirm a HITL gate
curl -X POST https://api.example.com/chat \
  -H "Authorization: Bearer $COGNITO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "¿Cuánto vendimos por región en el primer trimestre?",
    "session_id": "session-abc123",
    "confirmed": true
  }'

POST /api/upload

Upload an Excel (.xlsx, .xls) or CSV file for ad-hoc analysis. The endpoint validates the file, parses it with pandas, and stores the result in Redis keyed by a generated file_id. Pass the returned file_id in a subsequent WebSocket chat message (via the file_id field) to route that turn through the analyze_file pipeline node. Requires the file.upload permission (granted to finance_lead and above by default).

Request

multipart/form-data with the following fields:
file
file
required
The Excel or CSV file to upload. Accepted extensions: .xlsx, .xls, .csv. Maximum size is controlled by the MAX_UPLOAD_SIZE_MB environment variable.
session_id
string
Active session ID to associate the file with. When omitted, a new UUID session is created. The resolved session ID is always returned in the response.

Response — FileUploadResponse

file_id
string
required
UUID identifying this upload in Redis. Pass this value as file_id in the next WebSocket chat message.
session_id
string
required
Session the file was associated with (either the provided value or a newly generated UUID).
filename
string
required
Original filename as received from the client.
columns
array
required
List of column metadata objects parsed from the file.
row_count
integer
required
Number of data rows in the uploaded file (excluding the header row).
preview
array
required
First 5 rows of the file as an array of objects, useful for previewing content in the UI before querying.
file_size_bytes
integer
required
Size of the uploaded file in bytes.

Error Responses

StatusCondition
400 Bad RequestUnsupported file extension or parse failure.
401 UnauthorizedMissing or invalid JWT.
403 ForbiddenCaller lacks the file.upload permission.
413 Request Entity Too LargeFile exceeds the configured MAX_UPLOAD_SIZE_MB limit.
429 Too Many RequestsRate limit exceeded (10 req / minute).

Example

cURL
curl -X POST https://api.example.com/api/upload \
  -H "Authorization: Bearer $COGNITO_TOKEN" \
  -F "file=@ventas_q1.xlsx" \
  -F "session_id=session-abc123"
Response
{
  "file_id": "f7c2e1a0-3b4d-4e5f-8a9b-0c1d2e3f4a5b",
  "session_id": "session-abc123",
  "filename": "ventas_q1.xlsx",
  "columns": [
    { "name": "fecha", "dtype": "object", "sample_values": ["2024-01-01"], "null_count": 0, "stats": {} },
    { "name": "monto", "dtype": "float64", "sample_values": ["15000.00"], "null_count": 2, "stats": { "min": 100.0, "max": 95000.0, "mean": 18450.5 } }
  ],
  "row_count": 1240,
  "preview": [
    { "fecha": "2024-01-01", "monto": 15000.0 },
    { "fecha": "2024-01-02", "monto": 22400.5 }
  ],
  "file_size_bytes": 48320
}

GET /health

Returns service health status. No authentication required. Suitable for load balancer health checks and uptime monitors.

Response

status
string
required
"healthy" when the database is reachable, "degraded" otherwise.
database
string
required
"connected" or "disconnected" based on a live connectivity check against the MySQL RDS instance.
environment
string
required
The current deployment environment (e.g. "production", "staging", "development").
langsmith_enabled
boolean
required
true when LangSmith tracing is active. Reflects both LANGSMITH_API_KEY being set and LANGCHAIN_TRACING_V2=true.
metrics_enabled
boolean
required
true when Prometheus metrics collection is enabled.

Example

curl https://api.example.com/health
{
  "status": "healthy",
  "database": "connected",
  "environment": "production",
  "langsmith_enabled": true,
  "metrics_enabled": true
}

GET /metrics

Returns Prometheus-compatible plain-text metrics for scraping. No authentication required — restrict access at the network/load-balancer level in production.
The /metrics endpoint exposes the Prometheus exposition format (text/plain; charset=utf-8). Add it as a scrape target in your prometheus.yml:
scrape_configs:
  - job_name: erp_agent
    static_configs:
      - targets: ["api:8000"]
    metrics_path: /metrics
Key metrics exposed include HTTP request totals (method × endpoint × status code) and active WebSocket session counts.

Build docs developers (and LLMs) love