Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Agents/AI ERP Agents/StoreMonitoringAgent/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,12 @@ docs/SMA V2 cost estimate.html
docs/copilot-studio-agent-review.md
docs/cost-estimate-v2.md
docs/auto-mitigation-with-azure-arc.md
docs/pos-business-process-catalog.md
scripts/auto-mitigation-actions.ps1
scripts/invoke-arc-clear-store-commerce-event-log.ps1
scripts/invoke-arc-run-command-pilot.ps1
scripts/invoke-arc-store-commerce-version.ps1
kql-queries/pos-all-user-sessions-process-mining.kql
kql-queries/pos-user-session-process-mining.kql
kql-queries/pos-user-sessions-by-device.kql
scripts/New-RetailHardwareStationCertificate.ps1
7 changes: 4 additions & 3 deletions Agents/AI ERP Agents/StoreMonitoringAgent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ The solution connects POS devices to Azure via **Azure Arc** and **Azure Monitor
- See [Quick start](docs/quick-start-portal.md)

3. **Import the Agent**
- Import the Copilot Studio agent into your Power Platform environment using the solution zip file `StoreMonitoringAgent_1_0_0_25.zip` provided in the root of this repository. See [Step 7 in the Quick Start guide](docs/quick-start-portal.md#step-7-setup-copilot-studio-agent-5-minutes) for detailed instructions.
- Import the Copilot Studio agent into your Power Platform environment using the solution zip file `StoreMonitoringAgent_1_0_0_26.zip` provided in the root of this repository. See [Step 7 in the Quick Start guide](docs/quick-start-portal.md#step-7-setup-copilot-studio-agent-5-minutes) for detailed instructions.
Comment thread
SrinathSundaresan marked this conversation as resolved.

## Documentation

Expand All @@ -101,7 +101,8 @@ The solution connects POS devices to Azure via **Azure Arc** and **Azure Monitor
| [Device Onboarding Guide](docs/device-onboarding.md) | Connect POS devices to Azure Arc and configure AMA |
| [Capturing Database Metrics to Log Analytics](docs/database-metrics-log-analytics.md) | Configure offline SQL database metrics collection |
| [Store Commerce App Update Procedure](docs/store-commerce-update.md) | Procedure for updating Store Commerce on monitored devices |
| [Alert-Triggered Agent](docs/alert-triggered-agent.md) | Alert-triggered investigation pattern using Azure Monitor and Teams |
| [Autonomous / Proactive Monitoring Setup](docs/autonomous-proactive-monitoring.md) | Configure the Recurring Store Monitoring Agent Flow |
| [Model Support](docs/model-support.md) | Supported generative AI models for the Copilot Studio agent |
| [Alert-Triggered Agent](docs/alert-triggered-agent.md) | Alert-triggered investigation pattern using Azure Monitor and Teams |
| [Autonomous / Proactive Monitoring Setup](docs/autonomous-proactive-monitoring.md) | Configure the Recurring Store Monitoring Agent Flow |
| [Known Limitations](docs/known-limitations.md) | Current known limitations and workarounds |
| [Periodic Maintenance Guide](docs/periodic-maintenance.md) | Periodic rotation and expiration checks for secrets and certificates |
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ flowchart TD
H[Function App settings] -.-> D
I[Common Alert Schema] -.-> C
I -.-> E

classDef telemetry fill:#DFF3FF,stroke:#0078D4,color:#0B2942,stroke-width:2px
classDef monitor fill:#FFF4CE,stroke:#C19C00,color:#3B3000,stroke-width:2px
classDef compute fill:#F3E8FF,stroke:#7B2CBF,color:#2D123F,stroke-width:2px
classDef copilot fill:#E8F5E9,stroke:#2E7D32,color:#173A19,stroke-width:2px
classDef notification fill:#E8EAFD,stroke:#4F5BD5,color:#20265C,stroke-width:2px
classDef supporting fill:#F2F2F2,stroke:#616161,color:#242424,stroke-width:1.5px,stroke-dasharray:5 3

class A telemetry
class B,C monitor
class D compute
class E,F copilot
class G notification
class H,I supporting
```

## Request Flow
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
## Copilot Studio Agent

- **Non-deterministic response generation** — the AI may produce inaccurate summaries or miss relevant details for complex or ambiguous questions.
- **Large telemetry result sets may produce a no-information response** — when the selected time range returns a large volume of telemetry data, the agent may return "No information was found that could help answer this." Restrict the time range and run the query again to reduce the number of returned records.
- **Predefined topics only** — queries outside Application Errors, Hardware Station Errors, Retail Server Errors, Database Metrics, and Device Online/Offline require custom topic authoring.
- **Single Log Analytics workspace** — cross-workspace queries are not supported.

Expand Down
16 changes: 16 additions & 0 deletions Agents/AI ERP Agents/StoreMonitoringAgent/docs/model-support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Model Support

The D365 Commerce Store Monitoring Agent supports the following generative AI models in Microsoft Copilot Studio:

| Model | Support status |
| ----------------- | -------------- |
| GPT-5 Chat | Supported |
| Claude Sonnet 4.6 | Supported |

## Model Selection

Select one of the supported models in the Copilot Studio agent settings. Model availability can vary by environment, region, licensing, and Microsoft Copilot Studio release channel.

After changing the model, test the agent's monitoring, diagnostic, and alert-investigation topics before publishing it to production. Validate response accuracy, KQL workflow invocation, formatting, and AI-generated content disclosures.

Models not listed in this document have not been validated for this solution and are not currently supported.
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ Steps:
```
_(Store Commerce Event ID 40102 — used for Retail Server performance diagnostics)_
```xpath
Application!*[System[Provider[@Name='Microsoft Dynamics - Retail Hardware Station'] and EventID=7103]]
```
_(Retail Hardware Station Event ID 7103 — shared Hardware Station errors)_
```xpath
Application!*[System[Provider[@Name='DatabaseMetricsService'] and (EventID=3000)]]
```
_(Database Metrics Service — used by DatabaseMetrics topic)_
Expand Down Expand Up @@ -335,7 +339,7 @@ Default settings in `appsettings.json`:
3. Go to [Copilot Studio](https://copilotstudio.microsoft.com)
4. Click **Solutions** in the left menu
5. Click **Import solution**
6. Browse to the `StoreMonitoringAgent_1_0_0_25.zip` file provided in the root of this repository.
6. Browse to the `StoreMonitoringAgent_1_0_0_26.zip` file provided in the root of this repository.
Comment thread
SrinathSundaresan marked this conversation as resolved.
7. On the **Connections** page, map the **Azure Monitor Logs** connection reference to an existing connection or create one. Sign in with an account that has permission to query the Log Analytics workspace.
8. If prompted for the optional `SMAAlertObjectId` environment variable, keep the imported value or enter a temporary GUID. This value is not a secret and is only used by the optional alert-triggered flows. Replace it with the correct object ID when completing [Step 8](#step-8-optional---enable-autonomous-alert-capabilities).
9. Click **Next** → **Import** and wait for the import to complete.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<DirectoryRefId>INSTALLFOLDER</DirectoryRefId>
<SuppressRootDirectory>true</SuppressRootDirectory>
<PreprocessorVariable>var.PublishDir</PreprocessorVariable>
<Transforms>ExcludeServiceExecutable.xsl</Transforms>
</HarvestDirectory>
</ItemGroup>
</Project>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wix="http://wixtoolset.org/schemas/v4/wxs">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:key name="excluded-components"
match="wix:Component[wix:File[substring(@Source, string-length(@Source) - string-length('EventLogSinkConfigService.exe') + 1) = 'EventLogSinkConfigService.exe']]"
use="@Id" />

<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>

<xsl:template
match="wix:Component[wix:File[substring(@Source, string-length(@Source) - string-length('EventLogSinkConfigService.exe') + 1) = 'EventLogSinkConfigService.exe']]" />
<xsl:template match="wix:ComponentRef[key('excluded-components', @Id)]" />
</xsl:stylesheet>
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@
Value="&quot;icacls&quot; &quot;C:\Program Files\Microsoft Dynamics 365\10.0\Store Commerce\Microsoft\contentFiles\Pos\config.json&quot; /grant &quot;NT SERVICE\EventLogSinkConfigService:M&quot; /Q" />
<CustomAction Id="GrantConfigFilePermission" BinaryRef="Wix4UtilCA_X64" DllEntry="WixQuietExec64" Execute="deferred" Impersonate="no" Return="check" />

<!-- Schedule the permission grant after InstallFiles -->
<!-- Schedule the permission grant after the virtual service account is registered -->
<InstallExecuteSequence>
<Custom Action="GrantConfigFilePermission" After="InstallFiles" Condition="NOT REMOVE" />
<Custom Action="GrantConfigFilePermission" After="InstallServices" Condition="NOT REMOVE" />
</InstallExecuteSequence>

<!-- Use Standard WixUI -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ let WindowEnd = now();
Event
| where TimeGenerated between (WindowStart .. WindowEnd)
| where EventLog == "Application"
| where EventID == 40450
| where EventID == 40450 or (EventID == 7103 and Source =~ "Microsoft Dynamics - Retail Hardware Station")
| extend DeviceName = Computer
| summarize ErrorCount = count(), CriticalCount = countif(EventLevelName == "Critical"), ErrorCountOnly = countif(EventLevelName == "Error"), Sources = make_set(Source), SampleMessage = take_any(RenderedDescription) by TimeBucket = bin(TimeGenerated, 1h), DeviceName
| project Hour = format_datetime(TimeBucket, "yyyy-MM-dd HH:mm"), DeviceName, ErrorCount, CriticalCount, ErrorCountOnly, Sources, SampleMessage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Event
| where TimeGenerated > ago(1d)
| where EventLog == "Application"
| where EventLevelName in ("Error", "Critical")
| where EventID == 40450
| where EventID == 40450 or (EventID == 7103 and Source =~ "Microsoft Dynamics - Retail Hardware Station")
| extend DeviceName = Computer
| summarize
ErrorCount = count(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@ Event
| where TimeGenerated > ago(1d)
| where EventLog == "Application"
| where EventLevelName in ("Error", "Critical")
| where EventID == 40450
| extend DeviceName = Computer, ErrorMessage = RenderedDescription
| project TimeGenerated, DeviceName, EventID, Source, ErrorMessage
| where EventID == 40450 or (EventID == 7103 and Source =~ "Microsoft Dynamics - Retail Hardware Station")
| extend SplitMarker = iff(EventID == 7103, "ExceptionMessage", "The activityId")
| extend SplitStart = indexof(tolower(RenderedDescription), tolower(SplitMarker))
| extend StackStart = iff(EventID == 7103, SplitStart + strlen(SplitMarker), SplitStart)
| extend RawStackTrace = iff(SplitStart >= 0, trim_start(@'[\s:=''\.]+', substring(RenderedDescription, StackStart)), "")
Comment thread
SrinathSundaresan marked this conversation as resolved.
| extend StackTrace = replace_string(replace_string(replace_string(replace_string(replace_string(RawStackTrace, "\\\\r\\\\n", "\n"), "\\\\n", "\n"), "\\r\\n", "\n"), "\\n", "\n"), "\\t", "\t")
| extend DeviceName = Computer,
ErrorMessage = iff(SplitStart >= 0, trim_end(@'[\s,;:\.]+', substring(RenderedDescription, 0, SplitStart)), RenderedDescription)
| project TimeGenerated, DeviceName, EventID, Source, ErrorMessage, StackTrace
| order by TimeGenerated desc
| limit 100