Skip to content

Data model & schema

The Eventhouse holds landing tables (Raw_*, written by the collector) and one curated table (FdaInteractions, the troubleshooting/tuning triple). Schema is defined in fabric/kql/01_tables.kql; policies in 02_policies.kql.

flowchart LR
    subgraph raw [Landing tables · short retention]
        G[Raw_GraphInteractions]
        A[Raw_AuditInteractions]
        D[Raw_ExecutedDax]
        S[Raw_SdkRuns]
    end
    G --> C[(FdaInteractions<br/>curated triple)]
    A --> C
    D --> C
    W[Watermarks] -. incremental state .- C
    S -. side-by-side compare .- C

All tables are created with .create-merge (idempotent — safe to re-run; adds missing columns without dropping data).


FdaInteractions (curated)

One row per interaction — the troubleshooting/tuning triple. Written by the collector via .set-or-append FdaInteractions <| .... This is the table the review app and dashboard read.

Column Type Description
InteractionId string Stable key — Graph id, else audit RecordId, else correlation hash (dax-… for orphans)
Timestamp datetime Interaction time (response time for paired rows, DAX time for orphans)
User string UPN of the end user
AppHost string M365 for paired interactions; empty for monitoring-only orphans
ThreadId string Conversation / session id
CapacityId string Fabric capacity (reserved; populated from scope where available)
WorkspaceId / WorkspaceName string Workspace hosting the semantic model
AgentId / AgentName string FDA identity, when resolvable from audit
SemanticModelId / SemanticModelName string The queried model (ItemId / ItemName)
Question string Original user prompt
RephrasedQuestion string From ApplicationContext, when present
GeneratedDax string Best-available generated DAX (DSPM/SDK/extracted); may equal ExecutedDax
ExecutedDax string Final/primary executed DAX from monitoring
DaxQueries dynamic Ordered array {dax, durationMs, cpuMs, status, ts} for every execution in the turn
Answer string Response text
DurationMs long Summed query duration across the turn
CpuTimeMs long Summed CPU time across the turn
Status string Ok | Error | Unknown
ErrorMessage string Error detail, when present
MatchConfidence string Exact | Windowed | Unmatched — see correlation
Sources dynamic Which surfaces fed the row, e.g. ["graph","monitoring"]
CorrelationKey string Deterministic hash(user, minute-bucket, model)
IngestedAt datetime When the collector wrote the row

Raw_GraphInteractions (source A)

MS Graph aiInteractionHistory — prompt/response text, one row per message.

Column Type Description
InteractionId string aiInteraction id
ConversationId string sessionId / thread
CreatedDateTime datetime Message time
User string UPN the export was pulled for
UserId string Object id
AppClass string e.g. IPM.SkypeTeams.Message.Copilot.BizChat
InteractionType string userPrompt | aiResponse
Body string Prompt or response text (plain)
BodyType string text | html
Contexts dynamic Grounding resources referenced
Mentions dynamic @-mentions
Raw dynamic Full aiInteraction object
IngestedAt datetime Ingest time

Raw_AuditInteractions (source B)

Office 365 Management Activity API — CopilotInteraction metadata / index (RecordType 261).

Column Type Description
RecordId string Audit record id
CreationTime datetime Record time
Operation string CopilotInteraction
RecordType int 261
Workload string Copilot
User / UserId string End user
AppHost string Bing / Teams / Office / M365App / …
AgentId / AgentName string CopilotStudio.* or Fabric data agent id, when present
ThreadId string Conversation id
MessageIds dynamic Message id list
AISystemPlugin dynamic Plugin/agent descriptors
AccessedResources dynamic Resources the turn touched
ClientRegion string Client region
AuditData dynamic Full raw audit record
IngestedAt datetime Ingest time

Raw_ExecutedDax (source C)

Workspace monitoring SemanticModelLogs — executed DAX + performance.

Column Type Description
XmlaRequestId string OperationId / request id
Timestamp datetime Execution time
OperationName string QueryEnd / ExecuteQueryEnd / CommandEnd
OperationDetail string OperationDetailName
ExecutingUser string Identity FDA impersonated (the end user)
ApplicationName string Helps confirm FDA / Assistant origin
ApplicationContext dynamic Request context
WorkspaceId / WorkspaceName string Workspace
SemanticModelId / SemanticModelName string ItemId / ItemName
Dax string EventText — the DAX query
DurationMs long Query duration
CpuTimeMs long CPU time
Status string Execution status
ExecutionMetrics dynamic Engine metrics
IngestedAt datetime Ingest time

Raw_SdkRuns (source D, optional)

FDA SDK replay output — richest reasoning/steps for sampled questions. A reconstruction on the FDA side, not the live M365 turn. See SDK replay.

Column Type Description
RunId string Replay run id
Question string Replayed question
Answer string SDK answer
GeneratedQueries dynamic Generated DAX/SQL/KQL strings pulled from steps
Steps dynamic Full run-steps (tool calls, inputs, outputs, errors)
Status string Ok | Error
Error string Error detail
DataAgentName string Published agent name
ReplayedAt datetime Replay time

Watermarks (incremental state)

One row per source watermark — drives incremental, idempotent collection.

Column Type Description
Source string graph | audit | monitoring | curated
LastTimestamp datetime High-water mark for the source
LastRunAt datetime When the collector last advanced it
Detail string Free-text run note (e.g. row count)

Policies

Defined in 02_policies.kql. Two policy families:

Retention (PII-aware)

Raw payloads can contain sensitive prompt/response text, so they are kept shorter than the curated triple:

Table Soft-delete retention
Raw_GraphInteractions, Raw_AuditInteractions, Raw_ExecutedDax 90 days
Raw_SdkRuns 365 days
FdaInteractions 730 days

Ingestion batching (low latency)

Raw_GraphInteractions, Raw_AuditInteractions, Raw_ExecutedDax, and FdaInteractions use a 30-second / 500-item batching policy for near-real-time review.

Governance

Prompts and responses can contain sensitive data. The Eventhouse should inherit the workspace sensitivity label; restrict the KQL database and the review app to authorized reviewers. The split between short-lived Raw_* and the curated, optionally-redactable FdaInteractions is deliberate.