Chat Sessions
Overview
The SDAC chat experience uses server-side conversation persistence. Session management is built into the main chat endpoint rather than exposed as a separate external route.
Authentication
Widget clients call the same-origin chat proxy. Direct APIM callers must use an environment-published runtime route and send:
Authorization: Bearer {access_token}Ocp-Apim-Subscription-Key: {subscription_key}
See Authentication for the full header contract and Response Formats for the SSE response model.
Endpoint
| Attribute | Value |
|---|---|
| Endpoint | POST /api/ingestion/sdac/chat |
| Method | POST |
| Content-Type | application/json |
| Response | SSE stream |
Request
{
"reportId": "8201EDC2-2EDE-4CA1-AF44-D0F5AA185CDB",
"message": "What is the fringe variance for this report?",
"userId": "auditor@state.gov",
"sessionId": "browser-session-abc123",
"conversationId": "browser-session-abc123",
"agentId": "sdac-coordinator-release"
}
| Field | Type | Required | Description |
|---|---|---|---|
message | string | Yes | User message |
userId | string | Yes | User identifier from auth |
sessionId | string | Yes | Browser or client session ID |
reportId | UUID string | No | Report being discussed |
conversationId | string | No | Existing conversation to continue |
districtId | string | No | District identifier when no report is loaded |
quarter | string | No | Reporting quarter when resolving report context without reportId |
year | string | No | Reporting year when resolving report context without reportId |
agentId | string | No | Agent profile for the request |
When reportId is omitted, provide districtId, quarter, and year together. The chat service does not fetch default or latest district cost data from partial context.
Session Metadata Response
The first SSE event in every response is metadata:
{
"conversationId": "browser-session-abc123",
"turnNumber": 1,
"isNewConversation": true,
"conversationExpired": false
}
| Field | Type | Description |
|---|---|---|
conversationId | string | Conversation identifier to reuse on future requests |
turnNumber | number | Turn number for the current user message |
isNewConversation | boolean | true when the server started a new conversation |
conversationExpired | boolean | true when a previous conversation had expired and was replaced |
Conversation Lifecycle
First Request in a Browser Session
- Send a request without
conversationId. - The server starts a new conversation keyed to the supplied
sessionId. - Store the returned
conversationIdfrom themetadataevent.
Continuing a Conversation
- Send the next request with the stored
conversationId. - The server reloads recent conversation history.
- The assistant responds with awareness of prior turns.
Reusing a Session Without conversationId
If you omit conversationId but reuse a sessionId that already has persisted history, the server may resume that session-scoped conversation automatically.
If you need a guaranteed clean conversation, rotate sessionId before sending the next request.
Expired Conversation
If a referenced conversation has expired:
- The server starts a new conversation.
conversationExpiredis set totruein themetadataevent.- Prior context is not carried forward.
Retention
- Conversations expire after 90 days.
- The server keeps only a bounded recent history window in prompt context.
Side Effects
- A request without
conversationIdcreates or resumes a server-side conversation keyed tosessionId. - A request with
conversationIdreloads recent conversation history before generating the next answer. - Successful assistant turns emit a persisted
conversationSkthat can later be rated through the feedback API.
Feedback Metadata
The metadata event is for conversation state only. The values required for feedback submission arrive later in the done event:
{
"success": true,
"conversationId": "browser-session-abc123",
"conversationSk": 12345,
"turnNumber": 2
}
| Field | Use |
|---|---|
conversationSk | Primary key of the persisted assistant turn |
turnNumber | Assistant turn number to send to the feedback API |
SSE Event Types
| Event | Description |
|---|---|
metadata | Conversation state |
tool-start | Tool started |
tool-result | Tool completed |
warning | Runtime warning such as quarter fallback |
delta | Streamed assistant text |
usage | Token usage |
done | Stream completion with feedback metadata |
error | Stream failure |
Error Responses
| Status | Description |
|---|---|
| 400 | Invalid request body |
| 401 | Missing or expired bearer token |
| 403 | Invalid subscription key or insufficient scope |
| 500 | Conversation processing failed |
Examples
Start a New Conversation
curl -N -X POST "$WIDGET_BASE_URL/api/ingestion/sdac/chat" \
-H "Content-Type: application/json" \
-d '{
"reportId": "8201EDC2-2EDE-4CA1-AF44-D0F5AA185CDB",
"message": "Summarize the top issues in this report.",
"userId": "auditor@state.gov",
"sessionId": "browser-session-123",
"agentId": "sdac-coordinator-release"
}'
Continue the Conversation
curl -N -X POST "$WIDGET_BASE_URL/api/ingestion/sdac/chat" \
-H "Content-Type: application/json" \
-d '{
"reportId": "8201EDC2-2EDE-4CA1-AF44-D0F5AA185CDB",
"message": "Focus only on the highest-dollar items.",
"userId": "auditor@state.gov",
"sessionId": "browser-session-123",
"conversationId": "browser-session-123",
"agentId": "sdac-coordinator-release"
}'
Operational Notes
- Persist
conversationIdper active chat thread, not just per page load. - Persist
conversationSkand assistantturnNumberper assistant response if your UI collects feedback. - A single
sessionIdnormally corresponds to one resumable chat thread unless the client intentionally rotates session state.