Qud Agent Harness is a source-only research project that provides a local, typed automation boundary for a legally owned Caves of Qud installation. It combines a source mod, an authenticated loopback bridge, a Python client, isolated process supervision, and Gymnasium adapters. The harness exposes only player-visible observations by default and sends actions through Qud's native input and UI paths.
This repository contains integration code and non-proprietary contract fixtures only. It does not distribute Caves of Qud, save games, checkpoints, recorded trajectories, or other game-derived data. A separately purchased and installed copy of Caves of Qud is required for live use.
Version 1.0 freezes the documented Python, Gymnasium, and wire surfaces for stable local experiments. All ten interactive modes have passed live checks on the known working setup against isolated external fixtures.
- Unified schema-0.3 observations with bounded messages, visible map state, normalized modes, exact available actions, and opt-in privileged diagnostics.
- Authenticated NDJSON protocol 0.3 bound to loopback, with stale-observation rejection and no-retry semantics for uncertain gameplay actions.
- Eight-direction movement, wait, screen entry, modal navigation, semantic opaque UI targets, trade controls, targeting, and world travel.
- Typed synchronous Python API plus restricted and interactive Gymnasium environments.
- Harness-owned runtime directories, immutable save baselines, native character generation, detached episode handoff, and exact-child shutdown.
- Crash-safe append-only trajectory recording with summaries, public-field projection, explicit privileged opt-in, and bounded owned-root retention.
- Strict trajectory inspection/diffing, in-process protocol simulation, and explicitly authorized checked replay in fresh isolated episodes.
- Legacy JSON exporters retained as diagnostic outputs.
| Component | Known working version |
|---|---|
| Caves of Qud | 2.0.214.66 |
| Steam build | 24626113 |
| Host | Linux x86_64 |
| Bridge/Python package | 1.0.0 |
| Mod manifest | 2.0.0 |
| Protocol / observation / lifecycle | 0.3 / 0.3 / 0.1 |
| Vendored extractor | commit a4cce57a8a7f3a321522c34918cd31bbe67c31d1 |
Nearby Qud bugfix releases are expected to work, but this table records the setup actually exercised. Rebuild the mod and run the relevant smoke checks after an update if private integration behavior changes. See compatibility.
Supervisor-owned smoke runners accept --expected-game-version and
--expected-steam-build-id, or the corresponding QUD_EXPECTED_GAME_VERSION
and QUD_EXPECTED_STEAM_BUILD_ID environment variables, for validating a new
build without a source edit.
python3 -m venv .venv
.venv/bin/pip install -e './python[dev]'
./scripts/check.sh
export QUD_GAME_DIR="/absolute/path/to/Caves of Qud"
export QUD_USER_DIR="/absolute/path/to/CavesOfQud-user-data"
./scripts/install_mod.sh --dry-run
./scripts/install_mod.shAfter reviewing the source, enable mods and scripting mods in Qud. Manual attachment checks require a loaded disposable character:
./scripts/verify_installation.py
./scripts/smoke_protocol.py
./scripts/smoke_core_queue.pyThe installer writes the source mod to
$QUD_USER_DIR/Mods/QudStateExtractor, preserves a mode-0600 bridge token, and
places state exports under $QUD_USER_DIR/AgentHarness/state. It refuses to
overwrite a directory it cannot prove is harness-owned.
For complete setup, isolated episodes, and Python examples, read Getting started.
After defining a named profile in the configuration guide, the unified operator entry point covers the common source-local workflows:
qud-agent --profile local check
qud-agent --profile local state create
qud-agent --profile local validate
qud-agent --profile local state inspectvalidate is the default documented live path: it creates its own fixed-seed
Joppa character in the isolated root. It does not require or import a normal-
profile save. Custom character specifications and immutable baselines remain
explicit comparison inputs to the specialized runners.
./scripts/check.sh is the canonical offline check. It runs the .NET and
Python suites, C# and Python coverage collection, Ruff, strict mypy, JSON Schema
validation, shell syntax checks, and git diff --check.
./scripts/check.sh
QUD_GAME_DIR="$QUD_GAME_DIR" ./scripts/check.sh --with-gameThe game-enabled form also compiles the complete mod against the configured Qud assemblies. Live runners are separate because they launch or attach to Qud; supervisor-owned validation creates its input-free isolated reset state by default. Current evidence and known boundaries are recorded in Validation.
- Live interactive checks depend on private, non-committed immutable fixture baselines; those fixtures are not distributed with the repository.
- Rewards are intentionally zero; interpretation, reward design, arbitrary console commands, and hidden-state access are outside the supported surface.
- Multi-instance/vector execution and true headless operation are future work.
- Replay covers validated gameplay actions only; lifecycle reconstruction, arbitrary branching, rewards, and video playback remain outside its scope.
- Qud patch releases are expected to remain compatible, but private runtime integration points can still change.
- Getting started
- Architecture and threading
- Configuration
- Protocol, observations, and actions
- Python API
- Testing and validation evidence
- Compatibility and security
- Compatibility and deprecation policy and release checklist
- Roadmap, changelog, and contributing
- Architecture decision record and upstream provenance
This is a source-only research project. Do not commit or distribute proprietary Qud assemblies, saves, checkpoints, artwork, generated assemblies, logs, recorded trajectories, or state exports with this repository. Local users provide their own licensed game installation and disposable validation state.
The harness source is released under the MIT License. Caves of Qud and locally generated game data are not covered or distributed by that license. See SECURITY.md and the vendored component's provenance record.