# Plugin: Minimal Windows

**Audience:** Integrators registering a long-running managed plugin on Windows endpoints.

This example shows the minimum valid plugin JSON for a Windows executable: autoStart enabled, a primary MQTT subscription, monitoring and auto-restart active, and permission to publish to KeeperLogger. Use it as a starting point and replace the placeholder values before deploying. For Linux and macOS variants, see [Plugin: Minimal Linux](/keeperpam/endpoint-privilege-manager/integrations/examples/plugin-minimal-linux.md) and [Plugin: Minimal macOS](/keeperpam/endpoint-privilege-manager/integrations/examples/plugin-minimal-macos.md).

If your component runs on a schedule and exits rather than staying running, use a job task instead — start with [Job: Minimal Windows](/keeperpam/endpoint-privilege-manager/integrations/examples/job-minimal-windows.md).

## The Plugin JSON

```json
{
  "id": "MyBridge",
  "name": "My Bridge",
  "description": "Long-running bridge component.",
  "version": "1.0.0",

  "pluginType": "Executable",
  "executablePath": "bin/MyBridge/MyBridge.exe",
  "supportedPlatforms": ["Windows"],

  "Subscription": {
    "Topic": "MyBridge",
    "Qos": 2,
    "CleanSession": true
  },

  "metadata": {
    "mqttRole": ["subscriber", "publisher"],
    "mqttTopics": {
      "publish": ["KeeperLogger"],
      "subscribe": ["MyBridge", "MyBridge/Commands/+"]
    }
  },

  "startupPriority": 60,
  "autoStart": true,
  "executionContext": "Service",
  "requiresMonitoring": true,
  "autoRestart": true
}
```

## What to Change

<table data-header-hidden="false" data-header-sticky><thead><tr><th width="280.6666259765625">Field</th><th>What to Put Here</th></tr></thead><tbody><tr><td><code>id</code></td><td>A stable, unique identifier. This becomes the plugin's key in <code>/api/PluginSettings/{id}</code> and must match the filename: <code>MyBridge.json</code> for <code>"id": "MyBridge"</code>. Do not change this after deployment without coordinating a migration — existing settings stored under the old ID will not carry over.</td></tr><tr><td><code>name</code></td><td>A human-readable name shown in logs and the admin view.</td></tr><tr><td><code>version</code></td><td>Your binary's semantic version. Update this with each release for diagnostics and change tracking.</td></tr><tr><td><code>executablePath</code></td><td>Path to your binary relative to the agent root, or an absolute path. The default Windows agent root is <code>C:\Program Files\KeeperPrivilegeManager</code> — so <code>bin/MyBridge/MyBridge.exe</code> resolves to <code>C:\Program Files\KeeperPrivilegeManager\bin\MyBridge\MyBridge.exe</code>.</td></tr><tr><td><code>Subscription.Topic</code></td><td>The primary MQTT topic for this plugin. By convention, use the plugin <code>id</code>. Must be unique among all plugins registered on the agent.</td></tr><tr><td><code>metadata.mqttTopics.publish</code></td><td>Every MQTT topic your binary publishes to. Include <code>KeeperLogger</code> if you publish log messages. Add any other output topics here — the broker enforces this list.</td></tr><tr><td><code>metadata.mqttTopics.subscribe</code></td><td>Every MQTT topic your binary subscribes to beyond the primary <code>Subscription.Topic</code>. The <code>Commands/+</code> pattern is a convention for command-style topics — replace or remove it if your plugin does not use it.</td></tr><tr><td><code>startupPriority</code></td><td>Controls startup order relative to other plugins. Lower numbers start earlier. <code>60</code> is a reasonable default for a custom plugin that has no dependencies on other custom components.</td></tr></tbody></table>

## How This Works

**`pluginType: Executable`** tells the orchestrator to launch the binary as a child process. This is the correct type for a standalone executable.

**`executablePath`** is relative to the agent root, not to the plugin directory. `bin/MyBridge/MyBridge.exe` places the binary outside the `Plugins/` tree, which avoids the stricter certificate path checks that apply to executables located within plugin-related directories. Use an absolute path if your deployment layout does not follow this convention.

**`Subscription`** is the primary MQTT topic the orchestrator uses to identify this plugin. Set `Qos: 2` for commands that must not be lost or duplicated. `CleanSession: true` is appropriate for most plugins — it means the broker discards any queued messages from previous sessions when the plugin reconnects, rather than replaying them.

**`metadata.mqttTopics`** must accurately reflect what your binary actually publishes and subscribes to. The broker enforces these lists at runtime — a publish or subscribe outside the declared topics will be denied. Unlike job tasks, plugins do not have a separate job-level `mqttTopics` block; all topic declarations live here under `metadata`.

**`autoStart: true`** causes the orchestrator to launch the plugin when the agent starts. Set this to `false` if the plugin should only run on demand or when triggered by a job — see [Plugin: Manual Start](https://claude.ai/chat/plugin-manual-start) for that pattern.

**`requiresMonitoring: true`** and **`autoRestart: true`** together tell the orchestrator to watch the process and restart it if it exits unexpectedly. Enable both for any production plugin that must stay running. If your plugin exits intentionally under certain conditions, ensure those exits use a recognizable exit code so you can distinguish expected shutdowns from crashes in the logs.

**`executionContext: Service`** runs the plugin as the agent service account — appropriate for background components that do not require an interactive user session.

## Before You Deploy

1. **Sign the binary.** Plugin binaries on Windows are subject to stricter trust checks than job task binaries. Sign with an Authenticode certificate and add your thumbprint to `Settings:AlternativeSignatures` in `appsettings.json` if your deployment requires it.
2. **Place the binary** at the path resolved by `executablePath` before registering the plugin.
3. **Place the JSON file** at `{AgentRoot}\Plugins\MyBridge.json`. The filename must match `id`.
4. **Coordinate with your administrator** on the supported insertion path. Dropping a plugin JSON file and restarting the agent is the typical mechanism, but your environment may have packaging or policy requirements.
5. **Restart the agent service** after placing both files so the orchestrator picks up the new plugin registration.

## Verify

After the agent restarts, confirm the plugin started successfully by checking the agent logs for your plugin name, then verify MQTT connectivity by checking that your binary's KeeperLogger publishes are visible in the operator log view.

To read your plugin's effective settings:

```powershell
Invoke-RestMethod -Method Get `
  -Uri "https://127.0.0.1:6889/api/PluginSettings/MyBridge" `
  -Certificate $pluginClientCert
```

This call requires Plugin-tier authentication — it must come from a process the agent launched, not from an arbitrary script. Run it from inside your plugin binary at startup to confirm the settings path is working end to end.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.keeper.io/keeperpam/endpoint-privilege-manager/integrations/examples/plugin-minimal-windows.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
