Skip to main content

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

AttributeValue
EndpointPOST /api/ingestion/sdac/chat
MethodPOST
Content-Typeapplication/json
ResponseSSE 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"
}
FieldTypeRequiredDescription
messagestringYesUser message
userIdstringYesUser identifier from auth
sessionIdstringYesBrowser or client session ID
reportIdUUID stringNoReport being discussed
conversationIdstringNoExisting conversation to continue
districtIdstringNoDistrict identifier when no report is loaded
quarterstringNoReporting quarter when resolving report context without reportId
yearstringNoReporting year when resolving report context without reportId
agentIdstringNoAgent 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
}
FieldTypeDescription
conversationIdstringConversation identifier to reuse on future requests
turnNumbernumberTurn number for the current user message
isNewConversationbooleantrue when the server started a new conversation
conversationExpiredbooleantrue when a previous conversation had expired and was replaced

Conversation Lifecycle

First Request in a Browser Session

  1. Send a request without conversationId.
  2. The server starts a new conversation keyed to the supplied sessionId.
  3. Store the returned conversationId from the metadata event.

Continuing a Conversation

  1. Send the next request with the stored conversationId.
  2. The server reloads recent conversation history.
  3. 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:

  1. The server starts a new conversation.
  2. conversationExpired is set to true in the metadata event.
  3. 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 conversationId creates or resumes a server-side conversation keyed to sessionId.
  • A request with conversationId reloads recent conversation history before generating the next answer.
  • Successful assistant turns emit a persisted conversationSk that 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
}
FieldUse
conversationSkPrimary key of the persisted assistant turn
turnNumberAssistant turn number to send to the feedback API

SSE Event Types

EventDescription
metadataConversation state
tool-startTool started
tool-resultTool completed
warningRuntime warning such as quarter fallback
deltaStreamed assistant text
usageToken usage
doneStream completion with feedback metadata
errorStream failure

Error Responses

StatusDescription
400Invalid request body
401Missing or expired bearer token
403Invalid subscription key or insufficient scope
500Conversation 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 conversationId per active chat thread, not just per page load.
  • Persist conversationSk and assistant turnNumber per assistant response if your UI collects feedback.
  • A single sessionId normally corresponds to one resumable chat thread unless the client intentionally rotates session state.

Next Steps