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:
| Field | Type | Required | Description |
|---|---|---|---|
reportId | UUID | Yes | Cost report identifier |
message | string | Yes | User's question or instruction |
userId | string | Yes | Auditor email or identifier |
sessionId | string | Yes | Browser session identifier |
conversationId | UUID | No | Omit 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).