{"id":"0092a028-d6b6-4626-8605-f2e890d6642b","entityType":"agent","slug":"clawhub-zw008-veeam-aiops","name":"veeam-aiops","canonicalUrl":"https://www.xpersona.co/agent/clawhub-zw008-veeam-aiops","canonicalPath":"/agent/clawhub-zw008-veeam-aiops","generatedAt":"2026-10-10T03:02:02.036Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T20:26:39.439Z","emptyReason":null},"description":"Use this skill whenever the user needs to operate Veeam Backup & Replication — a one-shot health overview, read-only diagnostics / RCA (triage failed backup-job sessions and flag repositories low on space), list/inspect/start/stop/retry backup jobs, enable/disable jobs, list restore points and start a VM restore, list backup repositories with capacity, list stored backups and their objects, inventory backup infrastructure (managed servers, proxies), and poll/stop async sessions for job/restore progress. Always use this skill for \"list veeam jobs\", \"run veeam backup\", \"start veeam job\", \"veeam restore\", \"veeam repository\", \"veeam backup status\", or \"veeam session\" when the context is explicitly Veeam / Veeam Backup & Replication / VBR. Do NOT use when the target is not Veeam Backup & Replication (other backup products, hypervisor lifecycle, or cloud providers are out of scope). Common Veeam B&R operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers).","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 2K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:veeam-aiops","sourceUrl":"https://clawhub.ai/zw008/veeam-aiops","homepage":"https://clawhub.ai/zw008/skills/veeam-aiops","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/zw008/veeam-aiops","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/zw008/skills/veeam-aiops","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":66,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"veeam-aiops technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-09T20:26:39.439Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T20:26:39.439Z","emptyReason":null},"stars":null,"forks":null,"downloads":2027,"packageName":null,"latestVersion":"0.16.1","tractionLabel":"2K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T20:26:39.439Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T20:26:39.439Z","lastCrawledAt":"2026-10-09T20:26:39.439Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T20:26:39.439Z","lastVerifiedAt":null,"highlights":[{"version":"0.16.1","createdAt":"2026-09-15T06:22:49.149Z","changelog":"## veeam-aiops 0.16.1 Changelog - Removed the sample file: `skill-card.md`. - No user-facing changes to functionality or API. - Internal documentation cleanup only.","fileCount":7,"zipByteSize":24384},{"version":"0.16.0","createdAt":"2026-09-13T15:05:45.489Z","changelog":"veeam-aiops 0.16.0 - Updated documentation in SKILL.md, references/agent-guardrails.md, references/capabilities.md, and references/cli-reference.md. - Removed the skill-card.md file. - No functional or behavioral changes—this release is a documentation and cleanup update.","fileCount":7,"zipByteSize":24404},{"version":"0.15.3","createdAt":"2026-09-12T14:48:20.499Z","changelog":"- skill-card.md has been removed. - SKILL.md updated: OpenClaw plugin example now references \"clawhub:@zw008/veeam-aiops\" instead of the previous org. - No changes to logic or tooling—documentation update and cleanup only.","fileCount":7,"zipByteSize":23275},{"version":"0.15.2","createdAt":"2026-09-12T12:48:42.749Z","changelog":"veeam-aiops 0.15.2 - Updated agent guardrails and capabilities documentation. - Removed the obsolete skill-card.md file. - No changes to core functionality or configuration.","fileCount":7,"zipByteSize":23000},{"version":"0.15.1","createdAt":"2026-09-12T10:29:56.273Z","changelog":"veeam-aiops 0.15.1 - Removed the file: skill-card.md - No functional changes; this update is limited to documentation/metadata cleanup.","fileCount":7,"zipByteSize":22952},{"version":"0.15.0","createdAt":"2026-09-12T06:45:24.273Z","changelog":"veeam-aiops 0.15.0 - Added OpenClaw plugin installation instructions in SKILL.md for easier OpenClaw/MCP integration. - Clarified that the MCP server is fetched via `uvx` and must be on `PATH` when used as an OpenClaw plugin. - Removed the redundant skill-card.md file. - Updated documentation for improved clarity on installation and usage with OpenClaw.","fileCount":7,"zipByteSize":23131},{"version":"0.14.0","createdAt":"2026-09-12T00:42:35.372Z","changelog":"- Updated environment and binary requirements: now accepts either \"veeam-aiops\" or \"uvx\" binaries. - Removed skill-card.md file. - Refined metadata and compatibility sections for clarity and accuracy. - No user-facing command or workflow changes.","fileCount":7,"zipByteSize":22532},{"version":"0.13.1","createdAt":"2026-09-11T15:13:41.939Z","changelog":"veeam-aiops 0.13.1 - Updated documentation in `references/capabilities.md` - Removed the `skill-card.md` file - No changes to core functionality or behavior","fileCount":7,"zipByteSize":22570}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:veeam-aiops","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:veeam-aiops` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/zw008/veeam-aiops before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-veeam-aiops/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-veeam-aiops/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-veeam-aiops/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-veeam-aiops/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-veeam-aiops/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-veeam-aiops/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T03:02:02.032Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-veeam-aiops/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-veeam-aiops/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-veeam-aiops/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-veeam-aiops/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T20:26:39.439Z","emptyReason":null},"readme":"Skill: veeam-aiops\n\nOwner: zw008\n\nSummary: Use this skill whenever the user needs to operate Veeam Backup & Replication — a one-shot health overview, read-only diagnostics / RCA (triage failed backup-job sessions and flag repositories low on space), list/inspect/start/stop/retry backup jobs, enable/disable jobs, list restore points and start a VM restore, list backup repositories with capacity, list stored backups and their objects, inventory backup infrastructure (managed servers, proxies), and poll/stop async sessions for job/restore progress. Always use this skill for \"list veeam jobs\", \"run veeam backup\", \"start veeam job\", \"veeam restore\", \"veeam repository\", \"veeam backup status\", or \"veeam session\" when the context is explicitly Veeam / Veeam Backup & Replication / VBR. Do NOT use when the target is not Veeam Backup & Replication (other backup products, hypervisor lifecycle, or cloud providers are out of scope). Common Veeam B&R operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers).\n\nTags: latest:0.16.1\n\nVersion history:\n\nv0.16.1 | 2026-09-15T06:22:49.149Z | auto\n\n## veeam-aiops 0.16.1 Changelog\n\n- Removed the sample file: `skill-card.md`.\n- No user-facing changes to functionality or API.\n- Internal documentation cleanup only.\n\nv0.16.0 | 2026-09-13T15:05:45.489Z | auto\n\nveeam-aiops 0.16.0\n\n- Updated documentation in SKILL.md, references/agent-guardrails.md, references/capabilities.md, and references/cli-reference.md.\n- Removed the skill-card.md file.\n- No functional or behavioral changes—this release is a documentation and cleanup update.\n\nv0.15.3 | 2026-09-12T14:48:20.499Z | auto\n\n- skill-card.md has been removed.\n- SKILL.md updated: OpenClaw plugin example now references \"clawhub:@zw008/veeam-aiops\" instead of the previous org.\n- No changes to logic or tooling—documentation update and cleanup only.\n\nv0.15.2 | 2026-09-12T12:48:42.749Z | auto\n\nveeam-aiops 0.15.2\n\n- Updated agent guardrails and capabilities documentation.\n- Removed the obsolete skill-card.md file.\n- No changes to core functionality or configuration.\n\nv0.15.1 | 2026-09-12T10:29:56.273Z | auto\n\nveeam-aiops 0.15.1\n\n- Removed the file: skill-card.md\n- No functional changes; this update is limited to documentation/metadata cleanup.\n\nv0.15.0 | 2026-09-12T06:45:24.273Z | auto\n\nveeam-aiops 0.15.0\n\n- Added OpenClaw plugin installation instructions in SKILL.md for easier OpenClaw/MCP integration.\n- Clarified that the MCP server is fetched via `uvx` and must be on `PATH` when used as an OpenClaw plugin.\n- Removed the redundant skill-card.md file.\n- Updated documentation for improved clarity on installation and usage with OpenClaw.\n\nv0.14.0 | 2026-09-12T00:42:35.372Z | auto\n\n- Updated environment and binary requirements: now accepts either \"veeam-aiops\" or \"uvx\" binaries.\n- Removed skill-card.md file.\n- Refined metadata and compatibility sections for clarity and accuracy.\n- No user-facing command or workflow changes.\n\nv0.13.1 | 2026-09-11T15:13:41.939Z | auto\n\nveeam-aiops 0.13.1\n\n- Updated documentation in `references/capabilities.md`\n- Removed the `skill-card.md` file\n- No changes to core functionality or behavior\n\nv0.13.0 | 2026-09-11T14:48:04.830Z | auto\n\nveeam-aiops 0.13.0\n\n- Updated workflows for diagnosing job failures, now documenting the new `--since-hours 24` argument in documentation and usage examples.\n- Added and updated references in agent guardrails and capabilities documentation.\n- Cleaned up documentation by removing the deprecated `skill-card.md` file.\n- General documentation improvements and alignment across reference and CLI documentation files.\n\nv0.12.0 | 2026-09-11T08:04:03.523Z | auto\n\n**New per-VM backup storage usage and ranking tools added.**\n\n- Introduced new tools for per-VM backup storage usage and ranking VMs by storage consumed (showback/chargeback support).\n- Increased total MCP tool count from 25 to 27.\n- Documentation updated to reflect new backup usage and ranking capabilities.\n- Removed now-obsolete `skill-card.md` file.\n\nv0.11.0 | 2026-08-10T06:54:39.604Z | auto\n\n## veeam-aiops 0.11.0\n\n- Removed the sample file `skill-card.md`.\n- No changes to core functionality or features.\n\nv0.10.0 | 2026-08-03T05:55:12.634Z | auto\n\n- Removed the file skill-card.md.\n- No user-facing features were added or changed in this version.\n- Internal documentation and packaging simplified by removing redundant files.\n\nv0.9.0 | 2026-08-02T09:42:16.404Z | auto\n\n- Removed the file skill-card.md.\n- No changes to core functionality or configuration.\n- No impact to users or workflows; this is a documentation cleanup.\n\nv0.8.0 | 2026-07-21T15:31:25.516Z | auto\n\n## veeam-aiops 0.8.0\n\n- Removed the file: `skill-card.md`\n- No changes to functionality or user-facing behavior.\n- This update streamlines documentation by removing redundant or obsolete files.\n\nv0.7.0 | 2026-07-21T09:43:16.753Z | auto\n\nveeam-aiops 0.7.0\n\n- Governance harness updated: risk-tier labelling in @governed_tool decorator is now more descriptive.\n- Minor documentation enhancements across SKILL.md and reference guides for clarity and accuracy.\n- Internal references to risk tiers and audit updated to reflect improved labeling.\n- Removed legacy skill-card.md for file clean-up.\n\nv0.6.0 | 2026-07-20T11:17:42.350Z | auto\n\nveeam-aiops 0.6.0\n\n- Expanded documentation on dry-run support: clarified dry-run behavior for destructive operations, including audit and undo semantics.\n- Updated references and capability documentation for improved clarity and accuracy.\n- Removed obsolete skill-card.md file.\n\nv0.5.1 | 2026-07-19T13:13:28.326Z | auto\n\n## veeam-aiops 0.5.1 Changelog\n\n- Removed the file `skill-card.md`.\n- No new features or bug fixes, just cleanup of documentation assets.\n- Functionality and user experience remain unchanged.\n\nv0.5.0 | 2026-07-19T03:53:41.568Z | auto\n\nveeam-aiops 0.5.0\n\n- Adds diagnostics and RCA tools for failed backup jobs and repository capacity issues.\n- Expands MCP tool coverage to 25, including new diagnostic tools.\n- Documentation improved: new guardrails/agent docs, merged guidance on diagnostics, and richer workflows.\n- Removes outdated skill-card.md and restructures main docs for clarity.\n- Refines descriptions and metadata for enhanced discoverability and use-case guidance.\n\nv0.4.0 | 2026-07-17T05:54:15.204Z | auto\n\nveeam-aiops 0.4.0\n\n- Removed the sample file skill-card.md.\n- No feature or interface changes; this is a maintenance/clean-up release.\n\nv0.3.0 | 2026-07-13T13:07:25.575Z | auto\n\nveeam-aiops 0.3.0\n\n- Improved SKILL.md documentation for clarity and conciseness.\n- Updated installation and usage guidance for local and cloud scenarios.\n- Refined usage mode recommendations and related skill routing descriptions.\n- No changes to code or functionality; documentation update only.\n\nv0.2.0 | 2026-06-27T02:23:20.639Z | auto\n\nveeam-aiops 0.2.0\n\n- Credentials are now stored encrypted in ~/.veeam-aiops/secrets.enc, unlocked via a master password. Plaintext .env fallback is deprecated.\n- Major coverage expansion: 21 MCP tools (up from 12), including health overview, job retry, repository detail, backup objects, managed servers, proxies, session log/stop, and more.\n- Added quickstart onboarding (veeam-aiops init) with interactive or non-interactive (CI) flows.\n- Improved documentation: CLI reference, setup guide, capabilities.\n- Removed legacy skill-card.md.\n\nv0.1.0 | 2026-06-22T06:13:14.224Z | user\n\nv0.1.0 first release: standalone governed Veeam B&R ops — 12 MCP tools with built-in audit/budget/undo/risk-tier harness\n\nArchive index:\n\nArchive v0.16.1: 7 files, 24384 bytes\n\nFiles: references/agent-guardrails.md (9982b), references/capabilities.md (17524b), references/cli-reference.md (4109b), references/setup-guide.md (3570b), skill-card.md (2903b), SKILL.md (17247b), _meta.json (131b)\n\nFile v0.16.1:SKILL.md\n\n---\nname: veeam-aiops\nslug: veeam-aiops\ndisplayName: \"Veeam AIops\"\nsummary: \"Governed Veeam Backup & Replication ops — 27 MCP tools with audit, budget, undo guards.\"\nlicense: MIT\nhomepage: https://github.com/AIops-tools/Veeam-AIops\ntags: [aiops, mcp, governance, veeam]\ndescription: >\n  Use this skill whenever the user needs to operate Veeam Backup & Replication — a one-shot health overview, read-only diagnostics / RCA (triage failed backup-job sessions and flag repositories low on space), list/inspect/start/stop/retry backup jobs, enable/disable jobs, list restore points and start a VM restore, list backup repositories with capacity, list stored backups and their objects, inventory backup infrastructure (managed servers, proxies), and poll/stop async sessions for job/restore progress.\n  Always use this skill for \"list veeam jobs\", \"run veeam backup\", \"start veeam job\", \"veeam restore\", \"veeam repository\", \"veeam backup status\", or \"veeam session\" when the context is explicitly Veeam / Veeam Backup & Replication / VBR.\n  Do NOT use when the target is not Veeam Backup & Replication (other backup products, hypervisor lifecycle, or cloud providers are out of scope).\n  Common Veeam B&R operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers).\ninstaller:\n  kind: uv\n  package: veeam-aiops\nargument-hint: \"[job id or describe your Veeam task]\"\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"veeam-aiops\",\"uvx\"]},\"optional\":{\"env\":[\"VEEAM_AIOPS_CONFIG\",\"VEEAM_AIOPS_MASTER_PASSWORD\"]},\"homepage\":\"https://github.com/AIops-tools/Veeam-AIops\",\"emoji\":\"💾\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  Standalone, self-governed Veeam Backup & Replication operations. The governance harness (audit, policy, token/runaway budget, undo, risk-tiers) is bundled in the package — no external skill-family dependency.\n  All write operations are audited to a local SQLite DB under ~/.veeam-aiops/ (relocatable via VEEAM_AIOPS_HOME).\n  Credentials: Each Veeam target's login password is stored ENCRYPTED in ~/.veeam-aiops/secrets.enc (Fernet/AES-128 + scrypt-derived key) — never plaintext on disk. Run 'veeam-aiops init' to onboard, or 'veeam-aiops secret set <target>' to add one. The store is unlocked by a master password from VEEAM_AIOPS_MASTER_PASSWORD (non-interactive/MCP/CI) or an interactive prompt (CLI on a TTY). A legacy plaintext env var VEEAM_<TARGET_NAME_UPPER>_PASSWORD is still honoured as a fallback with a deprecation warning (migrate with 'veeam-aiops secret migrate'). The password is exchanged for a short-lived OAuth2 bearer token at connect time and held only in memory; passwords/tokens are never logged or echoed.\n  Destructive operations (job stop, session stop, restore start) require double confirmation at the CLI layer and support --dry-run. A dry_run MAY read (that is how it can tell you the call would be refused) but never writes, records no undo, and is audited like any other governed call; the CLI --dry-run routes through the same governed function as the MCP tool. All write tools pass through the @governed_tool decorator (budget guard + audit + risk-tier labelling). Reversible writes (job start/stop/retry, enable/disable) record an inverse undo descriptor; session stop and the VM restore are irreversible and record none.\n  Webhooks: none — no outbound network calls beyond the configured Veeam REST API endpoint.\n  SSL: verify_ssl defaults to true; disable only for self-signed lab certificates.\n  Transitive dependencies: httpx (HTTP client) and the MCP SDK. No post-install scripts or background services.\n---\n\n# Veeam AIops\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by Veeam Software.** \"Veeam\" is a trademark of its owner. Source code is publicly auditable at [github.com/AIops-tools/Veeam-AIops](https://github.com/AIops-tools/Veeam-AIops) under the MIT license.\n\nGoverned Veeam Backup & Replication operations — **27 MCP tools**, every one wrapped with the bundled `@governed_tool` harness: a local unified audit log under `~/.veeam-aiops/`, policy engine, token/runaway budget guard, undo-token recording, and descriptive risk tiers. Credentials are stored **encrypted** (`~/.veeam-aiops/secrets.enc`, Fernet + scrypt) — never plaintext on disk.\n\n> **Standalone**: the governance harness is bundled in the package (`veeam_aiops.governance`) — veeam-aiops has no external skill-family dependency. Coverage focuses on common Veeam operations and is not yet exhaustive.\n\n## What This Skill Does\n\n| Category | Tools | Count | Read or Write |\n|----------|-------|:-----:|:-------------:|\n| **Overview** | health overview | 1 | 1 read |\n| **Diagnostics / RCA** | job-failure triage, repository capacity | 2 | 2 read |\n| **Backup Jobs** | list, get, start, stop, retry, enable, disable | 7 | 2 read / 5 write |\n| **Restore** | list restore points (opt. per backup), start VM restore | 2 | 1 read / 1 write |\n| **Repositories** | list, get (detail), state (capacity) | 3 | 3 read |\n| **Backups** | list stored backups, list backup objects, per-VM storage usage, storage ranking | 4 | 4 read |\n| **Infrastructure** | managed servers, proxies | 2 | 2 read |\n| **Sessions** | list, get, log, stop (poll/cancel async progress) | 4 | 3 read / 1 write |\n\n## Quick Install\n\n```bash\nuv tool install veeam-aiops\nveeam-aiops init       # interactive wizard: connection + encrypted password\nveeam-aiops doctor\n```\n\nOr as an OpenClaw plugin, which installs this skill and its MCP server together:\n\n```bash\nopenclaw plugins install clawhub:@zw008/veeam-aiops\nopenclaw skills info veeam-aiops          # expect: Visible to model: yes\n```\n\nNeeds `uvx` on `PATH`: the MCP server is fetched with uv, pinned to this release.\n\n## When to Use This Skill\n\n- List/inspect Veeam backup jobs and their last result\n- Start or stop a backup job on demand\n- Enable or disable a job's schedule\n- List available restore points and start a VM restore\n- List backup repositories and stored backups\n- Report how much backup storage a VM consumes (showback/chargeback input) and which VMs cost the most to protect\n- Poll async sessions to follow job/restore progress\n\n**Do NOT use when** the target is not Veeam Backup & Replication (other backup products, hypervisor VM lifecycle, Kubernetes, or cloud providers are out of scope for this skill).\n\n## Related Skills — Skill Routing\n\n| If the user wants… | Use |\n|--------------------|-----|\n| Veeam backup jobs / restore / repositories | **veeam-aiops** (this skill) |\n| Hypervisor VM lifecycle (power, snapshot, migrate) | a hypervisor ops skill |\n| Container/cluster lifecycle | a cluster ops skill |\n\n## Common Workflows\n\n### Diagnose why last night's backups failed\n\n1. `veeam-aiops diagnose job-failures --since-hours 24` → worst-first table of Failed/Warning sessions, each with the categorized cause (repository full / source unreachable / credential-VSS / retry exhaustion) and the cited failing log line\n2. If a finding says **repository full**, confirm with `veeam-aiops diagnose repo-capacity` → the flagged repo's measured free% and free bytes\n3. Fix the root cause (extend/offload the repository, restore source connectivity, or repair guest credentials/VSS), then `veeam-aiops job retry <job_id>` to re-run only the failed objects\n4. `veeam-aiops session list` → `veeam-aiops session get <session_id>` to confirm the retry completes — do not tight-loop `session get` (the runaway budget guard will trip it)\n\n### Run a backup job and follow it to completion\n\n1. `veeam-aiops job list` → find the job id and confirm `lastResult`\n2. `veeam-aiops job start <job_id>` → starts the job (records an inverse `job_stop` undo descriptor)\n3. `veeam-aiops session list` → find the running session; `veeam-aiops session get <session_id>` → check `state` / `progressPercent`\n4. **Failure branch**: if `session get` shows the session `Failed`, inspect `result`, then re-run `job start` after fixing the cause — do not loop `session get` rapidly (the runaway budget guard will trip a tight poll loop).\n\n### Showback: how much backup storage does a VM consume?\n\n1. `veeam-aiops backup usage <vm-name>` → per backup (primary job and each backup copy): repository, restore points, stored / full / incremental bytes, shared bytes, job retention\n2. Read the caveats before quoting a number: files that hold **several** machines are reported as shared and never added to the VM's total; on block-clone repositories (ReFS / XFS fast clone) the stored total is an upper bound\n3. `veeam-aiops backup ranking --limit 20` → which machines consume the most backup storage, largest first; raise `--max-backups` if `backupsTruncated` is true. On a large estate scope it (`--backup <job name>` repeatable, `--repository <name>`) — a full scan can take tens of minutes; a SCOPED ranking is not an estate-wide one\n4. Apply your own storage price to the bytes — this tool reports consumption only. **Needs VBR 12.3 or later**; older servers get a clear refusal naming the minimum build.\n\n### Restore a VM from a restore point\n\n1. `veeam-aiops restore list-points` → identify the correct restore point id\n2. `veeam-aiops restore start --restore-point-id <id> --dry-run` → preview the exact API call **and the VM name + creation time** the id resolves to — never approve a restore from a GUID\n3. `veeam-aiops restore start --restore-point-id <id>` → double confirmation required; this is IRREVERSIBLE (overwrites/creates a VM) and records no undo token. Refused outright if the VM name matches the configured VBR host (an in-place overwrite of the backup server itself) — a name-based safety net, not a proof, so confirm the target yourself\n4. **Failure branch**: if `doctor` shows the VBR server unreachable or the password env var is missing, fix `~/.veeam-aiops/.env` (chmod 600) before retrying — the restore is never issued against an unauthenticated session.\n\n## Usage Mode\n\n| Scenario | Recommended | Why |\n|----------|:-----------:|-----|\n| Local/small models | **CLI** | fewer tokens than MCP |\n| Cloud models (Claude, GPT) | Either | MCP gives structured JSON I/O |\n| Automated pipelines | **MCP** | type-safe parameters, audited |\n\n## MCP Tools (27 — 19 read, 8 write)\n\n| Category | Tools | R/W |\n|----------|-------|:---:|\n| Overview | `overview` | Read |\n| Diagnostics / RCA | `job_failure_rca`, `repository_capacity_rca` | Read |\n| Backup Jobs | `job_list`, `job_get` | Read |\n| | `job_start`, `job_stop`, `job_retry`, `job_enable`, `job_disable` | Write |\n| Restore | `restore_list_points` | Read |\n| | `start_vm_restore` | Write |\n| Repositories | `repository_list`, `repository_get`, `repository_state` | Read |\n| Backups | `backup_list`, `backup_object_list`, `backup_object_storage_usage`, `backup_storage_ranking` | Read |\n| Infrastructure | `managed_server_list`, `proxy_list` | Read |\n| Sessions | `session_list`, `session_get`, `session_log` | Read |\n| | `session_stop` | Write |\n| Undo | `undo_list` | Read |\n| | `undo_apply` | Write |\n\n**Harness features that light up**: write tools with a clean inverse (`job_start`↔`job_stop`, `job_retry`→`job_stop`, `job_enable`↔`job_disable`) pass an `undo=` lambda so the harness records an inverse descriptor (with `_undo_id`) to the undo store. The irreversible `start_vm_restore` and `session_stop` declare no undo; `start_vm_restore` is tagged `risk_level=high`. All 27 tools are audit-logged under `~/.veeam-aiops/` and pass through the budget/runaway guard, each row carrying a descriptive risk tier. Veeam jobs/restores run as async sessions — poll with `session_get` / `session_log` instead of re-issuing (the runaway breaker backs this up). Start any triage with `overview` (jobs by last result, repos near full, running sessions), then drill in with `job_failure_rca` (categorizes failing sessions with cited error substrings) and `repository_capacity_rca` (cited free%).\n\n## CLI Quick Reference\n\n```bash\nveeam-aiops init                                      # onboarding wizard (encrypted password)\nveeam-aiops overview [--target <t>]                   # health summary\nveeam-aiops diagnose job-failures [--target <t>]      # RCA: triage failed job sessions\nveeam-aiops diagnose repo-capacity [--target <t>]     # RCA: repos low on free space\nveeam-aiops job list [--target <t>]\nveeam-aiops job get <job_id>\nveeam-aiops job start <job_id>\nveeam-aiops job stop <job_id> [--dry-run]              # double confirm\nveeam-aiops job retry <job_id>\nveeam-aiops job enable <job_id>\nveeam-aiops job disable <job_id>\nveeam-aiops restore list-points [--backup-id <id>] [--limit 100]\nveeam-aiops restore start --restore-point-id <id> [--dry-run]   # double confirm\nveeam-aiops repository list\nveeam-aiops repository get <repository_id>\nveeam-aiops repository state                           # capacity / free / used%\nveeam-aiops session list [--limit 100]\nveeam-aiops session get <session_id>\nveeam-aiops session log <session_id>\nveeam-aiops session stop <session_id> [--dry-run]     # double confirm\nveeam-aiops backup list\nveeam-aiops backup objects <backup_id>\nveeam-aiops infra servers\nveeam-aiops infra proxies\nveeam-aiops secret set <target>                        # store password encrypted\nveeam-aiops secret list                               # names only\nveeam-aiops secret migrate                            # import legacy plaintext .env\nveeam-aiops secret rotate-password\nveeam-aiops doctor\nveeam-aiops mcp                                        # start MCP server (stdio)\n```\n\nSee `references/cli-reference.md` for the full command list.\n\n## Troubleshooting\n\n### \"Config file not found\"\nRun `veeam-aiops init` to set up your first target (writes `~/.veeam-aiops/config.yaml` and stores the password encrypted).\n\n### \"No password for target '<name>'\"\nAdd it to the encrypted store: `veeam-aiops secret set <name>` (prompts hidden), or run `veeam-aiops init`. For non-interactive use (MCP/CI), also export `VEEAM_AIOPS_MASTER_PASSWORD` so the store can be unlocked without a prompt.\n\n### \"Master password not set\" / \"Wrong master password\"\nThe encrypted store `~/.veeam-aiops/secrets.enc` is unlocked by `VEEAM_AIOPS_MASTER_PASSWORD` (or an interactive prompt). If you forgot it, delete `secrets.enc` and re-run `veeam-aiops init`. Rotate it with `veeam-aiops secret rotate-password`.\n\n### \"Authentication/authorization failed (401)\"\nThe username/password is wrong, or the account lacks a Veeam role. Veeam usernames are typically `DOMAIN\\\\user` or a local Windows account on the VBR server. Confirm the account can log in to the Veeam console.\n\n### \"Could not reach Veeam server … check the host/port\"\nThe default REST API port is 9419 — confirm the Veeam Backup & Replication REST API service is running and the port is open. For self-signed certificates set `verify_ssl: false` on the target (lab only).\n\n### \"Resource not found (404)\"\nThe job/session/restore-point id is stale. List the parent collection first (`job list`, `session list`, `restore list-points`) to get a current id.\n\n## Governance & Safety\n\nThe skill delivers reads and writes and records them; it does **not** decide\nwhether a write is permitted. That is your agent's judgement, or the permission\nof the Veeam account you connect it with (a read-only or restricted role on the\nVBR server — writes then fail at the server). There is no read-only switch,\npolicy file, or approval gate.\n\n- Credentials stored **encrypted** in `~/.veeam-aiops/secrets.enc` (Fernet/AES-128 + scrypt key derivation; chmod 600) — never plaintext on disk; the master password is never stored, only a per-store salt + ciphertext\n- **Audit is the guarantee, and it is not bypassable.** Every operation — MCP and CLI alike — is logged to `~/.veeam-aiops/audit.db` (relocatable via `VEEAM_AIOPS_HOME`): params (secrets redacted), result, status, duration, and the risk tier. The CLI writes the same row the MCP path does.\n- `VEEAM_AUDIT_APPROVED_BY` / `VEEAM_AUDIT_RATIONALE` are optional annotations recorded on the audit row (who/why); they are never required and never block.\n- **Runaway guard** — a safety backstop, not authorization: cumulative tool calls and wall-time are capped, and the same call looped in a tight session-poll/retry window trips a circuit breaker.\n- Writes support `--dry-run` / `dry_run=True` and double confirmation at the CLI; CLI writes execute through the same governed tools, so they are audited + undo-recorded.\n- Reversible writes (job start/stop/retry, enable/disable) record an inverse undo descriptor; the irreversible `start_vm_restore` and `session_stop` record none.\n\nThe harness is bundled in the package — no external dependency, no manual setup. See `references/setup-guide.md` for security details.\n\n## Contributing & feature requests\n\nCoverage is intentionally focused. **Missing a device, action, or feature you need?** Open an issue or pull request at [github.com/AIops-tools/Veeam-AIops](https://github.com/AIops-tools/Veeam-AIops/issues) — feature requests, contributions, and comments are all welcome.\n\n## License\n\nMIT — [github.com/AIops-tools/Veeam-AIops](https://github.com/AIops-tools/Veeam-AIops)\n\nFile v0.16.1:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"veeam-aiops\",\n  \"version\": \"0.16.1\",\n  \"publishedAt\": 1789453369149\n}\n\nFile v0.16.1:references/agent-guardrails.md\n\n# Agent guardrails — running veeam-aiops with a smaller / local model\n\nIf you drive these tools with a local model (Llama, Qwen, Mistral … via Goose,\nOllama, LM Studio, or any OpenAI-compatible runtime), you will get noticeably\nbetter results with a short system prompt. This page gives you one, and — more\nimportantly — tells you which guardrails you **no longer need to write**, because\nthe tool now enforces them itself.\n\nThe distinction matters. A guardrail in a prompt is a request. A guardrail in the\nharness is a guarantee. Anything below that we could move into the harness, we did.\n\n## Authorization is not this tool's job — decide it where it belongs\n\nWhether a write should happen is your decision, or the account's. The tool does\nnot gate it — there is no read-only switch and no approval prompt to configure.\nThe two right places to control read vs write:\n\n- **The account you connect with.** Give the Veeam account you connect with a\n  read-only or restricted role on the VBR server. A write then fails at the\n  server, which is the only place the permission actually lives — a revoked\n  permission cannot be argued around by a model, but a skill-side flag can.\n- **Your agent's system prompt.** If you want an observe-only session, tell the\n  model not to call the write tools (they are clearly tagged `[WRITE]`).\n\nWhat the tool *does* guarantee is that you can always see what happened:\n\n## What the tool enforces — do not waste prompt budget on these\n\n| You might be tempted to prompt | Why you don't need to |\n|---|---|\n| \"Don't invent a value when a field is missing\" | A field the VBR API did not return comes back as `null`, never as `\"\"`. A job with no `lastResult` yet, a session with no verdict, a proxy with no reported host — all report `null`, and only a genuinely empty upstream value comes back as `\"\"`. Absent and empty are distinguishable in the payload. |\n| \"Tell me if the output was cut off\" | The reads that can be too large to return whole — `restore_list_points`, `session_list`, `undo_list`, and `backup_storage_ranking` — return an envelope such as `{\"restorePoints\": [...], \"returned\": N, \"limit\": L, \"truncated\": true/false}` (the ranking also says `scoped` / `backupsTruncated` when it covers only a selection or a scanned subset), newest first where time matters. Truncation is measured (one extra row is fetched), not guessed from a length coincidence. Every other list read pages through the whole collection — the VBR server may cap a page at 200 items (Veeam's spec default from revision 1.3) — and refuses with an error rather than returning a partial list if the server stops short. |\n| \"Preserve the ordering / tell me what's most urgent\" | `job_failure_rca` and `repository_capacity_rca` findings carry an explicit 1-based `rank`, worst-first. Priority is in the payload, not implied by list position. |\n| \"Explain why you flagged that repository / job\" | Every finding carries the measured signal that tripped it — the session `result` and the matched error substring, or the free-space percentage against the threshold — plus a concrete `cause` and `action`. The heuristics are transparent, not a verdict. |\n| \"Confirm before anything destructive\" | `job_stop`, `session_stop` and `restore start` require a `--dry-run`-able preview plus double confirmation at the CLI; the MCP write tools take `dry_run=True`. `start_vm_restore` is tagged `high` risk. |\n| \"Remember how to put it back\" | Writes with a clean inverse (`job_start`/`job_stop`, `job_enable`/`job_disable`, `job_retry`) record an undo token — list them with `undo_list`, replay with `undo_apply`. The irreversible ones (`start_vm_restore`, `session_stop`) record none and say so. |\n| \"Log what you did\" | Every governed call is audited to `~/.veeam-aiops/audit.db` regardless of what the model says it did — and the CLI writes the same row the MCP path does, so there is no unaudited entry point. |\n| \"Don't get stuck retrying\" | The runaway guard trips a circuit breaker if the same call is hammered in a tight loop (e.g. re-issuing a job instead of polling its session) — a stuck agent is stopped rather than left to burn calls and time. |\n\n## What still needs a prompt\n\nThese are model-behaviour problems the harness cannot fix from the outside.\nCopy this into your agent's system prompt:\n\n```text\nYou operate a Veeam Backup & Replication environment through the veeam-aiops\nMCP tools.\n\nTOOL USE\n- Before answering any question about the current Veeam environment, you MUST\n  call a tool. Never answer from memory or assumption.\n- Actually invoke the tool. Do not describe the call you would make, and do not\n  emit an example JSON response in place of calling it.\n- If a tool call fails, report the real error verbatim. Never fill the gap with\n  a plausible-sounding answer.\n\nREADING RESULTS\n- Read the whole result before concluding. If a result contains a \"truncated\"\n  field that is true, say so and re-run with a higher limit instead of treating\n  the partial result as complete.\n- A null field means the VBR API did not return that value. Report it as \"not\n  available\" — never infer it. A session with a null result has not finished,\n  which is not the same as having succeeded.\n- Report values exactly as returned. Do not normalise, translate, or prettify\n  job status strings, session results (Success / Warning / Failed / None), or\n  identifiers.\n- When a diagnose result has findings, work in \"rank\" order and cite the\n  measured number in each finding's \"detail\".\n\nSCOPE\n- Separate observation from interpretation. State what the tools returned, then\n  any interpretation, clearly marked as such.\n- Do not assert a backup failure, a capacity problem, or a missed RPO unless a\n  tool result supports it.\n- Do not add generic advice that does not follow from the tool output.\n- Do not confuse a job id with a session id, a session id with a restore point\n  id, or a backup id with the repository it lives on. They are different\n  objects with different tools.\n```\n\n## Recommended setup for a local model\n\nStart with a connection that *cannot* write, verify, and widen the account's\npermission only when you trust the setup — a restore or a stopped job on the\nwrong target is not something you want a smaller model reaching for on day one:\n\n```bash\n# e.g. connect with a Veeam account that has a read-only or restricted role on\n# the VBR server. Then:\nveeam-aiops doctor\n```\n\nOptionally annotate the audit trail with who is operating and why — recorded on\nevery row, never required:\n\n```bash\nexport VEEAM_AUDIT_APPROVED_BY=\"your.name@example.com\"\nexport VEEAM_AUDIT_RATIONALE=\"scheduled maintenance window 2026-07-20\"\n```\n\n## Veeam-specific notes\n\nThese are the places a smaller model most often goes wrong against a VBR server,\nand what to do about them:\n\n- **Jobs and restores are asynchronous.** `job_start`, `job_retry` and\n  `start_vm_restore` return immediately; the work happens in a *session*. Progress\n  belongs to `session_get`, not to the job. Tell the model to start once and poll\n  the session — the runaway budget guard will trip on a re-issue loop, but a\n  wasted trip is still a wasted trip.\n- **Four id namespaces look alike.** Job ids, session ids, backup ids and restore\n  point ids are all opaque strings. `backup_object_list` takes a *backup* id;\n  `restore_list_points` filters by a *backup* id and returns *restore point* ids;\n  `start_vm_restore` takes a *restore point* id. Models routinely pass the wrong\n  one — prefer chaining the tools (`backup_list` → `restore_list_points`) over\n  letting the model reconstruct an id.\n- **\"Warning\" is a real failure state.** A Veeam session result of `Warning` is\n  flagged by `job_failure_rca` alongside `Failed`. A model that treats Warning as\n  success will report a healthy backup estate that isn't one.\n- **A disabled job is not a failing job.** `job_list` reports `isDisabled`\n  separately from `lastResult`; a disabled job simply has not run.\n- **`start_vm_restore` cannot be undone.** It overwrites or creates a VM and\n  records no undo token. It is `high` risk deliberately. It is also a documented\n  skeleton: the exact endpoint and payload differ per\n  restore type (instant recovery vs full restore vs restore-to-new-location) and\n  per Veeam version, so validate it against your environment before trusting it.\n- **Always read the `dry_run` preview before approving a restore.** It names the\n  VM and creation time behind the restore-point GUID. The tool refuses a restore\n  whose VM name matches the configured VBR host — an in-place overwrite of the\n  backup server itself — but that check compares a display name to a hostname, so\n  **it will miss a VBR server named anything else**. Separately, when the\n  restore point cannot be read at all the restore is REFUSED, because nothing\n  can then say which machine would be overwritten; pass\n  `acknowledge_unresolved=True` only after confirming the target in the Veeam\n  console.\n\n## If your model still struggles\n\nSome behaviours are model-capacity limits rather than prompt problems:\n\n- **Multi-tool workflows time out or drift.** Prefer `overview` and the\n  `*_rca` diagnose tools — they do the multi-step correlation inside one call, so\n  the model does not have to chain reads and keep job/session ids straight.\n- **The model ignores later tool results in a long context.** Ask narrower\n  questions; use `job_get` / `session_get` on one object rather than pulling the\n  whole session list and reasoning over it.\n- **The model describes calls instead of making them.** This is usually a\n  runtime/tool-calling-format mismatch, not a prompt problem — check that your\n  client advertises the tools in the format your model was trained on.\n\nFeedback on running this with a specific local model is genuinely useful —\nopen an issue at\n[github.com/AIops-tools/Veeam-AIops](https://github.com/AIops-tools/Veeam-AIops/issues)\nwith the model, runtime, and what went wrong.\n\nFile v0.16.1:references/capabilities.md\n\n# veeam-aiops capabilities\n\n27 MCP tools (19 read, 8 write), each wrapped with the bundled `@governed_tool`\nharness. Typical response token estimates assume a small/medium environment.\n\n## Overview (1 — read)\n\n| Tool | R/W | Risk | Typical response tokens |\n|------|:---:|:----:|:----------------------:|\n| `overview` | R | low | ~150 |\n\nFan-out health summary: jobs grouped by last result, repositories at/above 85%\nused, and currently-running sessions. Call this first to triage an environment.\n\n## Diagnostics / RCA (2 — read)\n\n| Tool | R/W | Risk | Typical response tokens |\n|------|:---:|:----:|:----------------------:|\n| `job_failure_rca` | R | low | ~200–600 |\n| `repository_capacity_rca` | R | low | ~150 |\n\n`job_failure_rca` scans the newest `limit` sessions (default 100, newest first by\n`creationTime`; `sessionsTruncated` says older ones exist) — pass `since_hours=24`\nto make the window \"the last day\" instead — flags every Failed/Warning run, and\ncategorizes the likely cause (repository full, source/guest unreachable,\ncredential/VSS failure, retry exhaustion) from the failing log records — each\nfinding cites the session result + matched error substring, worst-first.\n`repository_capacity_rca` flags repositories under the free-space thresholds\n(<15% warn, <10% critical), citing the measured free% and free bytes.\n\n## Backup Jobs (7 — 2 read, 5 write)\n\n| Tool | R/W | Risk | Undo | Typical response tokens |\n|------|:---:|:----:|------|:----------------------:|\n| `job_list` | R | low | — | 150–600 (depends on job count) |\n| `job_get` | R | low | — | ~120 |\n| `job_start` | W | medium | `job_stop` | ~50 |\n| `job_stop` | W | medium | `job_start` | ~50 |\n| `job_retry` | W | medium | `job_stop` | ~50 |\n| `job_enable` | W | medium | `job_disable` | ~40 |\n| `job_disable` | W | medium | `job_enable` | ~40 |\n\nREST endpoints: `GET /api/v1/jobs`, `GET /api/v1/jobs/{id}`,\n`POST /api/v1/jobs/{id}/{start|stop|retry|enable|disable}`. The write tools\ncapture the job's prior status/lastResult for context.\n\n## Restore (2 — 1 read, 1 write)\n\n| Tool | R/W | Risk | Undo | Typical response tokens |\n|------|:---:|:----:|------|:----------------------:|\n| `restore_list_points` | R | low | — | 150–800 |\n| `start_vm_restore` | W | high | **none — irreversible** | ~40 |\n\n`restore_list_points` returns the newest `limit` points (default 100, max 1000) as\n`{\"restorePoints\", \"returned\", \"limit\", \"truncated\", \"order\"}` — an estate's restore\npoints are far too many to return whole. With `backup_id`, a point from another\nbackup coming back means the server ignored the filter, and that is refused.\n\nREST endpoints: `GET /api/v1/restorePoints` (`orderColumn=CreationTime&orderAsc=false`,\noptional `backupIdFilter`),\n`GET /api/v1/restorePoints/{id}` (to name what a restore would overwrite),\n`POST /api/v1/restore/vm`. `start_vm_restore` is a documented skeleton: the\nexact restore endpoint and payload vary by restore type and Veeam version.\n\nThe payload carries **no target mapping**, so it is a restore-to-original — an\nin-place overwrite. Two consequences worth knowing before you call it:\n\n- `dry_run=True` resolves the opaque restore-point id to the **VM name and\n  creation time** it would overwrite.\n- **An unreadable restore point is refused**, by the preview and the real call\n  alike: with no target mapping this is a restore-to-original with no undo, and\n  a tool that cannot name the machine it is about to overwrite has not given\n  anyone something to approve. `acknowledge_unresolved=True`\n  (CLI `--acknowledge-unresolved`) proceeds anyway, for when the target has been\n  confirmed in the Veeam console; `resolved: false` then says the target is\n  unknown. Refusing errs recoverably — restore from the console — while\n  proceeding errs onto a machine nobody could name.\n- It **refuses** when that VM name matches the configured VBR host — **on the\n  dry-run as well as the real call**, with identical behaviour. A\n  preview that returns green for a call that will then be refused is a preview\n  reporting the wrong outcome. Veeam's own\n  guidance is to back up the VBR server itself, so its restore point sits in the\n  same list as every other one with nothing marking it as special. **This check\n  is a safety net, not a proof**: a VM display name is not a hostname, so a VBR\n  server whose VM is named `Backup Server 01` is not caught. An unknown name is\n  still never read as \"it is the VBR server\" — that judgement stays open — but\n  the restore itself is now refused in that case by the separate unreadable-\n  target guard above.\n\n### Dry-run semantics (line-wide)\n\n`dry_run=True` returns `{\"dryRun\": true, \"would...\": {...}}`. A dry-run **may read** —\nresolving ids and evaluating guards is exactly what lets it answer \"would this be\nrefused?\" — but it **never writes** and records **no undo**. It runs through\n`@governed_tool` like any other call, so it is audited and it can be refused. The CLI\n`--dry-run` routes through the same governed function, so both entry points behave\nidentically.\n\n## Repositories (3 — read)\n\n| Tool | R/W | Risk | Typical response tokens |\n|------|:---:|:----:|:----------------------:|\n| `repository_list` | R | low | 100–400 |\n| `repository_get` | R | low | ~120 |\n| `repository_state` | R | low | 100–400 |\n\nREST endpoints: `GET /api/v1/backupInfrastructure/repositories`,\n`GET /api/v1/backupInfrastructure/repositories/{id}`,\n`GET /api/v1/backupInfrastructure/repositories/states` (capacity / free / used,\nplus a computed used%). `repository_get` merges the static record with its state\nrow when available.\n\n## Backups (4 — read)\n\n| Tool | R/W | Risk | Typical response tokens |\n|------|:---:|:----:|:----------------------:|\n| `backup_list` | R | low | 150–800 |\n| `backup_object_list` | R | low | 150–800 |\n| `backup_object_storage_usage` | R | low | 400–1500 |\n| `backup_storage_ranking` | R | low | 300–2000 |\n\nREST endpoints: `GET /api/v1/backups`, `GET /api/v1/backups/{id}/objects`.\n\n### Backup storage footprint (`backup_object_storage_usage`, `backup_storage_ranking`)\n\nSums Veeam's own per-file accounting from `GET /api/v1/backups/{id}/backupFiles`:\n`backupSize` (on disk after compression and deduplication) and `dataSize`\n(before). Other reads: `GET /api/v1/serverInfo` (build → REST revision),\n`GET /api/v1/backupObjects?nameFilter=`, `GET /api/v1/restorePoints?backupObjectIdFilter=`,\n`GET /api/v1/backups/{id}`, `GET /api/v1/jobs/{id}` (retention), `GET /api/v1/backupObjects/{id}`\n(ranking: owners a backup does not list). Every collection\nis paged to completion — the server caps a page at 200 by default.\n\n- **Needs VBR 12.3+.** `backupFiles` first appears in REST revision 1.2-rev0\n  (VBR 12.3.0.310, per Veeam's published revision table). The size reads send\n  the newest revision the server's build serves; the rest of the tool keeps its\n  pinned 1.1-rev1. Older builds get a refusal that names the minimum build.\n- **Works with a read-only Backup Viewer account.** `/api/v1/serverInfo` (the\n  build) is Backup Administrator only from revision 1.1-rev2 on; without it the\n  tools offer each revision newest-first on a one-item `GET /api/v1/backups` and\n  use the first the server accepts (`apiRevision.basis: \"probe\"`; refused\n  revisions are listed in `apiRevision.probeRefusals`).\n- **Shared files are never charged to one machine.** Per-job backup chains keep\n  several VMs in one file; revision 1.3-rev2 (VBR 13.1+) lists every owner, and\n  such files land in `sharedStoredBytes`, outside `storedBytes`. Older revisions\n  name one owner per file, so sharing is decided by the restore points the file\n  itself lists (`restorePointIds`): any point that is not this machine's makes\n  it shared, whatever owner it names. A file whose ownership the server states\n  inconsistently (no owner and no point list, or a single other owner with only\n  this machine's points) goes to `unattributedStoredBytes` — never charged, and\n  visible if owner ids ever turn out not to match backup-object ids. The ranking\n  reads no restore points and charges each file to its listed owner.\n- **The ranking separates two kinds of uncharged file.** A file naming no owner\n  at all is an ordinary per-job chain file and lands in `ownerlessStoredBytes`.\n  A file naming an owner id that its own backup's object listing does not\n  contain lands in `unmatchedOwnerStoredBytes` and raises a caveat — that is the\n  signal that backup-file owner ids and backup-object ids are different\n  namespaces on this build, which is the one assumption the Veeam spec never\n  pins down. `unresolvedStoredBytes` remains the sum of both. Judge a ranking's\n  fitness for chargeback on `unmatchedOwnerFiles`, never on the sum: a healthy\n  estate can carry a large ownerless total.\n- **A partial ranking says so.** `backupsScanned`/`backupsTotal`/\n  `backupsTruncated` are in the payload and the CLI prints an explicit PARTIAL\n  line, because the default `max_backups` (100) is below some estates' backup\n  count and widening a scan can put a previously unseen object at rank 1.\n- **Scope the scan instead of waiting for the whole estate.** A complete\n  ranking of a 123-backup VBR 13.1 estate took 21 minutes with 4 s of local\n  CPU — the time is the server. `backups` (ids or names; a backup is named\n  after its job) and `repository` (id or name) select what is read; the\n  filter is applied locally because `/backups` offers no repository filter;\n  names come from both plain and scale-out repositories.\n  A scope that matches nothing is an error, not an empty ranking. The payload\n  carries `scoped`, `scope` and `backupsInScope`; a scoped ranking adds a\n  caveat and the CLI prints SCOPED, because it ranks the selection, not the\n  environment. `backupsTruncated` is measured against the scope.\n- **Backups can be read in parallel** (`concurrency`, 1–8, **default 1**).\n  Opt-in because it is unmeasured on a real VBR: the server is already the\n  bottleneck, and parallel reads can push a slow `backupFiles` read past the\n  timeout — lower it if backups time out. Results are folded in scan order, so\n  the payload is identical at any concurrency; a hard error in one read returns\n  at once instead of waiting out the others. Token renewal is serialised, so\n  parallel reads that all meet an expired token log in once. The CLI reports\n  progress on stderr, so `--json` stays parseable.\n- **An owner missing from its backup's listing is looked up** once per id via\n  `GET /api/v1/backupObjects/{id}` (at most 200 ids; the rest are counted in\n  `ownerLookupsSkipped`; the budget goes to the ids carrying the most bytes, and\n  skipped ids get their own caveat rather than the namespace one, since they\n  were never checked). Found → the id is a backup-object id (typically a\n  machine moved to another job or removed from this one), its bytes are\n  charged to that machine and also counted in `recoveredOwnerStoredBytes`.\n  404 or a failed lookup → the bytes stay in `unmatchedOwnerStoredBytes` and\n  the namespace caveat stands. `unmatchedOwners` lists every id with its\n  `resolution` (`otherBackup`, `sameBackup`, `resolved`, `notFound`,\n  `lookupFailed`, `skipped`), largest first, at most 50 entries\n  (`unmatchedOwnersTotal`, `unmatchedOwnersTruncated`). A backup the server\n  lists without an id is reported in `unreadableBackups`, not silently skipped.\n- **One unreadable backup does not blank the result**: it is listed in\n  `unreadableBackups` (with the error) and left out of every total. An entry\n  with `timedOut: true` adds a caveat naming the fix — raise the target's\n  `timeout` in config.yaml (the same estate needed 300 s for `/backupFiles`\n  where the default is 30 s) — since retrying at the same budget cannot help.\n- **The restore-point filter is checked, not trusted.** A query for a random\n  object id must come back empty (`restorePointFilter: \"honoured\"`); then points\n  under a machine's old name are kept (`restorePointNamesSeen`). If the server\n  ignores the filter — or the check itself fails — points are matched by name,\n  the others are counted in `restorePointsSetAside`, and a caveat says so; if\n  two same-named machines then get the same points, totals are withheld and each\n  machine is marked `attributable: false`.\n- **Full vs incremental** comes from each restore point's `type` and the\n  `backupFileId` it lives in; the `.vbk`/`.vib`/`.vrb` extension is a fallback,\n  and `kindBasis` counts which rule classified each file.\n- **Missing is not zero**: files without a size are counted in `unsizedFiles`\n  and left out of the sums. `approxSourceBytes` is null before revision 1.3-rev2.\n- **Block cloning**: on ReFS / XFS fast-clone repositories synthetic fulls share\n  blocks, so summed file sizes can exceed physical consumption — an upper bound.\n- **Same name, different machines** (two vCenters) are kept apart by identity\n  (`path`, then `objectId` / BIOS UUID) and a caveat is added; the ranking merges\n  one machine across backups by the same identity. Where the revision exposes no\n  inventory id (Hyper-V and agents before 1.3-rev2) identity falls back to name,\n  with a caveat.\n- **Paging checks the server**: `skip` advances by what was actually returned,\n  items are de-duplicated by id, and a server that stops short of its own total\n  or repeats a page is refused rather than billed partially or twice.\n- `changeRate` is mean incremental `dataSize` ÷ latest full `dataSize`, per\n  increment (not per day).\n- No pricing: storage cost models are organisation-specific.\n\n## Infrastructure (2 — read)\n\n| Tool | R/W | Risk | Typical response tokens |\n|------|:---:|:----:|:----------------------:|\n| `managed_server_list` | R | low | 150–600 |\n| `proxy_list` | R | low | 150–600 |\n\nREST endpoints: `GET /api/v1/backupInfrastructure/managedServers`,\n`GET /api/v1/backupInfrastructure/proxies`. Read-only inventory of where jobs\nrun and what moves the data.\n\n## Sessions (4 — 3 read, 1 write)\n\n| Tool | R/W | Risk | Undo | Typical response tokens |\n|------|:---:|:----:|------|:----------------------:|\n| `session_list` | R | low | — | 150–800 |\n| `session_get` | R | low | — | ~120 |\n| `session_log` | R | low | — | 150–800 |\n| `session_stop` | W | medium | **none** | ~40 |\n\nREST endpoints: `GET /api/v1/sessions`, `GET /api/v1/sessions/{id}`,\n`GET /api/v1/sessions/{id}/logs`, `POST /api/v1/sessions/{id}/stop`. Sessions\nare how Veeam exposes async job/restore progress — poll these instead of\nre-issuing the originating operation; read `session_log` to see *why* one failed —\neach record carries `title`, `description` (the error detail), `status`,\n`startTime` and `updateTime`.\n`session_list` returns the newest `limit` sessions (default 100, max 1000) as\n`{\"sessions\", \"returned\", \"limit\", \"truncated\", \"order\"}`, sorted by the server\n(`orderColumn=CreationTime&orderAsc=false`), so \"recent\" is explicit;\n`since_hours` narrows it to sessions created in the last N hours.\n`overview` does **not** derive \"running\" from that window: it queries each\nunfinished state (`stateFilter`: Starting, Working, Stopping, Pausing, Resuming,\nPostprocessing, WaitingTape, WaitingRepository, WaitingSlot), so a job started\ndays ago is still reported; a refused state lands in `stateQueryErrors`.\n\n### List reads and paging\n\nThe VBR REST API pages its collections; Veeam's spec gives `limit` a default of\n200 from revision 1.3-rev0 (the pinned 1.1-rev1 documents no default). Inventory reads (`backup_list`,\n`backup_object_list`, `job_list`, `repository_list`, `repository_state`,\n`managed_server_list`, `proxy_list`) page to the end; `overview` and\n`repository_capacity_rca` therefore see every repository. The pager advances by\nwhat the server actually returned, de-duplicates by id, and raises instead of\nreturning a partial list if the server stops short or repeats a page.\n`backup_object_list` sends no paging parameters on its first request (the pinned\nrevision 1.1-rev1 declares none for that endpoint) and pages only if the server's\npagination block shows more.\n\n## Undo (2 — 1 read, 1 write)\n\n| Tool | R/W | Risk | Undo | Typical response tokens |\n|------|:---:|:----:|------|:----------------------:|\n| `undo_list` | R | low | — | ~100–400 |\n| `undo_apply` | W | medium | **none — single-use** | ~60 |\n\nGeneric governance tools provided by the bundled harness, not the Veeam REST\nAPI. `undo_list` lists the recorded reversible writes whose undo tokens have not\nyet been applied. `undo_apply` executes a recorded inverse for one token — it is\nitself governed (audited and budget-checked), single-use (a token\ncannot be replayed), and supports `dry_run` to preview the inverse first.\n\n## Harness behavior\n\n- **Encrypted credentials**: passwords are stored in `~/.veeam-aiops/secrets.enc`\n  (Fernet + scrypt), unlocked by `VEEAM_AIOPS_MASTER_PASSWORD` or a prompt —\n  never plaintext on disk.\n- **Audit**: all 27 tools log to `~/.veeam-aiops/audit.db`.\n- **Undo store**: the five reversible job writes record an inverse descriptor\n  (`_undo_id` on the result); `session_stop` and the high-risk restore record none.\n- **Budget/runaway guard**: caps cumulative calls + wall-time and trips tight\n  session-poll loops.\n- **Risk tier**: a descriptive label on each audit row derived from `risk_level`;\n  it gates nothing. `VEEAM_AUDIT_APPROVED_BY` / `VEEAM_AUDIT_RATIONALE` are\n  optional annotations recorded on the audit row, never required.\n- **Sanitize**: all API-returned text is truncated + control-char stripped.\n\nFile v0.16.1:references/cli-reference.md\n\n# veeam-aiops CLI reference\n\nGlobal options on most commands: `--target / -t <name>` selects a configured\ntarget (default: first target in `config.yaml`).\n\n## Onboarding & secrets\n\n```bash\nveeam-aiops init                           # interactive wizard: connection + encrypted password\nveeam-aiops secret set <target>            # store/replace a password (prompts hidden)\nveeam-aiops secret list                    # names only; values never shown\nveeam-aiops secret rm <target>             # delete a stored password\nveeam-aiops secret migrate                 # import a legacy plaintext .env into the encrypted store\nveeam-aiops secret rotate-password         # re-encrypt the store under a new master password\n```\n\n## Overview\n\n```bash\nveeam-aiops overview                       # jobs by last result, repos near full, running sessions\n```\n\n## Backup jobs\n\n```bash\nveeam-aiops job list                       # id, name, type, status, lastResult\nveeam-aiops job get <job_id>               # detail for one job (incl. schedule)\nveeam-aiops job start <job_id>             # start a backup job (async session)\nveeam-aiops job stop <job_id> [--dry-run]  # stop a running job — double confirm\nveeam-aiops job retry <job_id>             # retry failed objects (async session)\nveeam-aiops job enable <job_id>            # enable the job schedule\nveeam-aiops job disable <job_id>           # disable the job schedule\n```\n\n## Restore\n\n```bash\nveeam-aiops restore list-points [--backup-id <id>] [--limit 100]  # newest restore points first\nveeam-aiops restore start --restore-point-id <id> [--dry-run]\n                                           # IRREVERSIBLE — double confirm\n```\n\n## Repositories\n\n```bash\nveeam-aiops repository list                # id, name, type, path\nveeam-aiops repository get <repo_id>       # detail incl. capacity/free/used\nveeam-aiops repository state               # capacity summary for all repos (used%)\n```\n\n## Backups\n\n```bash\nveeam-aiops backup list                    # stored backups: id, name, type, time\nveeam-aiops backup objects <backup_id>     # protected objects inside a backup\nveeam-aiops backup usage <name> [--json]   # backup storage one VM consumes, per backup (VBR 12.3+)\nveeam-aiops backup ranking [--limit 20] [--max-backups 100] [--backup <id|name> ...] \\\n    [--repository <id|name>] [--concurrency 1] [--json]  # largest consumers first; progress on stderr\n```\n\n## Infrastructure\n\n```bash\nveeam-aiops infra servers                  # managed servers: id, name, type\nveeam-aiops infra proxies                  # backup proxies: id, name, type, server\n```\n\n## Sessions (async progress)\n\n```bash\nveeam-aiops session list [--limit 100]     # newest sessions first: state, result\nveeam-aiops session get <session_id>       # poll one session (progressPercent)\nveeam-aiops session log <session_id>       # log records (events) of a session\nveeam-aiops session stop <session_id> [--dry-run]   # cancel — double confirm\n```\n\n## Diagnostics / RCA (read-only)\n\n```bash\nveeam-aiops diagnose job-failures [--limit 100] [--since-hours 24]  # triage recent failures; categorize cause\nveeam-aiops diagnose repo-capacity         # flag repositories low on free space (<15% / <10%)\n```\n\nBoth render worst-first findings, each citing the measured signal (session\nresult + matched error substring, or free% / free bytes) that tripped it.\n\n## Doctor & MCP\n\n```bash\nveeam-aiops doctor [--skip-auth]           # config + encrypted store + connectivity check\nveeam-aiops mcp                            # start the MCP server (stdio transport)\n```\n\n## Notes\n\n- `job start`, `job retry`, and `restore start` kick off **async sessions**.\n  Follow progress with `session list` / `session get` / `session log`, not by\n  re-issuing the command.\n- Destructive commands (`job stop`, `session stop`, `restore start`) require two\n  confirmations and accept `--dry-run` to preview the exact API call.\n- Credentials live in the encrypted store (`secrets.enc`); set them with\n  `veeam-aiops init` or `veeam-aiops secret set`. Export\n  `VEEAM_AIOPS_MASTER_PASSWORD` for non-interactive unlock.\n\nFile v0.16.1:references/setup-guide.md\n\n# veeam-aiops setup guide\n\n## Install\n\n```bash\nuv tool install veeam-aiops\n# or: pipx install veeam-aiops\n```\n\n## Configure (recommended: the wizard)\n\n```bash\nveeam-aiops init            # collects connection details + an encrypted password\nveeam-aiops doctor          # verifies config, encrypted store, connectivity\n```\n\n`init` writes `~/.veeam-aiops/config.yaml` (no secrets) and stores the login\npassword **encrypted** in `~/.veeam-aiops/secrets.enc` (Fernet + scrypt; chmod\n600). It prompts for a *master password* that unlocks the store; set it via\n`VEEAM_AIOPS_MASTER_PASSWORD` for non-interactive (MCP/CI) use.\n\nExample `~/.veeam-aiops/config.yaml`:\n\n```yaml\ntargets:\n  - name: vbr-lab\n    host: 10.0.0.20\n    username: \"DOMAIN\\\\backup-admin\"   # or a local account on the VBR server\n    port: 9419                          # Veeam REST API port (default)\n    verify_ssl: false                   # self-signed lab certs only; true in prod\n```\n\n### Manage credentials manually\n\n```bash\nveeam-aiops secret set vbr-lab         # prompts hidden for the password\nveeam-aiops secret list                # names only; values never shown\nveeam-aiops secret rotate-password     # re-encrypt under a new master password\nveeam-aiops secret migrate             # import a legacy plaintext .env, then archives it\n```\n\nSecret names map to target names. A legacy plaintext env var\n`VEEAM_<TARGET_NAME_UPPER>_PASSWORD` is still honoured as a fallback (with a\ndeprecation warning) — `secret migrate` imports it into the encrypted store.\n\n## Use as an MCP server\n\n```jsonc\n{\n  \"command\": \"veeam-aiops\",\n  \"args\": [\"mcp\"],\n  \"env\": {\n    \"VEEAM_AIOPS_CONFIG\": \"~/.veeam-aiops/config.yaml\",\n    \"VEEAM_AIOPS_MASTER_PASSWORD\": \"your-master-password\"\n  }\n}\n```\n\n`VEEAM_AIOPS_MASTER_PASSWORD` lets the server unlock `secrets.enc` without an\ninteractive prompt.\n\nUsing the `veeam-aiops mcp` subcommand (rather than `uvx --from`) means the MCP\nclient launches the already-installed entry point and does not re-resolve the\npackage over the network at startup.\n\n## Security\n\n> **Disclaimer**: Community-maintained project, **not affiliated with, endorsed\n> by, or sponsored by Veeam Software**. MIT licensed. See `SECURITY.md`.\n\n- **Credentials**: stored **encrypted** in `~/.veeam-aiops/secrets.enc`\n  (Fernet/AES-128 + scrypt-derived key, chmod 600) — never plaintext on disk.\n  The master password is never stored (only a per-store salt + ciphertext) and\n  comes from `VEEAM_AIOPS_MASTER_PASSWORD` or an interactive prompt. The login\n  password is exchanged for a short-lived OAuth2 bearer token at connect time\n  and kept only in memory.\n- **Audit**: every operation logged to a local SQLite DB under\n  `~/.veeam-aiops/` (relocate with `VEEAM_AIOPS_HOME`).\n- **Budget guard**: cap calls/wall-time with `VEEAM_MAX_TOOL_CALLS` /\n  `VEEAM_MAX_TOOL_SECONDS`; a runaway session-poll/retry loop trips automatically.\n- **Risk tier**: a descriptive label recorded on each audit row (derived from\n  `risk_level`); it gates nothing. `VEEAM_AUDIT_APPROVED_BY` /\n  `VEEAM_AUDIT_RATIONALE` are optional annotations recorded alongside it.\n- **Destructive ops**: `job stop`, `session stop`, and `restore start` require\n  double confirmation + support `--dry-run` at the CLI.\n- **TLS**: `verify_ssl` defaults true; disable only for self-signed labs.\n- **No webhooks / telemetry / background services.**\n\n## Least privilege\n\nCreate a dedicated Veeam Backup & Replication user with only the role your\nworkflows need (e.g. a restricted backup-operator role) rather than a full\nadministrator account.\n\nFile v0.16.1:skill-card.md\n\n## Description:\n\nVeeam AIops helps agents operate Veeam Backup & Replication through governed CLI and MCP workflows for health checks, diagnostics, job control, repository and backup inventory, restore point listing, VM restore starts, and session progress.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[zw008](https://clawhub.ai/user/zw008)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nBackup administrators, SREs, and operations engineers use this skill to inspect and operate Veeam Backup & Replication environments from an agent. It supports read-only health and RCA workflows as well as governed job, restore, session, and undo operations.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill exposes high-impact write and restore actions without an enforced read-only or approval gate for agent or MCP use.\n\nMitigation: Use a dedicated least-privilege Veeam account, preferably read-only for diagnostics, and expose write tools only when the operator accepts the risks of job stops, schedule changes, session cancellation, and irreversible VM restore actions.\n\nRisk: The master password can be placed in MCP client configuration for non-interactive use, and legacy plaintext .env secrets are still honored as a fallback.\n\nMitigation: Avoid plaintext master-password storage where possible, migrate legacy .env secrets into the encrypted store, and restrict access to local configuration files.\n\nRisk: Restore and session cancellation workflows can affect live backup operations, and VM restore actions may be irreversible.\n\nMitigation: Use dry-run previews, confirm the resolved target before restore actions, and validate write operations in the intended Veeam environment before relying on autonomous execution.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/zw008/skills/veeam-aiops)\n- [Project homepage](https://github.com/AIops-tools/Veeam-AIops)\n- [Capabilities reference](references/capabilities.md)\n- [CLI reference](references/cli-reference.md)\n- [Setup guide](references/setup-guide.md)\n- [Agent guardrails](references/agent-guardrails.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with inline shell commands and JSON-style MCP or tool outputs]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Some list, session, restore point, and ranking outputs include truncation, scope, or ordering indicators that the agent should preserve when reporting results.]\n\n## Skill Version(s):\n\n0.16.1 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v0.16.0: 7 files, 24404 bytes\n\nFiles: references/agent-guardrails.md (9982b), references/capabilities.md (17524b), references/cli-reference.md (4109b), references/setup-guide.md (3570b), skill-card.md (2899b), SKILL.md (17247b), _meta.json (131b)\n\nFile v0.16.0:SKILL.md\n\n---\nname: veeam-aiops\nslug: veeam-aiops\ndisplayName: \"Veeam AIops\"\nsummary: \"Governed Veeam Backup & Replication ops — 27 MCP tools with audit, budget, undo guards.\"\nlicense: MIT\nhomepage: https://github.com/AIops-tools/Veeam-AIops\ntags: [aiops, mcp, governance, veeam]\ndescription: >\n  Use this skill whenever the user needs to operate Veeam Backup & Replication — a one-shot health overview, read-only diagnostics / RCA (triage failed backup-job sessions and flag repositories low on space), list/inspect/start/stop/retry backup jobs, enable/disable jobs, list restore points and start a VM restore, list backup repositories with capacity, list stored backups and their objects, inventory backup infrastructure (managed servers, proxies), and poll/stop async sessions for job/restore progress.\n  Always use this skill for \"list veeam jobs\", \"run veeam backup\", \"start veeam job\", \"veeam restore\", \"veeam repository\", \"veeam backup status\", or \"veeam session\" when the context is explicitly Veeam / Veeam Backup & Replication / VBR.\n  Do NOT use when the target is not Veeam Backup & Replication (other backup products, hypervisor lifecycle, or cloud providers are out of scope).\n  Common Veeam B&R operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers).\ninstaller:\n  kind: uv\n  package: veeam-aiops\nargument-hint: \"[job id or describe your Veeam task]\"\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"veeam-aiops\",\"uvx\"]},\"optional\":{\"env\":[\"VEEAM_AIOPS_CONFIG\",\"VEEAM_AIOPS_MASTER_PASSWORD\"]},\"homepage\":\"https://github.com/AIops-tools/Veeam-AIops\",\"emoji\":\"💾\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  Standalone, self-governed Veeam Backup & Replication operations. The governance harness (audit, policy, token/runaway budget, undo, risk-tiers) is bundled in the package — no external skill-family dependency.\n  All write operations are audited to a local SQLite DB under ~/.veeam-aiops/ (relocatable via VEEAM_AIOPS_HOME).\n  Credentials: Each Veeam target's login password is stored ENCRYPTED in ~/.veeam-aiops/secrets.enc (Fernet/AES-128 + scrypt-derived key) — never plaintext on disk. Run 'veeam-aiops init' to onboard, or 'veeam-aiops secret set <target>' to add one. The store is unlocked by a master password from VEEAM_AIOPS_MASTER_PASSWORD (non-interactive/MCP/CI) or an interactive prompt (CLI on a TTY). A legacy plaintext env var VEEAM_<TARGET_NAME_UPPER>_PASSWORD is still honoured as a fallback with a deprecation warning (migrate with 'veeam-aiops secret migrate'). The password is exchanged for a short-lived OAuth2 bearer token at connect time and held only in memory; passwords/tokens are never logged or echoed.\n  Destructive operations (job stop, session stop, restore start) require double confirmation at the CLI layer and support --dry-run. A dry_run MAY read (that is how it can tell you the call would be refused) but never writes, records no undo, and is audited like any other governed call; the CLI --dry-run routes through the same governed function as the MCP tool. All write tools pass through the @governed_tool decorator (budget guard + audit + risk-tier labelling). Reversible writes (job start/stop/retry, enable/disable) record an inverse undo descriptor; session stop and the VM restore are irreversible and record none.\n  Webhooks: none — no outbound network calls beyond the configured Veeam REST API endpoint.\n  SSL: verify_ssl defaults to true; disable only for self-signed lab certificates.\n  Transitive dependencies: httpx (HTTP client) and the MCP SDK. No post-install scripts or background services.\n---\n\n# Veeam AIops\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by Veeam Software.** \"Veeam\" is a trademark of its owner. Source code is publicly auditable at [github.com/AIops-tools/Veeam-AIops](https://github.com/AIops-tools/Veeam-AIops) under the MIT license.\n\nGoverned Veeam Backup & Replication operations — **27 MCP tools**, every one wrapped with the bundled `@governed_tool` harness: a local unified audit log under `~/.veeam-aiops/`, policy engine, token/runaway budget guard, undo-token recording, and descriptive risk tiers. Credentials are stored **encrypted** (`~/.veeam-aiops/secrets.enc`, Fernet + scrypt) — never plaintext on disk.\n\n> **Standalone**: the governance harness is bundled in the package (`veeam_aiops.governance`) — veeam-aiops has no external skill-family dependency. Coverage focuses on common Veeam operations and is not yet exhaustive.\n\n## What This Skill Does\n\n| Category | Tools | Count | Read or Write |\n|----------|-------|:-----:|:-------------:|\n| **Overview** | health overview | 1 | 1 read |\n| **Diagnostics / RCA** | job-failure triage, repository capacity | 2 | 2 read |\n| **Backup Jobs** | list, get, start, stop, retry, enable, disable | 7 | 2 read / 5 write |\n| **Restore** | list restore points (opt. per backup), start VM restore | 2 | 1 read / 1 write |\n| **Repositories** | list, get (detail), state (capacity) | 3 | 3 read |\n| **Backups** | list stored backups, list backup objects, per-VM storage usage, storage ranking | 4 | 4 read |\n| **Infrastructure** | managed servers, proxies | 2 | 2 read |\n| **Sessions** | list, get, log, stop (poll/cancel async progress) | 4 | 3 read / 1 write |\n\n## Quick Install\n\n```bash\nuv tool install veeam-aiops\nveeam-aiops init       # interactive wizard: connection + encrypted password\nveeam-aiops doctor\n```\n\nOr as an OpenClaw plugin, which installs this skill and its MCP server together:\n\n```bash\nopenclaw plugins install clawhub:@zw008/veeam-aiops\nopenclaw skills info veeam-aiops          # expect: Visible to model: yes\n```\n\nNeeds `uvx` on `PATH`: the MCP server is fetched with uv, pinned to this release.\n\n## When to Use This Skill\n\n- List/inspect Veeam backup jobs and their last result\n- Start or stop a backup job on demand\n- Enable or disable a job's schedule\n- List available restore points and start a VM restore\n- List backup repositories and stored backups\n- Report how much backup storage a VM consumes (showback/chargeback input) and which VMs cost the most to protect\n- Poll async sessions to follow job/restore progress\n\n**Do NOT use when** the target is not Veeam Backup & Replication (other backup products, hypervisor VM lifecycle, Kubernetes, or cloud providers are out of scope for this skill).\n\n## Related Skills — Skill Routing\n\n| If the user wants… | Use |\n|--------------------|-----|\n| Veeam backup jobs / restore / repositories | **veeam-aiops** (this skill) |\n| Hypervisor VM lifecycle (power, snapshot, migrate) | a hypervisor ops skill |\n| Container/cluster lifecycle | a cluster ops skill |\n\n## Common Workflows\n\n### Diagnose why last night's backups failed\n\n1. `veeam-aiops diagnose job-failures --since-hours 24` → worst-first table of Failed/Warning sessions, each with the categorized cause (repository full / source unreachable / credential-VSS / retry exhaustion) and the cited failing log line\n2. If a finding says **repository full**, confirm with `veeam-aiops diagnose repo-capacity` → the flagged repo's measured free% and free bytes\n3. Fix the root cause (extend/offload the repository, restore source connectivity, or repair guest credentials/VSS), then `veeam-aiops job retry <job_id>` to re-run only the failed objects\n4. `veeam-aiops session list` → `veeam-aiops session get <session_id>` to confirm the retry completes — do not tight-loop `session get` (the runaway budget guard will trip it)\n\n### Run a backup job and follow it to completion\n\n1. `veeam-aiops job list` → find the job id and confirm `lastResult`\n2. `veeam-aiops job start <job_id>` → starts the job (records an inverse `job_stop` undo descriptor)\n3. `veeam-aiops session list` → find the running session; `veeam-aiops session get <session_id>` → check `state` / `progressPercent`\n4. **Failure branch**: if `session get` shows the session `Failed`, inspect `result`, then re-run `job start` after fixing the cause — do not loop `session get` rapidly (the runaway budget guard will trip a tight poll loop).\n\n### Showback: how much backup storage does a VM consume?\n\n1. `veeam-aiops backup usage <vm-name>` → per backup (primary job and each backup copy): repository, restore points, stored / full / incremental bytes, shared bytes, job retention\n2. Read the caveats before quoting a number: files that hold **several** machines are reported as shared and never added to the VM's total; on block-clone repositories (ReFS / XFS fast clone) the stored total is an upper bound\n3. `veeam-aiops backup ranking --limit 20` → which machines consume the most backup storage, largest first; raise `--max-backups` if `backupsTruncated` is true. On a large estate scope it (`--backup <job name>` repeatable, `--repository <name>`) — a full scan can take tens of minutes; a SCOPED ranking is not an estate-wide one\n4. Apply your own storage price to the bytes — this tool reports consumption only. **Needs VBR 12.3 or later**; older servers get a clear refusal naming the minimum build.\n\n### Restore a VM from a restore point\n\n1. `veeam-aiops restore list-points` → identify the correct restore point id\n2. `veeam-aiops restore start --restore-point-id <id> --dry-run` → preview the exact API call **and the VM name + creation time** the id resolves to — never approve a restore from a GUID\n3. `veeam-aiops restore start --restore-point-id <id>` → double confirmation required; this is IRREVERSIBLE (overwrites/creates a VM) and records no undo token. Refused outright if the VM name matches the configured VBR host (an in-place overwrite of the backup server itself) — a name-based safety net, not a proof, so confirm the target yourself\n4. **Failure branch**: if `doctor` shows the VBR server unreachable or the password env var is missing, fix `~/.veeam-aiops/.env` (chmod 600) before retrying — the restore is never issued against an unauthenticated session.\n\n## Usage Mode\n\n| Scenario | Recommended | Why |\n|----------|:-----------:|-----|\n| Local/small models | **CLI** | fewer tokens than MCP |\n| Cloud models (Claude, GPT) | Either | MCP gives structured JSON I/O |\n| Automated pipelines | **MCP** | type-safe parameters, audited |\n\n## MCP Tools (27 — 19 read, 8 write)\n\n| Category | Tools | R/W |\n|----------|-------|:---:|\n| Overview | `overview` | Read |\n| Diagnostics / RCA | `job_failure_rca`, `repository_capacity_rca` | Read |\n| Backup Jobs | `job_list`, `job_get` | Read |\n| | `job_start`, `job_stop`, `job_retry`, `job_enable`, `job_disable` | Write |\n| Restore | `restore_list_points` | Read |\n| | `start_vm_restore` | Write |\n| Repositories | `repository_list`, `repository_get`, `repository_state` | Read |\n| Backups | `backup_list`, `backup_object_list`, `backup_object_storage_usage`, `backup_storage_ranking` | Read |\n| Infrastructure | `managed_server_list`, `proxy_list` | Read |\n| Sessions | `session_list`, `session_get`, `session_log` | Read |\n| | `session_stop` | Write |\n| Undo | `undo_list` | Read |\n| | `undo_apply` | Write |\n\n**Harness features that light up**: write tools with a clean inverse (`job_start`↔`job_stop`, `job_retry`→`job_stop`, `job_enable`↔`job_disable`) pass an `undo=` lambda so the harness records an inverse descriptor (with `_undo_id`) to the undo store. The irreversible `start_vm_restore` and `session_stop` declare no undo; `start_vm_restore` is tagged `risk_level=high`. All 27 tools are audit-logged under `~/.veeam-aiops/` and pass through the budget/runaway guard, each row carrying a descriptive risk tier. Veeam jobs/restores run as async sessions — poll with `session_get` / `session_log` instead of re-issuing (the runaway breaker backs this up). Start any triage with `overview` (jobs by last result, repos near full, running sessions), then drill in with `job_failure_rca` (categorizes failing sessions with cited error substrings) and `repository_capacity_rca` (cited free%).\n\n## CLI Quick Reference\n\n```bash\nveeam-aiops init                                      # onboarding wizard (encrypted password)\nveeam-aiops overview [--target <t>]                   # health summary\nveeam-aiops diagnose job-failures [--target <t>]      # RCA: triage failed job sessions\nveeam-aiops diagnose repo-capacity [--target <t>]     # RCA: repos low on free space\nveeam-aiops job list [--target <t>]\nveeam-aiops job get <job_id>\nveeam-aiops job start <job_id>\nveeam-aiops job stop <job_id> [--dry-run]              # double confirm\nveeam-aiops job retry <job_id>\nveeam-aiops job enable <job_id>\nveeam-aiops job disable <job_id>\nveeam-aiops restore list-points [--backup-id <id>] [--limit 100]\nveeam-aiops restore start --restore-point-id <id> [--dry-run]   # double confirm\nveeam-aiops repository list\nveeam-aiops repository get <repository_id>\nveeam-aiops repository state                           # capacity / free / used%\nveeam-aiops session list [--limit 100]\nveeam-aiops session get <session_id>\nveeam-aiops session log <session_id>\nveeam-aiops session stop <session_id> [--dry-run]     # double confirm\nveeam-aiops backup list\nveeam-aiops backup objects <backup_id>\nveeam-aiops infra servers\nveeam-aiops infra proxies\nveeam-aiops secret set <target>                        # store password encrypted\nveeam-aiops secret list                               # names only\nveeam-aiops secret migrate                            # import legacy plaintext .env\nveeam-aiops secret rotate-password\nveeam-aiops doctor\nveeam-aiops mcp                                        # start MCP server (stdio)\n```\n\nSee `references/cli-reference.md` for the full command list.\n\n## Troubleshooting\n\n### \"Config file not found\"\nRun `veeam-aiops init` to set up your first target (writes `~/.veeam-aiops/config.yaml` and stores the password encrypted).\n\n### \"No password for target '<name>'\"\nAdd it to the encrypted store: `veeam-aiops secret set <name>` (prompts hidden), or run `veeam-aiops init`. For non-interactive use (MCP/CI), also export `VEEAM_AIOPS_MASTER_PASSWORD` so the store can be unlocked without a prompt.\n\n### \"Master password not set\" / \"Wrong master password\"\nThe encrypted store `~/.veeam-aiops/secrets.enc` is unlocked by `VEEAM_AIOPS_MASTER_PASSWORD` (or an interactive prompt). If you forgot it, delete `secrets.enc` and re-run `veeam-aiops init`. Rotate it with `veeam-aiops secret rotate-password`.\n\n### \"Authentication/authorization failed (401)\"\nThe username/password is wrong, or the account lacks a Veeam role. Veeam usernames are typically `DOMAIN\\\\user` or a local Windows account on the VBR server. Confirm the account can log in to the Veeam console.\n\n### \"Could not reach Veeam server … check the host/port\"\nThe default REST API port is 9419 — confirm the Veeam Backup & Replication REST API service is running and the port is open. For self-signed certificates set `verify_ssl: false` on the target (lab only).\n\n### \"Resource not found (404)\"\nThe job/session/restore-point id is stale. List the parent collection first (`job list`, `session list`, `restore list-points`) to get a current id.\n\n## Governance & Safety\n\nThe skill delivers reads and writes and records them; it does **not** decide\nwhether a write is permitted. That is your agent's judgement, or the permission\nof the Veeam account you connect it with (a read-only or restricted role on the\nVBR server — writes then fail at the server). There is no read-only switch,\npolicy file, or approval gate.\n\n- Credentials stored **encrypted** in `~/.veeam-aiops/secrets.enc` (Fernet/AES-128 + scrypt key derivation; chmod 600) — never plaintext on disk; the master password is never stored, only a per-store salt + ciphertext\n- **Audit is the guarantee, and it is not bypassable.** Every operation — MCP and CLI alike — is logged to `~/.veeam-aiops/audit.db` (relocatable via `VEEAM_AIOPS_HOME`): params (secrets redacted), result, status, duration, and the risk tier. The CLI writes the same row the MCP path does.\n- `VEEAM_AUDIT_APPROVED_BY` / `VEEAM_AUDIT_RATIONALE` are optional annotations recorded on the audit row (who/why); they are never required and never block.\n- **Runaway guard** — a safety backstop, not authorization: cumulative tool calls and wall-time are capped, and the same call looped in a tight session-poll/retry window trips a circuit breaker.\n- Writes support `--dry-run` / `dry_run=True` and double confirmation at the CLI; CLI writes execute through the same governed tools, so they are audited + undo-recorded.\n- Reversible writes (job start/stop/retry, enable/disable) record an inverse undo descriptor; the irreversible `start_vm_restore` and `session_stop` record none.\n\nThe harness is bundled in the package — no external dependency, no manual setup. See `references/setup-guide.md` for security details.\n\n## Contributing & feature requests\n\nCoverage is intentionally focused. **Missing a device, action, or feature you need?** Open an issue or pull request at [github.com/AIops-tools/Veeam-AIops](https://github.com/AIops-tools/Veeam-AIops/issues) — feature requests, contributions, and comments are all welcome.\n\n## License\n\nMIT — [github.com/AIops-tools/Veeam-AIops](https://github.com/AIops-tools/Veeam-AIops)\n\nFile v0.16.0:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"veeam-aiops\",\n  \"version\": \"0.16.0\",\n  \"publishedAt\": 1789311945489\n}\n\nFile v0.16.0:references/agent-guardrails.md\n\n# Agent guardrails — running veeam-aiops with a smaller / local model\n\nIf you drive these tools with a local model (Llama, Qwen, Mistral … via Goose,\nOllama, LM Studio, or any OpenAI-compatible runtime), you will get noticeably\nbetter results with a short system prompt. This page gives you one, and — more\nimportantly — tells you which guardrails you **no longer need to write**, because\nthe tool now enforces them itself.\n\nThe distinction matters. A guardrail in a prompt is a request. A guardrail in the\nharness is a guarantee. Anything below that we could move into the harness, we did.\n\n## Authorization is not this tool's job — decide it where it belongs\n\nWhether a write should happen is your decision, or the account's. The tool does\nnot gate it — there is no read-only switch and no approval prompt to configure.\nThe two right places to control read vs write:\n\n- **The account you connect with.** Give the Veeam account you connect with a\n  read-only or restricted role on the VBR server. A write then fails at the\n  server, which is the only place the permission actually lives — a revoked\n  permission cannot be argued around by a model, but a skill-side flag can.\n- **Your agent's system prompt.** If you want an observe-only session, tell the\n  model not to call the write tools (they are clearly tagged `[WRITE]`).\n\nWhat the tool *does* guarantee is that you can always see what happened:\n\n## What the tool enforces — do not waste prompt budget on these\n\n| You might be tempted to prompt | Why you don't need to |\n|---|---|\n| \"Don't invent a value when a field is missing\" | A field the VBR API did not return comes back as `null`, never as `\"\"`. A job with no `lastResult` yet, a session with no verdict, a proxy with no reported host — all report `null`, and only a genuinely empty upstream value comes back as `\"\"`. Absent and empty are distinguishable in the payload. |\n| \"Tell me if the output was cut off\" | The reads that can be too large to return whole — `restore_list_points`, `session_list`, `undo_list`, and `backup_storage_ranking` — return an envelope such as `{\"restorePoints\": [...], \"returned\": N, \"limit\": L, \"truncated\": true/false}` (the ranking also says `scoped` / `backupsTruncated` when it covers only a selection or a scanned subset), newest first where time matters. Truncation is measured (one extra row is fetched), not guessed from a length coincidence. Every other list read pages through the whole collection — the VBR server may cap a page at 200 items (Veeam's spec default from revision 1.3) — and refuses with an error rather than returning a partial list if the server stops short. |\n| \"Preserve the ordering / tell me what's most urgent\" | `job_failure_rca` and `repository_capacity_rca` findings carry an explicit 1-based `rank`, worst-first. Priority is in the payload, not implied by list position. |\n| \"Explain why you flagged that repository / job\" | Every finding carries the measured signal that tripped it — the session `result` and the matched error substring, or the free-space percentage against the threshold — plus a concrete `cause` and `action`. The heuristics are transparent, not a verdict. |\n| \"Confirm before anything destructive\" | `job_stop`, `session_stop` and `restore start` require a `--dry-run`-able preview plus double confirmation at the CLI; the MCP write tools take `dry_run=True`. `start_vm_restore` is tagged `high` risk. |\n| \"Remember how to put it back\" | Writes with a clean inverse (`job_start`/`job_stop`, `job_enable`/`job_disable`, `job_retry`) record an undo token — list them with `undo_list`, replay with `undo_apply`. The irreversible ones (`start_vm_restore`, `session_stop`) record none and say so. |\n| \"Log what you did\" | Every governed call is audited to `~/.veeam-aiops/audit.db` regardless of what the model says it did — and the CLI writes the same row the MCP path does, so there is no unaudited entry point. |\n| \"Don't get stuck retrying\" | The runaway guard trips a circuit breaker if the same call is hammered in a tight loop (e.g. re-issuing a job instead of polling its session) — a stuck agent is stopped rather than left to burn calls and time. |\n\n## What still needs a prompt\n\nThese are model-behaviour problems the harness cannot fix from the outside.\nCopy this into your agent's system prompt:\n\n```text\nYou operate a Veeam Backup & Replication environment through the veeam-aiops\nMCP tools.\n\nTOOL USE\n- Before answering any question about the current Veeam environment, you MUST\n  call a tool. Never answer from memory or assumption.\n- Actually invoke the tool. Do not describe the call you would make, and do not\n  emit an example JSON response in place of calling it.\n- If a tool call fails, report the real error verbatim. Never fill the gap with\n  a plausible-sounding answer.\n\nREADING RESULTS\n- Read the whole result before concluding. If a result contains a \"truncated\"\n  field that is true, say so and re-run with a higher limit instead of treating\n  the partial result as complete.\n- A null field means the VBR API did not return that value. Report it as \"not\n  available\" — never infer it. A session with a null result has not finished,\n  which is not the same as having succeeded.\n- Report values exactly as returned. Do not normalise, translate, or prettify\n  job status strings, session results (Success / Warning / Failed / None), or\n  identifiers.\n- When a diagnose result has findings, work in \"rank\" order and cite the\n  measured number in each finding's \"detail\".\n\nSCOPE\n- Separate observation from interpretation. State what the tools returned, then\n  any interpretation, clearly marked as such.\n- Do not assert a backup failure, a capacity problem, or a missed RPO unless a\n  tool result supports it.\n- Do not add generic advice that does not follow from the tool output.\n- Do not confuse a job id with a session id, a session id with a restore point\n  id, or a backup id with the repository it lives on. They are different\n  objects with different tools.\n```\n\n## Recommended setup for a local model\n\nStart with a connection that *cannot* write, verify, and widen the account's\npermission only when you trust the setup — a restore or a stopped job on the\nwrong target is not something you want a smaller model reaching for on day one:\n\n```bash\n# e.g. connect with a Veeam account that has a read-only or restricted role on\n# the VBR server. Then:\nveeam-aiops doctor\n```\n\nOptionally annotate the audit trail with who is operating and why — recorded on\nevery row, never required:\n\n```bash\nexport VEEAM_AUDIT_APPROVED_BY=\"your.name@example.com\"\nexport VEEAM_AUDIT_RATIONALE=\"scheduled maintenance window 2026-07-20\"\n```\n\n## Veeam-specific notes\n\nThese are the places a smaller model most often goes wrong against a VBR server,\nand what to do about them:\n\n- **Jobs and restores are asynchronous.** `job_start`, `job_retry` and\n  `start_vm_restore` return immediately; the work happens in a *session*. Progress\n  belongs to `session_get`, not to the job. Tell the model to start once and poll\n  the session — the runaway budget guard will trip on a re-issue loop, but a\n  wasted trip is still a wasted trip.\n- **Four id namespaces look alike.** Job ids, session ids, backup ids and restore\n  point ids are all opaque strings. `backup_object_list` takes a *backup* id;\n  `restore_list_points` filters by a *backup* id and returns *restore point* ids;\n  `start_vm_restore` takes a *restore point* id. Models routinely pass the wrong\n  one — prefer chaining the tools (`backup_list` → `restore_list_points`) over\n  letting the model reconstruct an id.\n- **\"Warning\" is a real failure state.** A Veeam session result of `Warning` is\n  flagged by `job_failure_rca` alongside `Failed`. A model that treats Warning as\n  success will report a healthy backup estate that isn't one.\n- **A disabled job is not a failing job.** `job_list` reports `isDisabled`\n  separately from `lastResult`; a disabled job simply has not run.\n- **`start_vm_restore` cannot be undone.** It overwrites or creates a VM and\n  records no undo token. It is `high` risk deliberately. It is also a documented\n  skeleton: the exact endpoint and payload differ per\n  restore type (instant recovery vs full restore vs restore-to-new-location) and\n  per Veeam version, so validate it against your environment before trusting it.\n- **Always read the `dry_run` preview before approving a restore.** It names the\n  VM and creation time behind the restore-point GUID. The tool refuses a restore\n  whose VM name matches the configured VBR host — an in-place overwrite of the\n  backup server itself — but that check compares a display name to a hostname, so\n  **it will miss a VBR server named anything else**. Separately, when the\n  restore point cannot be read at all the restore is REFUSED, because nothing\n  can then say which machine would be overwritten; pass\n  `acknowledge_unresolved=True` only after confirming the target in the Veeam\n  console.\n\n## If your model still struggles\n\nSome behaviours are model-capacity limits rather than prompt problems:\n\n- **Multi-tool workflows time out or drift.** Prefer `overview` and the\n  `*_rca` diagnose tools — they do the multi-step correlation inside one call, so\n  the model does not have to chain reads and keep job/session ids straight.\n- **The model ignores later tool results in a long context.** Ask narrower\n  questions; use `job_get` / `session_get` on one object rather than pulling the\n  whole session list and reasoning over it.\n- **The model describes calls instead of making them.** This is usually a\n  runtime/tool-calling-format mismatch, not a prompt problem — check that your\n  client advertises the tools in the format your model was trained on.\n\nFeedback on running this with a specific local model is genuinely useful —\nopen an issue at\n[github.com/AIops-tools/Veeam-AIops](https://github.com/AIops-tools/Veeam-AIops/issues)\nwith the model, runtime, and what went wrong.\n\nFile v0.16.0:references/capabilities.md\n\n# veeam-aiops capabilities\n\n27 MCP tools (19 read, 8 write), each wrapped with the bundled `@governed_tool`\nharness. Typical response token estimates assume a small/medium environment.\n\n## Overview (1 — read)\n\n| Tool | R/W | Risk | Typical response tokens |\n|------|:---:|:----:|:----------------------:|\n| `overview` | R | low | ~150 |\n\nFan-out health summary: jobs grouped by last result, repositories at/above 85%\nused, and currently-running sessions. Call this first to triage an environment.\n\n## Diagnostics / RCA (2 — read)\n\n| Tool | R/W | Risk | Typical response tokens |\n|------|:---:|:----:|:----------------------:|\n| `job_failure_rca` | R | low | ~200–600 |\n| `repository_capacity_rca` | R | low | ~150 |\n\n`job_failure_rca` scans the newest `limit` sessions (default 100, newest first by\n`creationTime`; `sessionsTruncated` says older ones exist) — pass `since_hours=24`\nto make the window \"the last day\" instead — flags every Failed/Warning run, and\ncategorizes the likely cause (repository full, source/guest unreachable,\ncredential/VSS failure, retry exhaustion) from the failing log records — each\nfinding cites the session result + matched error substring, worst-first.\n`repository_capacity_rca` flags repositories under the free-space thresholds\n(<15% warn, <10% critical), citing the measured free% and free bytes.\n\n## Backup Jobs (7 — 2 read, 5 write)\n\n| Tool | R/W | Risk | Undo | Typical response tokens |\n|------|:---:|:----:|------|:----------------------:|\n| `job_list` | R | low | — | 150–600 (depends on job count) |\n| `job_get` | R | low | — | ~120 |\n| `job_start` | W | medium | `job_stop` | ~50 |\n| `job_stop` | W | medium | `job_start` | ~50 |\n| `job_retry` | W | medium | `job_stop` | ~50 |\n| `job_enable` | W | medium | `job_disable` | ~40 |\n| `job_disable` | W | medium | `job_enable` | ~40 |\n\nREST endpoints: `GET /api/v1/jobs`, `GET /api/v1/jobs/{id}`,\n`POST /api/v1/jobs/{id}/{start|stop|retry|enable|disable}`. The write tools\ncapture the job's prior status/lastResult for context.\n\n## Restore (2 — 1 read, 1 write)\n\n| Tool | R/W | Risk | Undo | Typical response tokens |\n|------|:---:|:----:|------|:----------------------:|\n| `restore_list_points` | R | low | — | 150–800 |\n| `start_vm_restore` | W | high | **none — irreversible** | ~40 |\n\n`restore_list_points` returns the newest `limit` points (default 100, max 1000) as\n`{\"restorePoints\", \"returned\", \"limit\", \"truncated\", \"order\"}` — an estate's restore\npoints are far too many to return whole. With `backup_id`, a point from another\nbackup coming back means the server ignored the filter, and that is refused.\n\nREST endpoints: `GET /api/v1/restorePoints` (`orderColumn=CreationTime&orderAsc=false`,\noptional `backupIdFilter`),\n`GET /api/v1/restorePoints/{id}` (to name what a restore would overwrite),\n`POST /api/v1/restore/vm`. `start_vm_restore` is a documented skeleton: the\nexact restore endpoint and payload vary by restore type and Veeam version.\n\nThe payload carries **no target mapping**, so it is a restore-to-original — an\nin-place overwrite. Two consequences worth knowing before you call it:\n\n- `dry_run=True` resolves the opaque restore-point id to the **VM name and\n  creation time** it would overwrite.\n- **An unreadable restore point is refused**, by the preview and the real call\n  alike: with no target mapping this is a restore-to-original with no undo, and\n  a tool that cannot name the machine it is about to overwrite has not given\n  anyone something to approve. `acknowledge_unresolved=True`\n  (CLI `--acknowledge-unresolved`) proceeds anyway, for when the target has been\n  confirmed in the Veeam console; `resolved: false` then says the target is\n  unknown. Refusing errs recoverably — restore from the console — while\n  proceeding errs onto a machine nobody could name.\n- It **refuses** when that VM name matches the configured VBR host — **on the\n  dry-run as well as the real call**, with identical behaviour. A\n  preview that returns green for a call that will then be refused is a preview\n  reporting the wrong outcome. Veeam's own\n  guidance is to back up the VBR server itself, so its restore point sits in the\n  same list as every other one with nothing marking it as special. **This check\n  is a safety net, not a proof**: a VM display name is not a hostname, so a VBR\n  server whose VM is named `Backup Server 01` is not caught. An unknown name is\n  still never read as \"it is the VBR server\" — that judgement stays open — but\n  the restore itself is now refused in that case by the separate unreadable-\n  target guard above.\n\n### Dry-run semantics (line-wide)\n\n`dry_run=True` returns `{\"dryRun\": true, \"would...\": {...}}`. A dry-run **may read** —\nresolving ids and evaluating guards is exactly what lets it answer \"would this be\nrefused?\" — but it **never writes** and records **no undo**. It runs through\n`@governed_tool` like any other call, so it is audited and it can be refused. The CLI\n`--dry-run` routes through the same governed function, so both entry points behave\nidentically.\n\n## Repositories (3 — read)\n\n| Tool | R/W | Risk | Typical response tokens |\n|------|:---:|:----:|:----------------------:|\n| `repository_list` | R | low | 100–400 |\n| `repository_get` | R | low | ~120 |\n| `repository_state` | R | low | 100–400 |\n\nREST endpoints: `GET /api/v1/backupInfrastructure/repositories`,\n`GET /api/v1/backupInfrastructure/repositories/{id}`,\n`GET /api/v1/backupInfrastructure/repositories/states` (capacity / free / used,\nplus a computed used%). `repository_get` merges the static record with its state\nrow when available.\n\n## Backups (4 — read)\n\n| Tool | R/W | Risk | Typical response tokens |\n|------|:---:|:----:|:----------------------:|\n| `backup_list` | R | low | 150–800 |\n| `backup_object_list` | R | low | 150–800 |\n| `backup_object_storage_usage` | R | low | 400–1500 |\n| `backup_storage_ranking` | R | low | 300–2000 |\n\nREST endpoints: `GET /api/v1/backups`, `GET /api/v1/backups/{id}/objects`.\n\n### Backup storage footprint (`backup_object_storage_usage`, `backup_storage_ranking`)\n\nSums Veeam's own per-file accounting from `GET /api/v1/backups/{id}/backupFiles`:\n`backupSize` (on disk after compression and deduplication) and `dataSize`\n(before). Other reads: `GET /api/v1/serverInfo` (build → REST revision),\n`GET /api/v1/backupObjects?nameFilter=`, `GET /api/v1/restorePoints?backupObjectIdFilter=`,\n`GET /api/v1/backups/{id}`, `GET /api/v1/jobs/{id}` (retention), `GET /api/v1/backupObjects/{id}`\n(ranking: owners a backup does not list). Every collection\nis paged to completion — the server caps a page at 200 by default.\n\n- **Needs VBR 12.3+.** `backupFiles` first appears in REST revision 1.2-rev0\n  (VBR 12.3.0.310, per Veeam's published revision table). The size reads send\n  the newest revision the server's build serves; the rest of the tool keeps its\n  pinned 1.1-rev1. Older builds get a refusal that names the minimum build.\n- **Works with a read-only Backup Viewer account.** `/api/v1/serverInfo` (the\n  build) is Backup Administrator only from revision 1.1-rev2 on; without it the\n  tools offer each revision newest-first on a one-item `GET /api/v1/backups` and\n  use the first the server accepts (`apiRevision.basis: \"probe\"`; refused\n  revisions are listed in `apiRevision.probeRefusals`).\n- **Shared files are never charged to one machine.** Per-job backup chains keep\n  several VMs in one file; revision 1.3-rev2 (VBR 13.1+) lists every owner, and\n  such files land in `sharedStoredBytes`, outside `storedBytes`. Older revisions\n  name one owner per file, so sharing is decided by the restore points the file\n  itself lists (`restorePointIds`): any point that is not this machine's makes\n  it shared, whatever owner it names. A file whose ownership the server states\n  inconsistently (no owner and no point list, or a single other owner with only\n  this machine's points) goes to `unattributedStoredBytes` — never charged, and\n  visible if owner ids ever turn out not to match backup-object ids. The ranking\n  reads no restore points and charges each file to its listed owner.\n- **The ranking separates two kinds of uncharged file.** A file naming no owner\n  at all is an ordinary per-job chain file and lands in `ownerlessStoredBytes`.\n  A file naming an owner id that its own backup's object listing does not\n  contain lands in `unmatchedOwnerStoredBytes` and raises a caveat — that is the\n  signal that backup-file owner ids and backup-object ids are different\n  namespaces on this build, which is the one assumption the Veeam spec never\n  pins down. `unresolvedStoredBytes` remains the sum of both. Judge a ranking's\n  fitness for chargeback on `unmatchedOwnerFiles`, never on the sum: a healthy\n  estate can carry a large ownerless total.\n- **A partial ranking says so.** `backupsScanned`/`backupsTotal`/\n  `backupsTruncated` are in the payload and the CLI prints an explicit PARTIAL\n  line, because the default `max_backups` (100) is below some estates' backup\n  count and widening a scan can put a previously unseen object at rank 1.\n- **Scope the scan instead of waiting for the whole estate.** A complete\n  ranking of a 123-backup VBR 13.1 estate took 21 minutes with 4 s of local\n  CPU — the time is the server. `backups` (ids or names; a backup is named\n  after its job) and `repository` (id or name) select what is read; the\n  filter is applied locally because `/backups` offers no repository filter;\n  names come from both plain and scale-out repositories.\n  A scope that matches nothing is an error, not an empty ranking. The payload\n  carries `scoped`, `scope` and `backupsInScope`; a scoped ranking adds a\n  caveat and the CLI prints SCOPED, because it ranks the selection, not the\n  environment. `backupsTruncated` is measured against the scope.\n- **Backups can be read in parallel** (`concurrency`, 1–8, **default 1**).\n  Opt-in because it is unmeasured on a real VBR: the server is already the\n  bottleneck, and parallel reads can push a slow `backupFiles` read past the\n  timeout — lower it if backups time out. Results are folded in scan order, so\n  the payload is identical at any concurrency; a hard error in one read returns\n  at once instead of waiting out the others. Token renewal is serialised, so\n  parallel reads that all meet an expired token log in once. The CLI reports\n  progress on stderr, so `--json` stays parseable.\n- **An owner missing from its backup's listing is looked up** once per id via\n  `GET /api/v1/backupObjects/{id}` (at most 200 ids; the rest are counted in\n  `ownerLookupsSkipped`; the budget goes to the ids carrying the most bytes, and\n  skipped ids get their own caveat rather than the namespace one, since they\n  were never checked). Found → the id is a backup-object id (typically a\n  machine moved to another job or removed from this one), its bytes are\n  charged to that machine and also counted in `recoveredOwnerStoredBytes`.\n  404 or a failed lookup → the bytes stay in `unmatchedOwnerStoredBytes` and\n  the namespace caveat stands. `unmatchedOwners` lists every id with its\n  `resolution` (`otherBackup`, `sameBackup`, `resolved`, `notFound`,\n  `lookupFailed`, `skipped`), largest first, at most 50 entries\n  (`unmatchedOwnersTotal`, `unmatchedOwnersTruncated`). A backup the server\n  lists without an id is reported in `unreadableBackups`, not silently skipped.\n- **One unreadable backup does not blank the result**: it is listed in\n  `unreadableBackups` (with the error) and left out of every total. An entry\n  with `timedOut: true` adds a caveat naming the fix — raise the target's\n  `timeout` in config.yaml (the same estate needed 300 s for `/backupFiles`\n  where the default is 30 s) — since retrying at the same budget cannot help.\n- **The restore-point filter is checked, not trusted.** A query for a random\n  object id must come back empty (`restorePointFilter: \"honoured\"`); then points\n  under a machine's old name are kept (`restorePointNamesSeen`). If the server\n  ignores the filter — or the check itself fails — points are matched by name,\n  the others are counted in `restorePointsSetAside`, and a caveat says so; if\n  two same-named machines then get the same points, totals are withheld and each\n  machine is marked `attributable: false`.\n- **Full vs incremental** comes from each restore point's `type` and the\n  `backupFileId` it lives in; the `.vbk`/`.vib`/`.vrb` extension is a fallback,\n  and `kindBasis` counts which rule classified each file.\n- **Missing is not zero**: files without a size are counted in `unsizedFiles`\n  and left out of the sums. `approxSourceBytes` is null before revision 1.3-rev2.\n- **Block cloning**: on ReFS / XFS fast-clone repositories synthetic fulls share\n  blocks, so summed file sizes can exceed physical consumption — an upper bound.\n- **Same name, different machines** (two vCenters) are kept apart by identity\n  (`path`, then `objectId` / BIOS UUID) and a caveat is added; the ranking merges\n  one machine across backups by the same identity. Where the revision exposes no\n  inventory id (Hyper-V and agents before 1.3-rev2) identity falls back to name,\n  with a caveat.\n- **Paging checks the server**: `skip` advances by what was actually returned,\n  items are de-duplicated by id, and a server that stops short of its own total\n  or repeats a page is refused rather than billed partially or twice.\n- `changeRate` is mean incremental `dataSize` ÷ latest full `dataSize`, per\n  increment (not per day).\n- No pricing: storage cost models are organisation-specific.\n\n## Infrastructure (2 — read)\n\n| Tool | R/W | Risk | Typical response tokens |\n|------|:---:|:----:|:----------------------:|\n| `managed_server_list` | R | low | 150–600 |\n| `proxy_list` | R | low | 150–600 |\n\nREST endpoints: `GET /api/v1/backupInfrastructure/managedServers`,\n`GET /api/v1/backupInfrastructure/proxies`. Read-only inventory of where jobs\nrun and what moves the data.\n\n## Sessions (4 — 3 read, 1 write)\n\n| Tool | R/W | Risk | Undo | Typical response tokens |\n|------|:---:|:----:|------|:----------------------:|\n| `session_list` | R | low | — | 150–800 |\n| `session_get` | R | low | — | ~120 |\n| `session_log` | R | low | — | 150–800 |\n| `session_stop` | W | medium | **none** | ~40 |\n\nREST endpoints: `GET /api/v1/sessions`, `GET /api/v1/sessions/{id}`,\n`GET /api/v1/sessions/{id}/logs`, `POST /api/v1/sessions/{id}/stop`. Sessions\nare how Veeam exposes async job/restore progress — poll these instead of\nre-issuing the originating operation; read `session_log` to see *why* one failed —\neach record carries `title`, `description` (the error detail), `status`,\n`startTime` and `updateTime`.\n`session_list` returns the newest `limit` sessions (default 100, max 1000) as\n`{\"sessions\", \"returned\", \"limit\", \"truncated\", \"order\"}`, sorted by the server\n(`orderColumn=CreationTime&orderAsc=false`), so \"recent\" is explicit;\n`since_hours` narrows it to sessions created in the last N hours.\n`overview` does **not** derive \"running\" from that window: it queries each\nunfinished state (`stateFilter`: Starting, Working, Stopping, Pausing, Resuming,\nPostprocessing, WaitingTape, WaitingRepository, WaitingSlot), so a job started\ndays ago is still reported; a refused state lands in `stateQueryErrors`.\n\n### List reads and paging\n\nThe VBR REST API pages its collections; Veeam's spec gives `limit` a default of\n200 from revision 1.3-rev0 (the pinned 1.1-rev1 documents no default). Inventory reads (`backup_list`,\n`backup_object_list`, `job_list`, `repository_list`, `repository_state`,\n`managed_server_list`, `proxy_list`) page to the end; `overview` and\n`repository_capacity_rca` therefore see every repository. The pager advances by\nwhat the server actually returned, de-duplicates by id, and raises instead of\nreturning a partial list if the server stops short or repeats a page.\n`backup_object_list` sends no paging parameters on its first request (the pinned\nrevision 1.1-rev1 declares none for that endpoint) and pages only if the server's\npagination block shows more.\n\n## Undo (2 — 1 read, 1 write)\n\n| Tool | R/W | Risk | Undo | Typical response tokens |\n|------|:---:|:----:|------|:----------------------:|\n| `undo_list` | R | low | — | ~100–400 |\n| `undo_apply` | W | medium | **none — single-use** | ~60 |\n\nGeneric governance tools provided by the bundled harness, not the Veeam REST\nAPI. `undo_list` lists the recorded reversible writes whose undo tokens have not\nyet been applied. `undo_apply` executes a recorded inverse for one token — it is\nitself governed (audited and budget-checked), single-use (a token\ncannot be replayed), and supports `dry_run` to preview the inverse first.\n\n## Harness behavior\n\n- **Encrypted credentials**: passwords are stored in `~/.veeam-aiops/secrets.enc`\n  (Fernet + scrypt), unlocked by `VEEAM_AIOPS_MASTER_PASSWORD` or a prompt —\n  never plaintext on disk.\n- **Audit**: all 27 tools log to `~/.veeam-aiops/audit.db`.\n- **Undo store**: the five reversible job writes record an inverse descriptor\n  (`_undo_id` on the result); `session_stop` and the high-risk restore record none.\n- **Budget/runaway guard**: caps cumulative calls + wall-time and trips tight\n  session-poll loops.\n- **Risk tier**: a descriptive label on each audit row derived from `risk_level`;\n  it gates nothing. `VEEAM_AUDIT_APPROVED_BY` / `VEEAM_AUDIT_RATIONALE` are\n  optional annotations recorded on the audit row, never required.\n- **Sanitize**: all API-returned text is truncated + control-char stripped.\n\nFile v0.16.0:references/cli-reference.md\n\n# veeam-aiops CLI reference\n\nGlobal options on most commands: `--target / -t <name>` selects a configured\ntarget (default: first target in `config.yaml`).\n\n## Onboarding & secrets\n\n```bash\nveeam-aiops init                           # interactive wizard: connection + encrypted password\nveeam-aiops secret set <target>            # store/replace a password (prompts hidden)\nveeam-aiops secret list                    # names only; values never shown\nveeam-aiops secret rm <target>             # delete a stored password\nveeam-aiops secret migrate                 # import a legacy plaintext .env into the encrypted store\nveeam-aiops secret rotate-password         # re-encrypt the store under a new master password\n```\n\n## Overview\n\n```bash\nveeam-aiops overview                       # jobs by last result, repos near full, running sessions\n```\n\n## Backup jobs\n\n```bash\nveeam-aiops job list                       # id, name, type, status, lastResult\nveeam-aiops job get <job_id>               # detail for one job (incl. schedule)\nveeam-aiops job start <job_id>             # start a backup job (async session)\nveeam-aiops job stop <job_id> [--dry-run]  # stop a running job — double confirm\nveeam-aiops job retry <job_id>             # retry failed objects (async session)\nveeam-aiops job enable <job_id>            # enable the job schedule\nveeam-aiops job disable <job_id>           # disable the job schedule\n```\n\n## Restore\n\n```bash\nveeam-aiops restore list-points [--backup-id <id>] [--limit 100]  # newest restore points first\nveeam-aiops restore start --restore-point-id <id> [--dry-run]\n                                           # IRREVERSIBLE — double confirm\n```\n\n## Repositories\n\n```bash\nveeam-aiops repository list                # id, name, type, path\nveeam-aiops repository get <repo_id>       # detail incl. capacity/free/used\nveeam-aiops repository state               # capacity summary for all repos (used%)\n```\n\n## Backups\n\n```bash\nveeam-aiops backup list                    # stored backups: id, name, type, time\nveeam-aiops backup objects <backup_id>     # protected objects inside a backup\nveeam-aiops backup usage <name> [--json]   # backup storage one VM consumes, per backup (VBR 12.3+)\nveeam-aiops backup ranking [--limit 20] [--max-backups 100] [--backup <id|name> ...] \\\n    [--repository <id|name>] [--concurrency 1] [--json]  # largest consumers first; progress on stderr\n```\n\n## Infrastructure\n\n```bash\nveeam-aiops infra servers                  # managed servers: id, name, type\nveeam-aiops infra proxies                  # backup proxies: id, name, type, server\n```\n\n## Sessions (async progress)\n\n```bash\nveeam-aiops session list [--limit 100]     # newest sessions first: state, result\nveeam-aiops session get <session_id>       # poll one session (progressPercent)\nveeam-aiops session log <session_id>       # log records (events) of a session\nveeam-aiops session stop <session_id> [--dry-run]   # cancel — double confirm\n```\n\n## Diagnostics / RCA (read-only)\n\n```bash\nveeam-aiops diagnose job-failures [--limit 100] [--since-hours 24]  # triage recent failures; categorize cause\nveeam-aiops diagnose repo-capacity         # flag repositories low on free space (<15% / <10%)\n```\n\nBoth render worst-first findings, each citing the measured signal (session\nresult + matched error substring, or free% / free bytes) that tripped it.\n\n## Doctor & MCP\n\n```bash\nveeam-aiops doctor [--skip-auth]           # config + encrypted store + connectivity check\nveeam-aiops mcp                            # start the MCP server (stdio transport)\n```\n\n## Notes\n\n- `job start`, `job retry`, and `restore start` kick off **async sessions**.\n  Follow progress with `session list` / `session get` / `session log`, not by\n  re-issuing the command.\n- Destructive commands (`job stop`, `session stop`, `restore start`) require two\n  confirmations and accept `--dry-run` to preview the exact API call.\n- Credentials live in the encrypted store (`secrets.enc`); set them with\n  `veeam-aiops init` or `veeam-aiops secret set`. Export\n  `VEEAM_AIOPS_MASTER_PASSWORD` for non-interactive unlock.\n\nFile v0.16.0:references/setup-guide.md\n\n# veeam-aiops setup guide\n\n## Install\n\n```bash\nuv tool install veeam-aiops\n# or: pipx install veeam-aiops\n```\n\n## Configure (recommended: the wizard)\n\n```bash\nveeam-aiops init            # collects connection details + an encrypted password\nveeam-aiops doctor          # verifies config, encrypted store, connectivity\n```\n\n`init` writes `~/.veeam-aiops/config.yaml` (no secrets) and stores the login\npassword **encrypted** in `~/.veeam-aiops/secrets.enc` (Fernet + scrypt; chmod\n600). It prompts for a *master password* that unlocks the store; set it via\n`VEEAM_AIOPS_MASTER_PASSWORD` for non-interactive (MCP/CI) use.\n\nExample `~/.veeam-aiops/config.yaml`:\n\n```yaml\ntargets:\n  - name: vbr-lab\n    host: 10.0.0.20\n    username: \"DOMAIN\\\\backup-admin\"   # or a local account on the VBR server\n    port: 9419                          # Veeam REST API port (default)\n    verify_ssl: false                   # self-signed lab certs only; true in prod\n```\n\n### Manage credentials manually\n\n```bash\nveeam-aiops secret set vbr-lab         # prompts hidden for the password\nveeam-aiops secret list                # names only; values never shown\nveeam-aiops secret rotate-password     # re-encrypt under a new master password\nveeam-aiops secret migrate             # import a legacy plaintext .env, then archives it\n```\n\nSecret names map to target names. A legacy plaintext env var\n`VEEAM_<TARGET_NAME_UPPER>_PASSWORD` is still honoured as a fallback (with a\ndeprecation warning) — `secret migrate` imports it into the encrypted store.\n\n## Use as an MCP server\n\n```jsonc\n{\n  \"command\": \"veeam-aiops\",\n  \"args\": [\"mcp\"],\n  \"env\": {\n    \"VEEAM_AIOPS_CONFIG\": \"~/.veeam-aiops/config.yaml\",\n    \"VEEAM_AIOPS_MASTER_PASSWORD\": \"your-master-password\"\n  }\n}\n```\n\n`VEEAM_AIOPS_MASTER_PASSWORD` lets the server unlock `secrets.enc` without an\ninteractive prompt.\n\nUsing the `veeam-aiops mcp` subcommand (rather than `uvx --from`) means the MCP\nclient launches the already-installed entry point and does not re-resolve the\npackage over the network at startup.\n\n## Security\n\n> **Disclaimer**: Community-maintained project, **not affiliated with, endorsed\n> by, or sponsored by Veeam Software**. MIT licensed. See `SECURITY.md`.\n\n- **Credentials**: stored **encrypted** in `~/.veeam-aiops/secrets.enc`\n  (Fernet/AES-128 + scrypt-derived key, chmod 600) — never plaintext on disk.\n  The master password is never stored (only a per-store salt + ciphertext) and\n  comes from `VEEAM_AIOPS_MASTER_PASSWORD` or an interactive prompt. The login\n  password is exchanged for a short-lived OAuth2 bearer token at connect time\n  and kept only in memory.\n- **Audit**: every operation logged to a local SQLite DB under\n  `~/.veeam-aiops/` (relocate with `VEEAM_AIOPS_HOME`).\n- **Budget guard**: cap calls/wall-time with `VEEAM_MAX_TOOL_CALLS` /\n  `VEEAM_MAX_TOOL_SECONDS`; a runaway session-poll/retry loop trips automatically.\n- **Risk tier**: a descriptive label recorded on each audit row (derived from\n  `risk_level`); it gates nothing. `VEEAM_AUDIT_APPROVED_BY` /\n  `VEEAM_AUDIT_RATIONALE` are optional annotations recorded alongside it.\n- **Destructive ops**: `job stop`, `session stop`, and `restore start` require\n  double confirmation + support `--dry-run` at the CLI.\n- **TLS**: `verify_ssl` defaults true; disable only for self-signed labs.\n- **No webhooks / telemetry / background services.**\n\n## Least privilege\n\nCreate a dedicated Veeam Backup & Replication user with only the role your\nworkflows need (e.g. a restricted backup-operator role) rather than a full\nadministrator account.\n\nFile v0.16.0:skill-card.md\n\n## Description:\n\nVeeam AIops helps agents operate Veeam Backup & Replication for health checks, diagnostics, backup job operations, repository and backup inventory, session monitoring, and VM restore workflows.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[zw008](https://clawhub.ai/user/zw008)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers, operators, and backup administrators use this skill to let an agent inspect Veeam Backup & Replication state, triage failed backup sessions, manage backup jobs, review repository capacity, and guide restore workflows. It is intended for explicitly Veeam/VBR contexts and not for other backup products, hypervisors, Kubernetes, or cloud lifecycle management.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill can perform high-impact Veeam write and restore actions without an enforced MCP approval or read-only boundary.\n\nMitigation: Use a dedicated read-only or tightly restricted Veeam account by default, and allow write tools only through a separate operational approval process.\n\nRisk: Production use with verify_ssl:false could weaken TLS protection for Veeam API access.\n\nMitigation: Keep SSL verification enabled in production and reserve verify_ssl:false only for explicitly controlled self-signed lab environments.\n\nRisk: A legacy plaintext password fallback may expose credentials if retained.\n\nMitigation: Migrate credentials into the encrypted store and remove plaintext .env or environment fallback usage.\n\nRisk: Installing an unpinned or unaudited package version can make release contents harder to verify.\n\nMitigation: Prefer a pinned, audited package version or a verified source before deployment.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/zw008/skills/veeam-aiops)\n- [Project homepage](https://github.com/AIops-tools/Veeam-AIops)\n- [Capabilities](references/capabilities.md)\n- [Setup guide](references/setup-guide.md)\n- [CLI reference](references/cli-reference.md)\n- [Agent guardrails](references/agent-guardrails.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with CLI commands, configuration examples, and MCP tool-use instructions]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [The skill may guide agents through structured Veeam diagnostics and operations; some underlying MCP and CLI results can include JSON-like status, pagination, truncation, audit, dry-run, or undo metadata.]\n\n## Skill Version(s):\n\n0.16.0 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v0.15.3: 7 files, 23275 bytes\n\nFiles: references/agent-guardrails.md (9876b), references/capabilities.md (14913b), references/cli-reference.md (4015b), references/setup-guide.md (3570b), skill-card.md (3069b), SKILL.md (17076b), _meta.json (131b)\n\nFile v0.15.3:SKILL.md\n\n---\nname: veeam-aiops\nslug: veeam-aiops\ndisplayName: \"Veeam AIops\"\nsummary: \"Governed Veeam Backup & Replication ops — 27 MCP tools with audit, budget, undo guards.\"\nlicense: MIT\nhomepage: https://github.com/AIops-tools/Veeam-AIops\ntags: [aiops, mcp, governance, veeam]\ndescription: >\n  Use this skill whenever the user needs to operate Veeam Backup & Replication — a one-shot health overview, read-only diagnostics / RCA (triage failed backup-job sessions and flag repositories low on space), list/inspect/start/stop/retry backup jobs, enable/disable jobs, list restore points and start a VM restore, list backup repositories with capacity, list stored backups and their objects, inventory backup infrastructure (managed servers, proxies), and poll/stop async sessions for job/restore progress.\n  Always use this skill for \"list veeam jobs\", \"run veeam backup\", \"start veeam job\", \"veeam restore\", \"veeam repository\", \"veeam backup status\", or \"veeam session\" when the context is explicitly Veeam / Veeam Backup & Replication / VBR.\n  Do NOT use when the target is not Veeam Backup & Replication (other backup products, hypervisor lifecycle, or cloud providers are out of scope).\n  Common Veeam B&R operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers).\ninstaller:\n  kind: uv\n  package: veeam-aiops\nargument-hint: \"[job id or describe your Veeam task]\"\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"veeam-aiops\",\"uvx\"]},\"optional\":{\"env\":[\"VEEAM_AIOPS_CONFIG\",\"VEEAM_AIOPS_MASTER_PASSWORD\"]},\"homepage\":\"https://github.com/AIops-tools/Veeam-AIops\",\"emoji\":\"💾\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  Standalone, self-governed Veeam Backup & Replication operations. The governance harness (audit, policy, token/runaway budget, undo, risk-tiers) is bundled in the package — no external skill-family dependency.\n  All write operations are audited to a local SQLite DB under ~/.veeam-aiops/ (relocatable via VEEAM_AIOPS_HOME).\n  Credentials: Each Veeam target's login password is stored ENCRYPTED in ~/.veeam-aiops/secrets.enc (Fernet/AES-128 + scrypt-derived key) — never plaintext on disk. Run 'veeam-aiops init' to onboard, or 'veeam-aiops secret set <target>' to add one. The store is unlocked by a master password from VEEAM_AIOPS_MASTER_PASSWORD (non-interactive/MCP/CI) or an interactive prompt (CLI on a TTY). A legacy plaintext env var VEEAM_<TARGET_NAME_UPPER>_PASSWORD is still honoured as a fallback with a deprecation warning (migrate with 'veeam-aiops secret migrate'). The password is exchanged for a short-lived OAuth2 bearer token at connect time and held only in memory; passwords/tokens are never logged or echoed.\n  Destructive operations (job stop, session stop, restore start) require double confirmation at the CLI layer and support --dry-run. A dry_run MAY read (that is how it can tell you the call would be refused) but never writes, records no undo, and is audited like any other governed call; the CLI --dry-run routes through the same governed function as the MCP tool. All write tools pass through the @governed_tool decorator (budget guard + audit + risk-tier labelling). Reversible writes (job start/stop/retry, enable/disable) record an inverse undo descriptor; session stop and the VM restore are irreversible and record none.\n  Webhooks: none — no outbound network calls beyond the configured Veeam REST API endpoint.\n  SSL: verify_ssl defaults to true; disable only for self-signed lab certificates.\n  Transitive dependencies: httpx (HTTP client) and the MCP SDK. No post-install scripts or background services.\n---\n\n# Veeam AIops\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by Veeam Software.** \"Veeam\" is a trademark of its owner. Source code is publicly auditable at [github.com/AIops-tools/Veeam-AIops](https://github.com/AIops-tools/Veeam-AIops) under the MIT license.\n\nGoverned Veeam Backup & Replication operations — **27 MCP tools**, every one wrapped with the bundled `@governed_tool` harness: a local unified audit log under `~/.veeam-aiops/`, policy engine, token/runaway budget guard, undo-token recording, and descriptive risk tiers. Credentials are stored **encrypted** (`~/.veeam-aiops/secrets.enc`, Fernet + scrypt) — never plaintext on disk.\n\n> **Standalone**: the governance harness is bundled in the package (`veeam_aiops.governance`) — veeam-aiops has no external skill-family dependency. Coverage focuses on common Veeam operations and is not yet exhaustive.\n\n## What This Skill Does\n\n| Category | Tools | Count | Read or Write |\n|----------|-------|:-----:|:-------------:|\n| **Overview** | health overview | 1 | 1 read |\n| **Diagnostics / RCA** | job-failure triage, repository capacity | 2 | 2 read |\n| **Backup Jobs** | list, get, start, stop, retry, enable, disable | 7 | 2 read / 5 write |\n| **Restore** | list restore points (opt. per backup), start VM restore | 2 | 1 read / 1 write |\n| **Repositories** | list, get (detail), state (capacity) | 3 | 3 read |\n| **Backups** | list stored backups, list backup objects, per-VM storage usage, storage ranking | 4 | 4 read |\n| **Infrastructure** | managed servers, proxies | 2 | 2 read |\n| **Sessions** | list, get, log, stop (poll/cancel async progress) | 4 | 3 read / 1 write |\n\n## Quick Install\n\n```bash\nuv tool install veeam-aiops\nveeam-aiops init       # interactive wizard: connection + encrypted password\nveeam-aiops doctor\n```\n\nOr as an OpenClaw plugin, which installs this skill and its MCP server together:\n\n```bash\nopenclaw plugins install clawhub:@zw008/veeam-aiops\nopenclaw skills info veeam-aiops          # expect: Visible to model: yes\n```\n\nNeeds `uvx` on `PATH`: the MCP server is fetched with uv, pinned to this release.\n\n## When to Use This Skill\n\n- List/inspect Veeam backup jobs and their last result\n- Start or stop a backup job on demand\n- Enable or disable a job's schedule\n- List available restore points and start a VM restore\n- List backup repositories and stored backups\n- Report how much backup storage a VM consumes (showback/chargeback input) and which VMs cost the most to protect\n- Poll async sessions to follow job/restore progress\n\n**Do NOT use when** the target is not Veeam Backup & Replication (other backup products, hypervisor VM lifecycle, Kubernetes, or cloud providers are out of scope for this skill).\n\n## Related Skills — Skill Routing\n\n| If the user wants… | Use |\n|--------------------|-----|\n| Veeam backup jobs / restore / repositories | **veeam-aiops** (this skill) |\n| Hypervisor VM lifecycle (power, snapshot, migrate) | a hypervisor ops skill |\n| Container/cluster lifecycle | a cluster ops skill |\n\n## Common Workflows\n\n### Diagnose why last night's backups failed\n\n1. `veeam-aiops diagnose job-failures --since-hours 24` → worst-first table of Failed/Warning sessions, each with the categorized cause (repository full / source unreachable / credential-VSS / retry exhaustion) and the cited failing log line\n2. If a finding says **repository full**, confirm with `veeam-aiops diagnose repo-capacity` → the flagged repo's measured free% and free bytes\n3. Fix the root cause (extend/offload the repository, restore source connectivity, or repair guest credentials/VSS), then `veeam-aiops job retry <job_id>` to re-run only the failed objects\n4. `veeam-aiops session list` → `veeam-aiops session get <session_id>` to confirm the retry completes — do not tight-loop `session get` (the runaway budget guard will trip it)\n\n### Run a backup job and follow it to completion\n\n1. `veeam-aiops job list` → find the job id and confirm `lastResult`\n2. `veeam-aiops job start <job_id>` → starts the job (records an inverse `job_stop` undo descriptor)\n3. `veeam-aiops session list` → find the running session; `veeam-aiops session get <session_id>` → check `state` / `progressPercent`\n4. **Failure branch**: if `session get` shows the session `Failed`, inspect `result`, then re-run `job start` after fixing the cause — do not loop `session get` rapidly (the runaway budget guard will trip a tight poll loop).\n\n### Showback: how much backup storage does a VM consume?\n\n1. `veeam-aiops backup usage <vm-name>` → per backup (primary job and each backup copy): repository, restore points, stored / full / incremental bytes, shared bytes, job retention\n2. Read the caveats before quoting a number: files that hold **several** machines are reported as shared and never added to the VM's total; on block-clone repositories (ReFS / XFS fast clone) the stored total is an upper bound\n3. `veeam-aiops backup ranking --limit 20` → which machines consume the most backup storage, largest first; raise `--max-backups` if `backupsTruncated` is true\n4. Apply your own storage price to the bytes — this tool reports consumption only. **Needs VBR 12.3 or later**; older servers get a clear refusal naming the minimum build.\n\n### Restore a VM from a restore point\n\n1. `veeam-aiops restore list-points` → identify the correct restore point id\n2. `veeam-aiops restore start --restore-point-id <id> --dry-run` → preview the exact API call **and the VM name + creation time** the id resolves to — never approve a restore from a GUID\n3. `veeam-aiops restore start --restore-point-id <id>` → double confirmation required; this is IRREVERSIBLE (overwrites/creates a VM) and records no undo token. Refused outright if the VM name matches the configured VBR host (an in-place overwrite of the backup server itself) — a name-based safety net, not a proof, so confirm the target yourself\n4. **Failure branch**: if `doctor` shows the VBR server unreachable or the password env var is missing, fix `~/.veeam-aiops/.env` (chmod 600) before retrying — the restore is never issued against an unauthenticated session.\n\n## Usage Mode\n\n| Scenario | Recommended | Why |\n|----------|:-----------:|-----|\n| Local/small models | **CLI** | fewer tokens than MCP |\n| Cloud models (Claude, GPT) | Either | MCP gives structured JSON I/O |\n| Automated pipelines | **MCP** | type-safe parameters, audited |\n\n## MCP Tools (27 — 19 read, 8 write)\n\n| Category | Tools | R/W |\n|----------|-------|:---:|\n| Overview | `overview` | Read |\n| Diagnostics / RCA | `job_failure_rca`, `repository_capacity_rca` | Read |\n| Backup Jobs | `job_list`, `job_get` | Read |\n| | `job_start`, `job_stop`, `job_retry`, `job_enable`, `job_disable` | Write |\n| Restore | `restore_list_points` | Read |\n| | `start_vm_restore` | Write |\n| Repositories | `repository_list`, `repository_get`, `repository_state` | Read |\n| Backups | `backup_list`, `backup_object_list`, `backup_object_storage_usage`, `backup_storage_ranking` | Read |\n| Infrastructure | `managed_server_list`, `proxy_list` | Read |\n| Sessions | `session_list`, `session_get`, `session_log` | Read |\n| | `session_stop` | Write |\n| Undo | `undo_list` | Read |\n| | `undo_apply` | Write |\n\n**Harness features that light up**: write tools with a clean inverse (`job_start`↔`job_stop`, `job_retry`→`job_stop`, `job_enable`↔`job_disable`) pass an `undo=` lambda so the harness records an inverse descriptor (with `_undo_id`) to the undo store. The irreversible `start_vm_restore` and `session_stop` declare no undo; `start_vm_restore` is tagged `risk_level=high`. All 27 tools are audit-logged under `~/.veeam-aiops/` and pass through the budget/runaway guard, each row carrying a descriptive risk tier. Veeam jobs/restores run as async sessions — poll with `session_get` / `session_log` instead of re-issuing (the runaway breaker backs this up). Start any triage with `overview` (jobs by last result, repos near full, running sessions), then drill in with `job_failure_rca` (categorizes failing sessions with cited error substrings) and `repository_capacity_rca` (cited free%).\n\n## CLI Quick Reference\n\n```bash\nveeam-aiops init                                      # onboarding wizard (encrypted password)\nveeam-aiops overview [--target <t>]                   # health summary\nveeam-aiops diagnose job-failures [--target <t>]      # RCA: triage failed job sessions\nveeam-aiops diagnose repo-capacity [--target <t>]     # RCA: repos low on free space\nveeam-aiops job list [--target <t>]\nveeam-aiops job get <job_id>\nveeam-aiops job start <job_id>\nveeam-aiops job stop <job_id> [--dry-run]              # double confirm\nveeam-aiops job retry <job_id>\nveeam-aiops job enable <job_id>\nveeam-aiops job disable <job_id>\nveeam-aiops restore list-points [--backup-id <id>] [--limit 100]\nveeam-aiops restore start --restore-point-id <id> [--dry-run]   # double confirm\nveeam-aiops repository list\nveeam-aiops repository get <repository_id>\nveeam-aiops repository state                           # capacity / free / used%\nveeam-aiops session list [--limit 100]\nveeam-aiops session get <session_id>\nveeam-aiops session log <session_id>\nveeam-aiops session stop <session_id> [--dry-run]     # double confirm\nveeam-aiops backup list\nveeam-aiops backup objects <backup_id>\nveeam-aiops infra servers\nveeam-aiops infra proxies\nveeam-aiops secret set <target>                        # store password encrypted\nveeam-aiops secret list                               # names only\nveeam-aiops secret migrate                            # import legacy plaintext .env\nveeam-aiops secret rotate-password\nveeam-aiops doctor\nveeam-aiops mcp                                        # start MCP server (stdio)\n```\n\nSee `references/cli-reference.md` for the full command list.\n\n## Troubleshooting\n\n### \"Config file not found\"\nRun `veeam-aiops init` to set up your first target (writes `~/.veeam-aiops/config.yaml` and stores the password encrypted).\n\n### \"No password for target '<name>'\"\nAdd it to the encrypted store: `veeam-aiops secret set <name>` (prompts hidden), or run `veeam-aiops init`. For non-interactive use (MCP/CI), also export `VEEAM_AIOPS_MASTER_PASSWORD` so the store can be unlocked without a prompt.\n\n### \"Master password not set\" / \"Wrong master password\"\nThe encrypted store `~/.veeam-aiops/secrets.enc` is unlocked by `VEEAM_AIOPS_MASTER_PASSWORD` (or an interactive prompt). If you forgot it, delete `secrets.enc` and re-run `veeam-aiops init`. Rotate it with `veeam-aiops secret rotate-password`.\n\n### \"Authentication/authorization failed (401)\"\nThe username/password is wrong, or the account lacks a Veeam role. Veeam usernames are typically `DOMAIN\\\\user` or a local Windows account on the VBR server. Confirm the account can log in to the Veeam console.\n\n### \"Could not reach Veeam server … check the host/port\"\nThe default REST API port is 9419 — confirm the Veeam Backup & Replication REST API service is running and the port is open. For self-signed certificates set `verify_ssl: false` on the target (lab only).\n\n### \"Resource not found (404)\"\nThe job/session/restore-point id is stale. List the parent collection first (`job list`, `session list`, `restore list-points`) to get a current id.\n\n## Governance & Safety\n\nThe skill delivers reads and writes and records them; it does **not** decide\nwhether a write is permitted. That is your agent's judgement, or the permission\nof the Veeam account you connect it with (a read-only or restricted role on the\nVBR server — writes then fail at the server). There is no read-only switch,\npolicy file, or approval gate.\n\n- Credentials stored **encrypted** in `~/.veeam-aiops/secrets.enc` (Fernet/AES-128 + scrypt key derivation; chmod 600) — never plaintext on disk; the master password is never stored, only a per-store salt + ciphertext\n- **Audit is the guarantee, and it is not bypassable.** Every operation — MCP and CLI alike — is logged to `~/.veeam-aiops/audit.db` (relocatable via `VEEAM_AIOPS_HOME`): params (secrets redacted), result, status, duration, and the risk tier. The CLI writes the same row the MCP path does.\n- `VEEAM_AUDIT_APPROVED_BY` / `VEEAM_AUDIT_RATIONALE` are optional annotations recorded on the audit row (who/why); they are never required and never block.\n- **Runaway guard** — a safety backstop, not authorization: cumulative tool calls and wall-time are capped, and the same call looped in a tight session-poll/retry window trips a circuit breaker.\n- Writes support `--dry-run` / `dry_run=True` and double confirmation at the CLI; CLI writes execute through the same governed tools, so they are audited + undo-recorded.\n- Reversible writes (job start/stop/retry, enable/disable) record an inverse undo descriptor; the irreversible `start_vm_restore` and `session_stop` record none.\n\nThe harness is bundled in the package — no external dependency, no manual setup. See `references/setup-guide.md` for security details.\n\n## Contributing & feature requests\n\nCoverage is intentionally focused. **Missing a device, action, or feature you need?** Open an issue or pull request at [github.com/AIops-tools/Veeam-AIops](https://github.com/AIops-tools/Veeam-AIops/issues) — feature requests, contributions, and comments are all welcome.\n\n## License\n\nMIT — [github.com/AIops-tools/Veeam-AIops](https://github.com/AIops-tools/Veeam-AIops)\n\nFile v0.15.3:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"veeam-aiops\",\n  \"version\": \"0.15.3\",\n  \"publishedAt\": 1789224500499\n}\n\nFile v0.15.3:references/agent-guardrails.md\n\n# Agent guardrails — running veeam-aiops with a smaller / local model\n\nIf you drive these tools with a local model (Llama, Qwen, Mistral … via Goose,\nOllama, LM Studio, or any OpenAI-compatible runtime), you will get noticeably\nbetter results with a short system prompt. This page gives you one, and — more\nimportantly — tells you which guardrails you **no longer need to write**, because\nthe tool now enforces them itself.\n\nThe distinction matters. A guardrail in a prompt is a request. A guardrail in the\nharness is a guarantee. Anything below that we could move into the harness, we did.\n\n## Authorization is not this tool's job — decide it where it belongs\n\nWhether a write should happen is your decision, or the account's. The tool does\nnot gate it — there is no read-only switch and no approval prompt to configure.\nThe two right places to control read vs write:\n\n- **The account you connect with.** Give the Veeam account you connect with a\n  read-only or restricted role on the VBR server. A write then fails at the\n  server, which is the only place the permission actually lives — a revoked\n  permission cannot be argued around by a model, but a skill-side flag can.\n- **Your agent's system prompt.** If you want an observe-only session, tell the\n  model not to call the write tools (they are clearly tagged `[WRITE]`).\n\nWhat the tool *does* guarantee is that you can always see what happened:\n\n## What the tool enforces — do not waste prompt budget on these\n\n| You might be tempted to prompt | Why you don't need to |\n|---|---|\n| \"Don't invent a value when a field is missing\" | A field the VBR API did not return comes back as `null`, never as `\"\"`. A job with no `lastResult` yet, a session with no verdict, a proxy with no reported host — all report `null`, and only a genuinely empty upstream value comes back as `\"\"`. Absent and empty are distinguishable in the payload. |\n| \"Tell me if the output was cut off\" | The reads that can be too large to return whole — `restore_list_points`, `session_list`, `undo_list`, and `backup_storage_ranking` — return an envelope such as `{\"restorePoints\": [...], \"returned\": N, \"limit\": L, \"truncated\": true/false}`, newest first where time matters. Truncation is measured (one extra row is fetched), not guessed from a length coincidence. Every other list read pages through the whole collection — the VBR server may cap a page at 200 items (Veeam's spec default from revision 1.3) — and refuses with an error rather than returning a partial list if the server stops short. |\n| \"Preserve the ordering / tell me what's most urgent\" | `job_failure_rca` and `repository_capacity_rca` findings carry an explicit 1-based `rank`, worst-first. Priority is in the payload, not implied by list position. |\n| \"Explain why you flagged that repository / job\" | Every finding carries the measured signal that tripped it — the session `result` and the matched error substring, or the free-space percentage against the threshold — plus a concrete `cause` and `action`. The heuristics are transparent, not a verdict. |\n| \"Confirm before anything destructive\" | `job_stop`, `session_stop` and `restore start` require a `--dry-run`-able preview plus double confirmation at the CLI; the MCP write tools take `dry_run=True`. `start_vm_restore` is tagged `high` risk. |\n| \"Remember how to put it back\" | Writes with a clean inverse (`job_start`/`job_stop`, `job_enable`/`job_disable`, `job_retry`) record an undo token — list them with `undo_list`, replay with `undo_apply`. The irreversible ones (`start_vm_restore`, `session_stop`) record none and say so. |\n| \"Log what you did\" | Every governed call is audited to `~/.veeam-aiops/audit.db` regardless of what the model says it did — and the CLI writes the same row the MCP path does, so there is no unaudited entry point. |\n| \"Don't get stuck retrying\" | The runaway guard trips a circuit breaker if the same call is hammered in a tight loop (e.g. re-issuing a job instead of polling its session) — a stuck agent is stopped rather than left to burn calls and time. |\n\n## What still needs a prompt\n\nThese are model-behaviour problems the harness cannot fix from the outside.\nCopy this into your agent's system prompt:\n\n```text\nYou operate a Veeam Backup & Replication environment through the veeam-aiops\nMCP tools.\n\nTOOL USE\n- Before answering any question about the current Veeam environment, you MUST\n  call a tool. Never answer from memory or assumption.\n- Actually invoke the tool. Do not describe the call you would make, and do not\n  emit an example JSON response in place of calling it.\n- If a tool call fails, report the real error verbatim. Never fill the gap with\n  a plausible-sounding answer.\n\nREADING RESULTS\n- Read the whole result before concluding. If a result contains a \"truncated\"\n  field that is true, say so and re-run with a higher limit instead of treating\n  the partial result as complete.\n- A null field means the VBR API did not return that value. Report it as \"not\n  available\" — never infer it. A session with a null result has not finished,\n  which is not the same as having succeeded.\n- Report values exactly as returned. Do not normalise, translate, or prettify\n  job status strings, session results (Success / Warning / Failed / None), or\n  identifiers.\n- When a diagnose result has findings, work in \"rank\" order and cite the\n  measured number in each finding's \"detail\".\n\nSCOPE\n- Separate observation from interpretation. State what the tools returned, then\n  any interpretation, clearly marked as such.\n- Do not assert a backup failure, a capacity problem, or a missed RPO unless a\n  tool result supports it.\n- Do not add generic advice that does not follow from the tool output.\n- Do not confuse a job id with a session id, a session id with a restore point\n  id, or a backup id with the repository it lives on. They are different\n  objects with different tools.\n```\n\n## Recommended setup for a local model\n\nStart with a connection that *cannot* write, verify, and widen the account's\npermission only when you trust the setup — a restore or a stopped job on the\nwrong target is not something you want a smaller model reaching for on day one:\n\n```bash\n# e.g. connect with a Veeam account that has a read-only or restricted role on\n# the VBR server. Then:\nveeam-aiops doctor\n```\n\nOptionally annotate the audit trail with who is operating and why — recorded on\nevery row, never required:\n\n```bash\nexport VEEAM_AUDIT_APPROVED_BY=\"your.name@example.com\"\nexport VEEAM_AUDIT_RATIONALE=\"scheduled maintenance window 2026-07-20\"\n```\n\n## Veeam-specific notes\n\nThese are the places a smaller model most often goes wrong against a VBR server,\nand what to do about them:\n\n- **Jobs and restores are asynchronous.** `job_start`, `job_retry` and\n  `start_vm_restore` return immediately; the work happens in a *session*. Progress\n  belongs to `session_get`, not to the job. Tell the model to start once and poll\n  the session — the runaway budget guard will trip on a re-issue loop, but a\n  wasted trip is still a wasted trip.\n- **Four id namespaces look alike.** Job ids, session ids, backup ids and restore\n  point ids are all opaque strings. `backup_object_list` takes a *backup* id;\n  `restore_list_points` filters by a *backup* id and returns *restore point* ids;\n  `start_vm_restore` takes a *restore point* id. Models routinely pass the wrong\n  one — prefer chaining the tools (`backup_list` → `restore_list_points`) over\n  letting the model reconstruct an id.\n- **\"Warning\" is a real failure state.** A Veeam session result of `Warning` is\n  flagged by `job_failure_rca` alongside `Failed`. A model that treats Warning as\n  success will report a healthy backup estate that isn't one.\n- **A disabled job is not a failing job.** `job_list` reports `isDisabled`\n  separately from `lastResult`; a disabled job simply has not run.\n- **`start_vm_restore` cannot be undone.** It overwrites or creates a VM and\n  records no undo token. It is `high` risk deliberately. It is also a documented\n  skeleton: the exact endpoint and payload differ per\n  restore type (instant recovery vs full restore vs restore-to-new-location) and\n  per Veeam version, so validate it against your environment before trusting it.\n- **Always read the `dry_run` preview before approving a restore.** It names the\n  VM and creation time behind the restore-point GUID. The tool refuses a restore\n  whose VM name matches the configured VBR host — an in-place overwrite of the\n  backup server itself — but that check compares a display name to a hostname, so\n  **it will miss a VBR server named anything else**. Separately, when the\n  restore point cannot be read at all the restore is REFUSED, because nothing\n  can then say which machine would be overwritten; pass\n  `acknowledge_unresolved=True` only after confirming the target in the Veeam\n  console.\n\n## If your model still struggles\n\nSome behaviours are model-capacity limits rather than prompt problems:\n\n- **Multi-tool workflows time out or drift.** Prefer `overview` and the\n  `*_rca` diagnose tools — they do the multi-step correlation inside one call, so\n  the model does not have to chain reads and keep job/session ids straight.\n- **The model ignores later tool results in a long context.** Ask narrower\n  questions; use `job_get` / `session_get` on one object rather than pulling the\n  whole session list and reasoning over it.\n- **The model describes calls instead of making them.** This is usually a\n  runtime/tool-calling-format mismatch, not a prompt problem — check that your\n  client advertises the tools in the format your model was trained on.\n\nFeedback on running this with a specific local model is genuinely useful —\nopen an issue at\n[github.com/AIops-tools/Veeam-AIops](https://github.com/AIops-tools/Veeam-AIops/issues)\nwith the model, runtime, and what went wrong.\n\nFile v0.15.3:references/capabilities.md\n\n# veeam-aiops capabilities\n\n27 MCP tools (19 read, 8 write), each wrapped with the bundled `@governed_tool`\nharness. Typical response token estimates assume a small/medium environment.\n\n## Overview (1 — read)\n\n| Tool | R/W | Risk | Typical response tokens |\n|------|:---:|:----:|:----------------------:|\n| `overview` | R | low | ~150 |\n\nFan-out health summary: jobs grouped by last result, repositories at/above 85%\nused, and currently-running sessions. Call this first to triage an environment.\n\n## Diagnostics / RCA (2 — read)\n\n| Tool | R/W | Risk | Typical response tokens |\n|------|:---:|:----:|:----------------------:|\n| `job_failure_rca` | R | low | ~200–600 |\n| `repository_capacity_rca` | R | low | ~150 |\n\n`job_failure_rca` scans the newest `limit` sessions (default 100, newest first by\n`creationTime`; `sessionsTruncated` says older ones exist) — pass `since_hours=24`\nto make the window \"the last day\" instead — flags every Failed/Warning run, and\ncategorizes the likely cause (repository full, source/guest unreachable,\ncredential/VSS failure, retry exhaustion) from the failing log records — each\nfinding cites the session result + matched error substring, worst-first.\n`repository_capacity_rca` flags repositories under the free-space thresholds\n(<15% warn, <10% critical), citing the measured free% and free bytes.\n\n## Backup Jobs (7 — 2 read, 5 write)\n\n| Tool | R/W | Risk | Undo | Typical response tokens |\n|------|:---:|:----:|------|:----------------------:|\n| `job_list` | R | low | — | 150–600 (depends on job count) |\n| `job_get` | R | low | — | ~120 |\n| `job_start` | W | medium | `job_stop` | ~50 |\n| `job_stop` | W | medium | `job_start` | ~50 |\n| `job_retry` | W | medium | `job_stop` | ~50 |\n| `job_enable` | W | medium | `job_disable` | ~40 |\n| `job_disable` | W | medium | `job_enable` | ~40 |\n\nREST endpoints: `GET /api/v1/jobs`, `GET /api/v1/jobs/{id}`,\n`POST /api/v1/jobs/{id}/{start|stop|retry|enable|disable}`. The write tools\ncapture the job's prior status/lastResult for context.\n\n## Restore (2 — 1 read, 1 write)\n\n| Tool | R/W | Risk | Undo | Typical response tokens |\n|------|:---:|:----:|------|:----------------------:|\n| `restore_list_points` | R | low | — | 150–800 |\n| `start_vm_restore` | W | high | **none — irreversible** | ~40 |\n\n`restore_list_points` returns the newest `limit` points (default 100, max 1000) as\n`{\"restorePoints\", \"returned\", \"limit\", \"truncated\", \"order\"}` — an estate's restore\npoints are far too many to return whole. With `backup_id`, a point from another\nbackup coming back means the server ignored the filter, and that is refused.\n\nREST endpoints: `GET /api/v1/restorePoints` (`orderColumn=CreationTime&orderAsc=false`,\noptional `backupIdFil\n\nArchive v0.15.2: 7 files, 23000 bytes\n\nFiles: references/agent-guardrails.md (9876b), references/capabilities.md (14913b), references/cli-reference.md (4015b), references/setup-guide.md (3570b), skill-card.md (2444b), SKILL.md (17082b), _meta.json (131b)\n\nArchive v0.15.1: 7 files, 22952 bytes\n\nFiles: references/agent-guardrails.md (10042b), references/capabilities.md (14349b), references/cli-reference.md (4015b), references/setup-guide.md (3570b), skill-card.md (2676b), SKILL.md (17082b), _meta.json (131b)\n\nArchive v0.15.0: 7 files, 23131 bytes\n\nFiles: references/agent-guardrails.md (10042b), references/capabilities.md (14349b), references/cli-reference.md (4015b), references/setup-guide.md (3570b), skill-card.md (3251b), SKILL.md (17082b), _meta.json (131b)\n\nArchive v0.14.0: 7 files, 22532 bytes\n\nFiles: references/agent-guardrails.md (10042b), references/capabilities.md (13383b), references/cli-reference.md (4015b), references/setup-guide.md (3570b), skill-card.md (3002b), SKILL.md (16772b), _meta.json (131b)\n\nArchive v0.13.1: 7 files, 22570 bytes\n\nFiles: references/agent-guardrails.md (10042b), references/capabilities.md (13383b), references/cli-reference.md (4015b), references/setup-guide.md (3570b), skill-card.md (3149b), SKILL.md (16874b), _meta.json (131b)\n\nArchive v0.13.0: 7 files, 22430 bytes\n\nFiles: references/agent-guardrails.md (10042b), references/capabilities.md (13277b), references/cli-reference.md (4015b), references/setup-guide.md (3570b), skill-card.md (2942b), SKILL.md (16874b), _meta.json (131b)\n\nArchive v0.12.0: 7 files, 21623 bytes\n\nFiles: references/agent-guardrails.md (9778b), references/capabilities.md (11363b), references/cli-reference.md (3980b), references/setup-guide.md (3570b), skill-card.md (3045b), SKILL.md (16829b), _meta.json (131b)","readmeExcerpt":"Skill: veeam-aiops Owner: zw008 Summary: Use this skill whenever the user needs to operate Veeam Backup & Replication — a one-shot health overview, read-only diagnostics / RCA (triage failed backup-job sessions and flag repositories low on space), list/inspect/start/stop/retry backup jobs, enable/disable jobs, list restore points and start a VM restore, list backup repositories with capacity, list stored backups and ","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"uv tool install veeam-aiops\nveeam-aiops init       # interactive wizard: connection + encrypted password\nveeam-aiops doctor"},{"language":"bash","snippet":"openclaw plugins install clawhub:@zw008/veeam-aiops\nopenclaw skills info veeam-aiops          # expect: Visible to model: yes"},{"language":"bash","snippet":"veeam-aiops init                                      # onboarding wizard (encrypted password)\nveeam-aiops overview [--target <t>]                   # health summary\nveeam-aiops diagnose job-failures [--target <t>]      # RCA: triage failed job sessions\nveeam-aiops diagnose repo-capacity [--target <t>]     # RCA: repos low on free space\nveeam-aiops job list [--target <t>]\nveeam-aiops job get <job_id>\nveeam-aiops job start <job_id>\nveeam-aiops job stop <job_id> [--dry-run]              # double confirm\nveeam-aiops job retry <job_id>\nveeam-aiops job enable <job_id>\nveeam-aiops job disable <job_id>\nveeam-aiops restore list-points [--backup-id <id>] [--limit 100]\nveeam-aiops restore start --restore-point-id <id> [--dry-run]   # double confirm\nveeam-aiops repository list\nveeam-aiops repository get <repository_id>\nveeam-aiops repository state                           # capacity / free / used%\nveeam-aiops session list [--limit 100]\nveeam-aiops session get <session_id>\nveeam-aiops session log <session_id>\nveeam-aiops session stop <session_id> [--dry-run]     # double confirm\nveeam-aiops backup list\nveeam-aiops backup objects <backup_id>\nveeam-aiops infra servers\nveeam-aiops infra proxies\nveeam-aiops secret set <target>                        # store password encrypted\nveeam-aiops secret list                               # names only\nveeam-aiops secret migrate                            # import legacy plaintext .env\nveeam-aiops secret rotate-password\nveeam-aiops doctor\nveeam-aiops mcp                                        # start MCP server (stdio)"},{"language":"text","snippet":"You operate a Veeam Backup & Replication environment through the veeam-aiops\nMCP tools.\n\nTOOL USE\n- Before answering any question about the current Veeam environment, you MUST\n  call a tool. Never answer from memory or assumption.\n- Actually invoke the tool. Do not describe the call you would make, and do not\n  emit an example JSON response in place of calling it.\n- If a tool call fails, report the real error verbatim. Never fill the gap with\n  a plausible-sounding answer.\n\nREADING RESULTS\n- Read the whole result before concluding. If a result contains a \"truncated\"\n  field that is true, say so and re-run with a higher limit instead of treating\n  the partial result as complete.\n- A null field means the VBR API did not return that value. Report it as \"not\n  available\" — never infer it. A session with a null result has not finished,\n  which is not the same as having succeeded.\n- Report values exactly as returned. Do not normalise, translate, or prettify\n  job status strings, session results (Success / Warning / Failed / None), or\n  identifiers.\n- When a diagnose result has findings, work in \"rank\" order and cite the\n  measured number in each finding's \"detail\".\n\nSCOPE\n- Separate observation from interpretation. State what the tools returned, then\n  any interpretation, clearly marked as such.\n- Do not assert a backup failure, a capacity problem, or a missed RPO unless a\n  tool result supports it.\n- Do not add generic advice that does not follow from the tool output.\n- Do not confuse a job id with a session id, a session id with a restore point\n  id, or a backup id with the repository it lives on. They are different\n  objects with different tools."},{"language":"bash","snippet":"# e.g. connect with a Veeam account that has a read-only or restricted role on\n# the VBR server. Then:\nveeam-aiops doctor"},{"language":"bash","snippet":"export VEEAM_AUDIT_APPROVED_BY=\"your.name@example.com\"\nexport VEEAM_AUDIT_RATIONALE=\"scheduled maintenance window 2026-07-20\""}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: veeam-aiops\nslug: veeam-aiops\ndisplayName: \"Veeam AIops\"\nsummary: \"Governed Veeam Backup & Replication ops — 27 MCP tools with audit, budget, undo guards.\"\nlicense: MIT\nhomepage: https://github.com/AIops-tools/Veeam-AIops\ntags: [aiops, mcp, governance, veeam]\ndescription: >\n  Use this skill whenever the user needs to operate Veeam Backup & Replication — a one-shot health overview, read-only diagnostics / RCA (triage failed backup-job sessions and flag repositories low on space), list/inspect/start/stop/retry backup jobs, enable/disable jobs, list restore points and start a VM restore, list backup repositories with capacity, list stored backups and their objects, inventory backup infrastructure (managed servers, proxies), and poll/stop async sessions for job/restore progress.\n  Always use this skill for \"list veeam jobs\", \"run veeam backup\", \"start veeam job\", \"veeam restore\", \"veeam repository\", \"veeam backup status\", or \"veeam session\" when the context is explicitly Veeam / Veeam Backup & Replication / VBR.\n  Do NOT use when the target is not Veeam Backup & Replication (other backup products, hypervisor lifecycle, or cloud providers are out of scope).\n  Common Veeam B&R operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers).\ninstaller:\n  kind: uv\n  package: veeam-aiops\nargument-hint: \"[job id or describe your Veeam task]\"\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"veeam-aiops\",\"uvx\"]},\"optional\":{\"env\":[\"VEEAM_AIOPS_CONFIG\",\"VEEAM_AIOPS_MASTER_PASSWORD\"]},\"homepage\":\"https://github.com/AIops-tools/Veeam-AIops\",\"emoji\":\"💾\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  Standalone, self-governed Veeam Backup & Replication operations. The governance harness (audit, policy, token/runaway budget, undo, risk-tiers) is bundled in the package — no external skill-family dependency.\n  All write operations are audited to a local SQLite DB under ~/.veeam-aiops/ (relocatable via VEEAM_AIOPS_HOME).\n  Credentials: Each Veeam target's login password is stored ENCRYPTED in ~/.veeam-aiops/secrets.enc (Fernet/AES-128 + scrypt-derived key) — never plaintext on disk. Run 'veeam-aiops init' to onboard, or 'veeam-aiops secret set <target>' to add one. The store is unlocked by a master password from VEEAM_AIOPS_MASTER_PASSWORD (non-interactive/MCP/CI) or an interactive prompt (CLI on a TTY). A legacy plaintext env var VEEAM_<TARGET_NAME_UPPER>_PASSWORD is still honoured as a fallback with a deprecation warning (migrate with 'veeam-aiops secret migrate'). The password is exchanged for a short-lived OAuth2 bearer token at connect time and held only in memory; passwords/tokens are never logged or echoed.\n  Destructive operations (job stop, session stop, restore start) require double confirmation at the CLI layer and support --dry-run. A dry_run MAY read (that is how it can tell you the call would be refused) but never writes, records no undo, and is audited like any other governed call; the CLI --d"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"veeam-aiops\",\n  \"version\": \"0.16.1\",\n  \"publishedAt\": 1789453369149\n}"},{"path":"references/agent-guardrails.md","content":"# Agent guardrails — running veeam-aiops with a smaller / local model\n\nIf you drive these tools with a local model (Llama, Qwen, Mistral … via Goose,\nOllama, LM Studio, or any OpenAI-compatible runtime), you will get noticeably\nbetter results with a short system prompt. This page gives you one, and — more\nimportantly — tells you which guardrails you **no longer need to write**, because\nthe tool now enforces them itself.\n\nThe distinction matters. A guardrail in a prompt is a request. A guardrail in the\nharness is a guarantee. Anything below that we could move into the harness, we did.\n\n## Authorization is not this tool's job — decide it where it belongs\n\nWhether a write should happen is your decision, or the account's. The tool does\nnot gate it — there is no read-only switch and no approval prompt to configure.\nThe two right places to control read vs write:\n\n- **The account you connect with.** Give the Veeam account you connect with a\n  read-only or restricted role on the VBR server. A write then fails at the\n  server, which is the only place the permission actually lives — a revoked\n  permission cannot be argued around by a model, but a skill-side flag can.\n- **Your agent's system prompt.** If you want an observe-only session, tell the\n  model not to call the write tools (they are clearly tagged `[WRITE]`).\n\nWhat the tool *does* guarantee is that you can always see what happened:\n\n## What the tool enforces — do not waste prompt budget on these\n\n| You might be tempted to prompt | Why you don't need to |\n|---|---|\n| \"Don't invent a value when a field is missing\" | A field the VBR API did not return comes back as `null`, never as `\"\"`. A job with no `lastResult` yet, a session with no verdict, a proxy with no reported host — all report `null`, and only a genuinely empty upstream value comes back as `\"\"`. Absent and empty are distinguishable in the payload. |\n| \"Tell me if the output was cut off\" | The reads that can be too large to return whole — `restore_list_points`, `session_list`, `undo_list`, and `backup_storage_ranking` — return an envelope such as `{\"restorePoints\": [...], \"returned\": N, \"limit\": L, \"truncated\": true/false}` (the ranking also says `scoped` / `backupsTruncated` when it covers only a selection or a scanned subset), newest first where time matters. Truncation is measured (one extra row is fetched), not guessed from a length coincidence. Every other list read pages through the whole collection — the VBR server may cap a page at 200 items (Veeam's spec default from revision 1.3) — and refuses with an error rather than returning a partial list if the server stops short. |\n| \"Preserve the ordering / tell me what's most urgent\" | `job_failure_rca` and `repository_capacity_rca` findings carry an explicit 1-based `rank`, worst-first. Priority is in the payload, not implied by list position. |\n| \"Explain why you flagged that repository / job\" | Every finding carries the measured signal that tripped it — the session `result` and the matc"},{"path":"references/capabilities.md","content":"# veeam-aiops capabilities\n\n27 MCP tools (19 read, 8 write), each wrapped with the bundled `@governed_tool`\nharness. Typical response token estimates assume a small/medium environment.\n\n## Overview (1 — read)\n\n| Tool | R/W | Risk | Typical response tokens |\n|------|:---:|:----:|:----------------------:|\n| `overview` | R | low | ~150 |\n\nFan-out health summary: jobs grouped by last result, repositories at/above 85%\nused, and currently-running sessions. Call this first to triage an environment.\n\n## Diagnostics / RCA (2 — read)\n\n| Tool | R/W | Risk | Typical response tokens |\n|------|:---:|:----:|:----------------------:|\n| `job_failure_rca` | R | low | ~200–600 |\n| `repository_capacity_rca` | R | low | ~150 |\n\n`job_failure_rca` scans the newest `limit` sessions (default 100, newest first by\n`creationTime`; `sessionsTruncated` says older ones exist) — pass `since_hours=24`\nto make the window \"the last day\" instead — flags every Failed/Warning run, and\ncategorizes the likely cause (repository full, source/guest unreachable,\ncredential/VSS failure, retry exhaustion) from the failing log records — each\nfinding cites the session result + matched error substring, worst-first.\n`repository_capacity_rca` flags repositories under the free-space thresholds\n(<15% warn, <10% critical), citing the measured free% and free bytes.\n\n## Backup Jobs (7 — 2 read, 5 write)\n\n| Tool | R/W | Risk | Undo | Typical response tokens |\n|------|:---:|:----:|------|:----------------------:|\n| `job_list` | R | low | — | 150–600 (depends on job count) |\n| `job_get` | R | low | — | ~120 |\n| `job_start` | W | medium | `job_stop` | ~50 |\n| `job_stop` | W | medium | `job_start` | ~50 |\n| `job_retry` | W | medium | `job_stop` | ~50 |\n| `job_enable` | W | medium | `job_disable` | ~40 |\n| `job_disable` | W | medium | `job_enable` | ~40 |\n\nREST endpoints: `GET /api/v1/jobs`, `GET /api/v1/jobs/{id}`,\n`POST /api/v1/jobs/{id}/{start|stop|retry|enable|disable}`. The write tools\ncapture the job's prior status/lastResult for context.\n\n## Restore (2 — 1 read, 1 write)\n\n| Tool | R/W | Risk | Undo | Typical response tokens |\n|------|:---:|:----:|------|:----------------------:|\n| `restore_list_points` | R | low | — | 150–800 |\n| `start_vm_restore` | W | high | **none — irreversible** | ~40 |\n\n`restore_list_points` returns the newest `limit` points (default 100, max 1000) as\n`{\"restorePoints\", \"returned\", \"limit\", \"truncated\", \"order\"}` — an estate's restore\npoints are far too many to return whole. With `backup_id`, a point from another\nbackup coming back means the server ignored the filter, and that is refused.\n\nREST endpoints: `GET /api/v1/restorePoints` (`orderColumn=CreationTime&orderAsc=false`,\noptional `backupIdFilter`),\n`GET /api/v1/restorePoints/{id}` (to name what a restore would overwrite),\n`POST /api/v1/restore/vm`. `start_vm_restore` is a documented skeleton: the\nexact restore endpoint and payload vary by restore type and Veeam version.\n\nThe payload carries **no target mapping**, so it is"},{"path":"references/cli-reference.md","content":"# veeam-aiops CLI reference\n\nGlobal options on most commands: `--target / -t <name>` selects a configured\ntarget (default: first target in `config.yaml`).\n\n## Onboarding & secrets\n\n```bash\nveeam-aiops init                           # interactive wizard: connection + encrypted password\nveeam-aiops secret set <target>            # store/replace a password (prompts hidden)\nveeam-aiops secret list                    # names only; values never shown\nveeam-aiops secret rm <target>             # delete a stored password\nveeam-aiops secret migrate                 # import a legacy plaintext .env into the encrypted store\nveeam-aiops secret rotate-password         # re-encrypt the store under a new master password\n```\n\n## Overview\n\n```bash\nveeam-aiops overview                       # jobs by last result, repos near full, running sessions\n```\n\n## Backup jobs\n\n```bash\nveeam-aiops job list                       # id, name, type, status, lastResult\nveeam-aiops job get <job_id>               # detail for one job (incl. schedule)\nveeam-aiops job start <job_id>             # start a backup job (async session)\nveeam-aiops job stop <job_id> [--dry-run]  # stop a running job — double confirm\nveeam-aiops job retry <job_id>             # retry failed objects (async session)\nveeam-aiops job enable <job_id>            # enable the job schedule\nveeam-aiops job disable <job_id>           # disable the job schedule\n```\n\n## Restore\n\n```bash\nveeam-aiops restore list-points [--backup-id <id>] [--limit 100]  # newest restore points first\nveeam-aiops restore start --restore-point-id <id> [--dry-run]\n                                           # IRREVERSIBLE — double confirm\n```\n\n## Repositories\n\n```bash\nveeam-aiops repository list                # id, name, type, path\nveeam-aiops repository get <repo_id>       # detail incl. capacity/free/used\nveeam-aiops repository state               # capacity summary for all repos (used%)\n```\n\n## Backups\n\n```bash\nveeam-aiops backup list                    # stored backups: id, name, type, time\nveeam-aiops backup objects <backup_id>     # protected objects inside a backup\nveeam-aiops backup usage <name> [--json]   # backup storage one VM consumes, per backup (VBR 12.3+)\nveeam-aiops backup ranking [--limit 20] [--max-backups 100] [--backup <id|name> ...] \\\n    [--repository <id|name>] [--concurrency 1] [--json]  # largest consumers first; progress on stderr\n```\n\n## Infrastructure\n\n```bash\nveeam-aiops infra servers                  # managed servers: id, name, type\nveeam-aiops infra proxies                  # backup proxies: id, name, type, server\n```\n\n## Sessions (async progress)\n\n```bash\nveeam-aiops session list [--limit 100]     # newest sessions first: state, result\nveeam-aiops session get <session_id>       # poll one session (progressPercent)\nveeam-aiops session log <session_id>       # log records (events) of a session\nveeam-aiops session stop <session_id> [--dry-run]   # cancel — double confirm\n```\n\n## Diagnostics / RCA (read-only)\n\n```"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":2104,"uniquenessScore":40,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T20:26:39.439Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-09T20:26:39.439Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T03:02:02.036Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}