# MetaCrate grid-agent operations This is the operator runbook for the portable `metacrate-grid-agent` binary. The binary has no dependency on systemd, a Windows service manager, a CLR, Python, Node.js, a provider SDK, or a shell at runtime. Linux service files and install helpers are packaging conveniences around the same foreground process and versioned control protocol. ## Quick start and modes Build the credential-free binary and validate the example without contacting a grid or LLM: ```sh cargo build --locked --release -p metacrate-grid-agent target/release/metacrate-grid-agent --config config/grid-agent.example.yml --check-config target/release/metacrate-grid-agent --config config/grid-agent.example.yml --run-once ``` `--check-config` parses YAML and any legacy referenced secret files, validates all bounds and TLS files, then exits before constructing the grid or LLM clients. The example is fake/offline mode (`integrated=false`, `split=false`) and all credential-looking values are placeholders. For live foreground or an embedded TUI, build intentionally: ```sh cargo build --locked --release -p metacrate-grid-agent --features live-grid target/release/metacrate-grid-agent --config /path/to/config.yml target/release/metacrate-grid-agent --config /path/to/config.yml --tui ``` Set `integrated=true` for the foreground and embedded-TUI commands. Set `split=true` for a headless service, then run the same binary as the TUI client: ```sh metacrate-grid-agent --config /path/to/config.yml metacrate-grid-agent --config /path/to/config.yml --tui-client ``` The TUI client and service must use the same control address and operator token. `--tui-client` never needs the grid password or LLM key. `--run-once` performs one supervised readiness/login and clean logout cycle. `--print-paths` prints the platform defaults without loading configuration. If `--config` is omitted, the default file is used only when it already exists: | Platform | Configuration | Non-secret state | |---|---|---| | Linux/Unix | `$XDG_CONFIG_HOME/metacrate/config.yml`, otherwise `$HOME/.config/metacrate/config.yml` | `$XDG_DATA_HOME/metacrate/grid-agent`, otherwise `$HOME/.local/share/metacrate/grid-agent` | | macOS | `$HOME/Library/Application Support/MetaCrate/config.yml` | `$HOME/Library/Application Support/MetaCrate/grid-agent` | | Windows | `%APPDATA%\MetaCrate\config.yml` | `%LOCALAPPDATA%\MetaCrate/grid-agent` | Relative paths in a YAML document resolve relative to that document where specified; service deployments should use absolute paths. ## Endpoint, grid identity, and authority `llm.endpoint_url` is the OpenAI-compatible provider base URL. Mentra owns the Responses path, SSE stream, endpoint behavior, and conversation runtime. For a proxy whose Responses endpoint is `/go/v1/responses`, configure the base ending in `/go`, not the final request path. Set `llm.model` to the model ID and keep `llm.api_key` in the private `config.yml`. Live modes require `grid.login_url`, `grid.avatar_name`, and `grid.password`. `authorized_avatar_uuids` contains exact grid UUIDs, never display names. Text claiming an authorized identity grants no authority. Public chat can request bounded informational work and safe public LSL delivery; movement, teleport, building, roaming changes, and administration remain policy-gated and require an authenticated authorized IM or a narrowly bound scheduler grant. Above-threshold actions receive an isolated one-shot LLM safety review; they do not depend on a continuously present human operator. ## Configuration contract and migration The YAML root uses `schema_version: 1`. Omitting it is accepted as legacy version 1. Any other value fails before startup with a migration message. There is no automatic in-place migration: copy the file, update the copy using the release notes/example, validate the copy, then atomically select it. Unknown fields fail closed. Installers never overwrite or migrate operator files. Resolution order is: 1. bounded built-in defaults; 2. the platform `config.yml` or explicit `--config` document; 3. legacy secret files referenced by that document. Process environment variables do not override connection, mode, or authority. Migrate an existing `.env` once with `metacrate-grid-agent --import-env /path/to/.env`, inspect it using `--preferences`, then remove the old file under the operator's retention policy. JSON remains readable only for migration. Mode, endpoints, credentials, authorization UUIDs, TLS, storage, queue/resource limits, reconnect policy, behavior, and interaction settings are restart-only. Runtime control can pause/resume autonomy, toggle the roaming job, make an emergency decision on an existing approval, cancel an active action, expire/delete conversation state, inject an operator message, reconnect, or shut down; it does not silently rewrite the configuration. A future reloadable field must be explicitly added to the versioned control/config contract. ## Secrets and privacy Threat model: grid residents, object/avatar/inventory metadata, capability replies, model output, public chat, IM text, and persisted files are untrusted. Remote peers may inject instructions, spoof names, replay approvals/call IDs, flood queues, delay or truncate replies, and attempt secret exfiltration. The service identity, local config/secret ACLs, authenticated UUID/control role, opaque policy authorization, generation fencing, bounded queues, and audit sink are trust boundaries. Host/root compromise, a malicious binary/dependency, and an operator deliberately approving a harmful action are outside the process sandbox and require OS/supply-chain/operational controls. Never place API keys, grid passwords, or control tokens in command arguments, unit files, wrapper XML, logs, crash-report commands, issue reports, or TUI screens. Secret wrappers redact `Debug` and `Display`, are not serializable, and normal observability stores pseudonymous correlation IDs, result codes, bounds, and hashes—not prompt bodies, credentials, visual pixels, or raw tool arguments. Secret files must be regular, non-symlink, bounded UTF-8 files containing one line. On Unix, startup rejects group/other permission bits; use mode `0600` or stricter and ownership by the service identity. On Windows, set an NTFS ACL that grants only the service identity and Administrators, for example with `icacls`; Rust's portable metadata API cannot prove arbitrary Windows ACL semantics, and FAT/network filesystems may not enforce them. Treat an unverifiable filesystem as unsuitable for unattended secrets. Rotate one credential at a time in `--preferences` (or an ACL-restricted copy of `config.yml`), save, run `--check-config`, then restart. Revoke the old credential only after readiness. Control observer and operator tokens must differ from each other and from grid/LLM credentials. ## Linux systemd The hardened example is [`../packaging/metacrate-grid-agent/systemd/metacrate-grid-agent.service`](../packaging/metacrate-grid-agent/systemd/metacrate-grid-agent.service). Create the unprivileged `metacrate-agent` identity, copy (do not overwrite) an operator configuration to `/etc/metacrate/config.yml` and create `/var/lib/metacrate/grid-agent`. Keep the configuration owned by the service identity with mode `0600`; do not put credentials in the unit environment. Install the unit, inspect the sandbox, validate, then start: ```sh sudo systemd-analyze security packaging/metacrate-grid-agent/systemd/metacrate-grid-agent.service sudo -u metacrate-agent /usr/local/bin/metacrate-grid-agent --config /etc/metacrate/config.yml --check-config sudo systemctl daemon-reload sudo systemctl enable --now metacrate-grid-agent.service ``` The unit uses `SIGINT`, matching foreground Ctrl-C and the owned graceful shutdown path. Do not replace it with `SIGKILL`. `ProtectSystem=strict` permits writes only under the state directory. ## Windows service operation Run the same `.exe`, YAML, control TCP protocol, and shutdown path. Portable foreground operation in PowerShell is the baseline: ```powershell & 'C:\Program Files\MetaCrate\metacrate-grid-agent.exe' --config 'C:\ProgramData\MetaCrate\config.yml' --check-config & 'C:\Program Files\MetaCrate\metacrate-grid-agent.exe' --config 'C:\ProgramData\MetaCrate\config.yml' ``` For unattended use, configure a maintained Windows service wrapper (for example WinSW) to launch exactly that command as a dedicated low-privilege account and to translate SCM Stop into Ctrl-C/console control before its timeout. Keep `config.yml` ACL-restricted to the service identity. Configure restart-on-failure, not unconditional rapid restart. Validate as the service identity before registration. The wrapper must not capture environment values or command output into a world-readable log. The supplied PowerShell installer replaces only the executable and never state. ## Control, network, and health Split control defaults to loopback TCP. A non-loopback bind is rejected unless an explicit Rustls certificate/private key is configured. Use host firewalls to allow only operator networks, protect token files, and prefer loopback plus an authenticated tunnel. Observer tokens are read-only. Protocol framing, role permissions, cancellation, event gaps, and limits are in the control-plane doc. Readiness is stricter than a TCP connection: the runtime view must show `transport_connected=true` and `agent_ready=true`. The TUI Overview and observer Runtime request are health/readiness checks; process existence alone is not readiness. Alert on authentication-blocked, sustained degraded/backoff, queue saturation/dropped-event counters, audit failure, orphan builds, and a stale generation. ## Retention, backup, upgrade, and rollback Conversation snapshots, landmark state, and audit journals are non-secret but privacy-sensitive. Stop or pause mutation, take a filesystem-consistent backup of the configured data directory, and encrypt/restrict the backup. Do not back up secrets with ordinary state. Journal rotation is bounded by the configured observability policy; ship rotated files to restricted storage before deletion when retention policy requires it. Replay is diagnostic and never executes an action. Release installation replaces only the binary. The POSIX and PowerShell helpers stage a temporary executable then move it into place; neither touches config, secrets, conversations, landmarks, or journals. For upgrade: back up state, install the new binary, validate the existing config, stop gracefully, start, and verify readiness. For rollback: stop gracefully, restore the prior binary, restore state only when the new version changed it incompatibly, validate, and start. Never run two service generations against one writable data directory. ## Failure playbooks - Authentication blocked: pause retries, verify login URL/avatar and rotate the password file; never paste it into logs. Force reconnect after correction. - LLM unavailable/rate limited: autonomy remains bounded; verify the provider base URL, firewall/DNS, key, and model compatibility. Multimodal rejection falls back to the textual scene summary without resending the large image. - Maintenance/disconnect: allow generation fencing and bounded backoff. Stale inference/mutation results are discarded; do not bypass reconnect controls. - Emergency: use operator Pause first, Cancel the exact active action when appropriate, then Graceful Shutdown. Ctrl-C/SIGINT follows the same cleanup. - Orphan build: keep the reported object IDs, inspect ownership in-world, and manually recover only those IDs. Never bulk-delete by name or proximity. - Corrupt persistence: preserve the quarantined file for restricted diagnosis; the service recovers an older valid generation or starts fail-closed. Do not hand-edit a live journal. - Full disk/audit backpressure: pause autonomy, free space according to retention policy, and restart only after the audit path is writable. Policy fails closed when required audit records cannot be accepted. ## Resource defaults and unsupported operations The example records all current queue, message, conversation, tool, behavior, reconnect, and interaction defaults. Important defaults include 256 grid events, 32 control commands, 512 observations, four concurrent inference requests, 16 tool calls, 512 active senders/sessions, a two-minute model window, and bounded 10-second shutdown. Vision defaults to a 640x360 headless Bevy/wgpu JPEG, a 64-meter configurable view radius, a persistent 512 MiB decoded-texture cache, and a deterministic software fallback with bounded entities, triangles, asset work, JPEG bytes, time, and concurrency. Authorized `behavior_camera_set` calls are limited to 96 meters from the avatar by default, require a distinct target, and accept a 20-120 degree vertical field of view; `behavior_camera_reset` restores the avatar-facing 60-degree view. Unsupported by design: arbitrary raw packets or agent-control flags, arbitrary shell/subprocess execution, provider/model discovery outside Mentra, remote plaintext control, unauthenticated mutation, unrestricted walking/teleport/touch/follow, automatic config migration, persistence of viewport pixels, framebuffer/screen capture, and treating untrusted grid/LLM text as instructions or authority. ## Release evidence Build the intentional graphs and retain the commands/output with the release: ```sh cargo build --locked --release -p metacrate-grid-agent cargo build --locked --release -p metacrate-grid-agent --features live-grid cargo tree --locked -p metacrate-grid-agent --features live-grid -e normal,build cargo audit ``` Record the binary byte size (`stat -c %s` on Linux or `Get-Item ... .Length` on PowerShell) and the `cargo tree` inventory. Reject CLR/scripting/provider SDK, subprocess adapters, unreviewed graphics stacks, or undeclared native libraries on the agent path. The consolidated Gitea gate runs only on `ubuntu-latest`; Windows portability is proved by the existing cross-target compile/static gate rather than a Windows Gitea runner. The milestone baseline is recorded in [grid-agent-release-evidence.md](grid-agent-release-evidence.md). Related contracts: [architecture](grid-agent-architecture.md), [policy](grid-agent-policy.md), [session](grid-agent-session.md), [control](grid-agent-control-plane.md), [observability](grid-agent-observability.md), [TUI](grid-agent-tui.md), and [conversation storage](grid-agent-conversation.md).