WindowsAgent is an extensible Go agent for capabilities that must run inside a signed-in Windows user's interactive session.
Its first capability is primary-monitor still capture through Windows Graphics Capture (WGC). It also includes a finite, read-only observation-job runtime that brokers locally distributed Starlark Script Packages to a unified memory/file observer process. Script Packages may carry manifest-declared native DLLs and call them through the Script Runner's generic Windows amd64 FFI. Every capability remains behind an explicit package, API, permission, and validation boundary.
Warning
The current HTTP server listens on 0.0.0.0:8787 without authentication,
TLS, or CORS by default. Anyone who can reach that port can trigger and
download screenshots and read foreground process metadata, including window
titles and executable paths. Use it only on a trusted LAN or private overlay
network.
The screenshot capability is available today:
- Windows 10 1903+ amd64
- primary-monitor capture using WGC and Direct3D 11
- SDR PNG output
- HDR scRGB capture tone-mapped to an SDR PNG preview
- cursor inclusion selected per request
- foreground process ID, executable name/path, window title, and observation time recorded with each capture
- capture-time foreground rule resolution with a navigable Codex
AGENTS.md - SHA-256 verified artifacts and bounded retention
- strict JSON errors with no GDI or hidden capture fallback
- optional hidden startup through an interactive-user Scheduled Task
The generic Starlark launcher and one Script capability are available today:
crimson-desert/inventoryperforms a finite memory attempt and, only when that attempt cannot produce a valid inventory, decodes one explicitly selected save file- the Go launcher resolves any registered
windows-observation-v1capability from its owning Rule, validates its input schema and host resource bindings, and never contains a capability allowlist - the job returns one schema-validated JSON result with per-call provenance
- the Go host launches only the runner and observer directly under one bounded Windows Job Object; it does not use PowerShell or a polling loop
windows-observer.exeremains game-neutral and never loads DLLs- the save file becomes a job-scoped opaque blob; the Script Runner resolves that blob and loads only the package-declared DLL alias
This is not a general remote memory API. HTTP exposes a live read-only Script catalog; the bearer-protected run endpoint delegates one request to the local launcher inside the signed-in Windows session.
Go 1.23 or newer is required.
mkdir -p .build
go test ./...
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 \
go build -trimpath \
-o .build/windows-capture-agent.exe \
./cmd/windows-capture-agent
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 \
go build -trimpath -ldflags "-H=windowsgui" \
-o .build/windows-capture-agent-background.exe \
./cmd/windows-capture-agent
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 \
go build -trimpath \
-o .build/windows-observer.exe \
./cmd/windows-observer
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 \
go build -trimpath \
-o .build/windows-observation-script-runner.exe \
./cmd/windows-observation-script-runner
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 \
go build -trimpath \
-o .build/windows-observation-job.exe \
./cmd/windows-observation-job
cp -R Rules .build/The GUI-subsystem build runs without a console window.
Run the console build inside the signed-in Windows user's session:
.\.build\windows-capture-agent.exe `
--rules-dir (Resolve-Path .\.build\Rules)Available options:
--listen HTTP listen address (default 0.0.0.0:8787)
--data-dir artifact and log root
--rules-dir external Rule plugin directory (default <data-dir>/Rules)
--script-api-token-file bearer-token file (default <data-dir>/script-api.token)
--capture-timeout per-request timeout (default 5s)
--retention number of artifacts to retain (default 100)
--log-level debug, info, warn, or error
--log-file optional JSON log file
The process must not run as a traditional Session 0 Windows service because WGC requires access to the interactive desktop.
Create one strict launcher request outside the Rule plugin:
{
"inputs": {
"save": {
"root": "crimson-desert-saves",
"relative": "slot1/save.save"
}
},
"fileRoots": {
"crimson-desert-saves": "C:\\Users\\user\\AppData\\Local\\Pearl Abyss\\CD\\save\\<account-id>"
}
}Run the registered capability through the generic launcher from the signed-in session:
.\.build\windows-observation-job.exe `
--capability crimson-desert/inventory `
--install-root (Resolve-Path .\.build) `
--rules-dir (Resolve-Path .\.build\Rules) `
--request-file (Resolve-Path .\inventory-request.json)inputSchema belongs to the Script Package; fileRoots supplies exact
host-authorized bindings for the aliases requested by its manifest. Missing,
extra, relative, or undeclared bindings fail. The launcher derives the expected
foreground executable from the capability's owning Rule folder. The
--process-id and --process-path flags exist only for a trusted local host
that already resolved that same owning-Rule process; the observer still
revalidates its path, creation time, and executable SHA-256.
The package declares native-library alias save-decoder, its
windows-amd64 artifact, call limit, and native-memory limit. Starlark
loads only that alias through native.load_library("save-decoder"); it owns the
crimson-rs export signatures, record layout, return codes, and JSON conversion.
load_library is used because load is a reserved Starlark keyword.
From the repository root in PowerShell:
.\scripts\install-windows-capture-agent.ps1 `
-ExecutablePath .\.build\windows-capture-agent-background.exe `
-RulesPath .\.build\RulesThe installer copies the capture executable, generic Starlark launcher,
Script Runner, Observer, and external Rule plugins under the current user's
%LOCALAPPDATA%, registers an interactive-token at-logon Scheduled Task,
starts it, and verifies /healthz. All four executables must be present
beside the selected build artifact before installation. The installer does
not create an SCM service or modify Windows Firewall.
Builds that stored rule.agents.sha256, or matched Rule metadata without
rule.scripts, use an incompatible capture metadata contract. The installer
detects those captures before stopping the current task and refuses the
migration unless explicitly asked to preserve them:
.\scripts\install-windows-capture-agent.ps1 `
-ExecutablePath .\.build\windows-capture-agent-background.exe `
-RulesPath .\.build\Rules `
-ArchiveIncompatibleCapturesThe switch renames the existing captures directory to a timestamped
captures.pre-external-rules-* archive. It does not reinterpret or delete the
old artifacts.
Publish one updated Rule plugin without rebuilding the executable or restarting the task:
.\scripts\sync-windows-agent-rule.ps1 `
-SourceRulePath .\Rules\CrimsonDesert.exe `
-DestinationRulesDir "$env:LOCALAPPDATA\gameGuide\windows-capture-agent\Rules"For deployment compatibility, the current executable, task, and data directory
retain their established windows-capture-agent names. They identify the first
capability, not the broader project.
GET /healthz
GET /v1/status
POST /v1/captures
GET /v1/captures/latest
GET /v1/captures/latest/content
GET /v1/captures/{id}
GET /v1/captures/{id}/content
GET /v1/rules/{rule-id}/AGENTS.md
GET /v1/rules/{rule-id}/scripts
POST /v1/scripts/run
Create a capture:
curl.exe `
-H "Content-Type: application/json" `
--data-binary '{"include_cursor":true}' `
http://127.0.0.1:8787/v1/capturesDownload the latest PNG:
curl.exe `
-o capture.png `
http://127.0.0.1:8787/v1/captures/latest/contentDiscover the current Script contracts for a matched Rule:
curl.exe http://127.0.0.1:8787/v1/rules/CrimsonDesert.exe/scriptsThe catalog returns each capability's ID, declared runtime, title, package version, input schema, output schema, and authenticated launcher endpoint. It is read-only and does not execute a Script.
Run one registered Script from the signed-in agent session:
$token = [IO.File]::ReadAllText(
"$env:LOCALAPPDATA\gameGuide\windows-capture-agent\script-api.token"
)
curl.exe `
-H "Authorization: Bearer $token" `
-H "Content-Type: application/json" `
--data-binary "@inventory-invocation.json" `
http://127.0.0.1:8787/v1/scripts/runThe invocation body contains capability, inputs, and fileRoots; it uses
the same input and binding contract as the local launcher request. The
installer creates the token once, preserves it across upgrades, stores only
its path in task configuration, and never places its value in Rule content or
HTTP discovery responses. Script execution is serialized and does not upload,
rewrite, or reload a Rule plugin.
Only one capture can run at a time. A concurrent request receives
409 capture_busy. Each completed artifact contains capture.png and
metadata.json. The response and metadata include a required foreground
object:
{
"foreground": {
"observed_at": "2026-07-27T01:02:03.000000004Z",
"process_id": 4242,
"executable_name": "Game.exe",
"executable_path": "C:\\Games\\Game.exe",
"window_title": "Game"
},
"rule": {
"status": "matched",
"description": "The executing agent must read rule.agents.url and rule.scripts.url before taking any rule-specific action.",
"id": "Game.exe",
"agents": {
"url": "/v1/rules/Game.exe/AGENTS.md",
"content_type": "text/markdown; charset=utf-8"
},
"scripts": {
"url": "/v1/rules/Game.exe/scripts",
"content_type": "application/json; charset=utf-8"
}
}
}The foreground window is sampled immediately after WGC produces the captured
frame. The same response resolves its executable name against the current
external folders under Rules/; this keeps the capture JSON as Codex's single
Windows perception entry point. Each request reloads rule.json and
AGENTS.md, so a completed Rule plugin replacement requires no agent reload or
task restart. Codex follows rule.agents.url for policy and
rule.scripts.url for the current machine-readable capability, input, output,
and launcher contract. Script package validation occurs only when that catalog
or capability is requested; capture remains independent from Script package
health. An executable without a rule reports
rule.status=unmatched with a description that no rule guidance is available,
without inventing a substitute.
If Windows does not expose the foreground process or its executable
path, the request fails explicitly with 503 foreground_process_unavailable;
the agent does not guess process identity or commit a partial artifact.
Foreground and rule metadata are required for every artifact under this contract. Artifact directories created by older builds do not contain the full contract and fail the strict startup scan rather than being presented as complete captures. Preserve or archive those directories before installing this build with a new, empty data directory; there is no automatic migration.
cmd/windows-capture-agent/ screenshot capability executable
cmd/windows-observation-job/ generic local windows-observation-v1 launcher
cmd/windows-observation-script-runner/ isolated Starlark runner
cmd/windows-observer/ unified read-only memory/file observer
docs/design/ maintained design registry
internal/observationjob/ finite broker and Windows Job Object limits
internal/observationlauncher/ native child-process isolation
internal/observer/ permission-bounded memory/file backends
internal/scriptrunner/ Starlark runtime and generic Windows native FFI
internal/artifact/ artifact transactions and retention
internal/capture/ screenshot capability contracts
internal/config/ process configuration
internal/foreground/ foreground process observation
internal/httpapi/ current HTTP surface
internal/pixels/ SDR and HDR pixel conversion
internal/rules/ live Rule plugin loading and navigation
internal/scriptlaunch/ strict generic launcher request contract
internal/wgc/ WGC and Direct3D 11 implementation
Rules/<Executable.exe>/ distributable rule.json, AGENTS.md, and Scripts
scripts/ Windows installation helpers
New or changed Script packages must follow the
Script Package development contract.
It defines package ownership, source-transition rules, manifest validation,
native ABI responsibility, privacy boundaries, and required validation.
New capabilities should receive their own internal package and API contract instead of being folded into the screenshot packages.
See SECURITY.md before exposing the listener or reporting a vulnerability. Contributions are described in CONTRIBUTING.md.
WindowsAgent is available under the MIT License.