Skip to main content

Streaming Responses

SDAC Chat Streaming

POST /sdac/chat

The source-backed streaming endpoint for SDAC report review. Browser widget code normally calls the dashboard/widget proxy at POST /api/ingestion/sdac/chat, which forwards to the runtime while preserving the widget token boundary. APIM may publish the runtime route with an environment-specific prefix.

curl -X POST "$BASE_URL/sdac/chat" \
-H "Content-Type: application/json" \
-d '{
"reportId": "8201EDC2-2EDE-4CA1-AF44-D0F5AA185CDB",
"message": "What is the fringe variance for this report?",
"userId": "auditor@state.gov",
"sessionId": "browser-session-abc123",
"conversationId": null
}'

Request fields:

FieldTypeRequiredDescription
reportIdUUIDYesCost report identifier
messagestringYesUser's question or instruction
userIdstringYesAuditor email or identifier
sessionIdstringYesBrowser session identifier
conversationIdUUIDNoOmit for new conversation; include to continue

SSE Event Stream

The response is a Server-Sent Events stream with these event types:

metadata -- Sent first, contains session context:

{
"conversationId": "conv-uuid-123",
"turnNumber": 1,
"isNewConversation": true,
"conversationExpired": false
}

tool-start -- Agent is calling a validation tool:

{
"toolCallId": "call-uuid",
"toolName": "sdac-validate-fringe",
"displayName": "Validate Fringe Benefits"
}

tool-result -- Tool execution completed:

{
"toolCallId": "call-uuid",
"toolName": "sdac-validate-fringe",
"success": true,
"summary": "3 warnings found in fringe data"
}

delta -- Incremental text from the agent:

{ "content": "Fringe is " }

usage -- Token consumption for cost tracking:

{
"promptTokens": 1200,
"completionTokens": 85
}

done -- Stream complete:

{ "success": true }

error -- Error during processing:

{ "message": "Tool execution failed" }

Client-Side Parsing

const response = await fetch('/api/ingestion/sdac/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
reportId: '8201EDC2-2EDE-4CA1-AF44-D0F5AA185CDB',
message: 'What is the fringe variance?',
userId: 'auditor@state.gov',
sessionId: 'browser-session-abc123'
})
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
const { done, value } = await reader.read();
if (done) break;

const chunk = decoder.decode(value);
// Parse SSE events from chunk
for (const line of chunk.split('\n')) {
if (line.startsWith('data: ')) {
const data = JSON.parse(line.slice(6));
// Handle event data
}
}
}

Agent Streaming (Generic)

POST /ai/{domain}/agents/{slug}/stream

Any agent can be invoked in streaming mode. See Invoke Agents & Tools for input format details.

Example -- TAP Image Caption Agent:

curl -X POST "$BASE_URL/ai/tap/agents/image-caption/stream" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"role": "user",
"content": [
{ "type": "image", "image": "https://example.com/image.jpg" },
{ "type": "text", "text": "{\"context\": {\"postId\": 12345}}" }
]
}
]
}'

The SSE event types are the same as described above (delta, tool-call, tool-result, usage, done, error).