From 526a3faf21d1a32ea2037d84e96e2f8c1bfba172 Mon Sep 17 00:00:00 2001 From: Paulo Lacerda Date: Fri, 29 May 2026 00:43:54 -0300 Subject: [PATCH] fix(agent): use ruamel.yaml instead of pyyaml in agent modules (#193) Four agent modules imported PyYAML (`import yaml`) but `pyproject.toml` only declares `ruamel.yaml`. On clean CI runners (no PyYAML in the venv) this raised `ModuleNotFoundError: yaml` at `agentops doctor` time, breaking the doctor step of the generated deploy workflow. Refactored to the existing `ruamel.yaml` dependency (same pattern as `src/agentops/utils/yaml.py`): - `agent/checks/opex_workspace.py` - `agent/checks/spec_conformance.py` - `agent/llm_assist/_bundle_rule.py` - `agent/cockpit.py` (preserved the lazy-import semantics inside `_resolve_agent_identity`) Behaviour preserved: `YAML(typ='safe').load(...)` returns plain dicts/lists just like `yaml.safe_load(...)`. No new runtime dependency. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/agentops/agent/checks/opex_workspace.py | 7 ++++--- src/agentops/agent/checks/spec_conformance.py | 11 ++++++----- src/agentops/agent/cockpit.py | 4 ++-- src/agentops/agent/llm_assist/_bundle_rule.py | 7 ++++--- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/agentops/agent/checks/opex_workspace.py b/src/agentops/agent/checks/opex_workspace.py index 9ab8ca1..78abac6 100644 --- a/src/agentops/agent/checks/opex_workspace.py +++ b/src/agentops/agent/checks/opex_workspace.py @@ -24,7 +24,8 @@ from pathlib import Path from typing import Any, Dict, List, Optional -import yaml +from ruamel.yaml import YAML +from ruamel.yaml.error import YAMLError from agentops.agent.findings import Category, Finding, Severity @@ -552,8 +553,8 @@ def _safe_load_yaml(path: Path) -> Optional[dict]: return None try: with path.open("r", encoding="utf-8") as handle: - data = yaml.safe_load(handle) - except (OSError, yaml.YAMLError): + data = YAML(typ="safe").load(handle) + except (OSError, YAMLError): return None return data if isinstance(data, dict) else None diff --git a/src/agentops/agent/checks/spec_conformance.py b/src/agentops/agent/checks/spec_conformance.py index 0be4440..1b53725 100644 --- a/src/agentops/agent/checks/spec_conformance.py +++ b/src/agentops/agent/checks/spec_conformance.py @@ -22,7 +22,8 @@ from pathlib import Path from typing import Iterable, List, Optional -import yaml +from ruamel.yaml import YAML +from ruamel.yaml.error import YAMLError from agentops.agent.config import SpecConformanceCheckConfig from agentops.agent.findings import Category, Finding, Severity @@ -297,8 +298,8 @@ def _check_agent_drift(workspace: Path, doc: SpecDocument) -> List[Finding]: if not run_yaml.exists(): return [] try: - raw = yaml.safe_load(run_yaml.read_text(encoding="utf-8")) - except (OSError, yaml.YAMLError): + raw = YAML(typ="safe").load(run_yaml.read_text(encoding="utf-8")) + except (OSError, YAMLError): return [] if not isinstance(raw, dict): return [] @@ -342,8 +343,8 @@ def _collect_evaluator_names(workspace: Path) -> set[str]: return out for p in bundles_dir.glob("*.y*ml"): try: - raw = yaml.safe_load(p.read_text(encoding="utf-8")) - except (OSError, yaml.YAMLError): + raw = YAML(typ="safe").load(p.read_text(encoding="utf-8")) + except (OSError, YAMLError): continue if not isinstance(raw, dict): continue diff --git a/src/agentops/agent/cockpit.py b/src/agentops/agent/cockpit.py index 239566d..7b05cfe 100644 --- a/src/agentops/agent/cockpit.py +++ b/src/agentops/agent/cockpit.py @@ -2286,11 +2286,11 @@ def _resolve_agent_identity(workspace: Path) -> Tuple[Optional[str], str]: ``agentops.yaml``) takes precedence over the legacy layered schema (``target.endpoint.agent_id`` in ``run.yaml``). """ - import yaml # noqa: PLC0415 + from ruamel.yaml import YAML # noqa: PLC0415 def _read_yaml(path: Path) -> Optional[dict]: try: - data = yaml.safe_load(path.read_text(encoding="utf-8")) + data = YAML(typ="safe").load(path.read_text(encoding="utf-8")) except Exception: # noqa: BLE001 return None return data if isinstance(data, dict) else None diff --git a/src/agentops/agent/llm_assist/_bundle_rule.py b/src/agentops/agent/llm_assist/_bundle_rule.py index 5381b74..d0177a2 100644 --- a/src/agentops/agent/llm_assist/_bundle_rule.py +++ b/src/agentops/agent/llm_assist/_bundle_rule.py @@ -11,7 +11,8 @@ from pathlib import Path from typing import List, Optional -import yaml +from ruamel.yaml import YAML +from ruamel.yaml.error import YAMLError from agentops.agent.findings import Category, Finding from agentops.agent.llm_assist._base import ( @@ -106,8 +107,8 @@ def check_bundle_coverage( # Sanity check: skip when the YAML is unparseable. try: - yaml.safe_load(bundle_text) - except yaml.YAMLError: + YAML(typ="safe").load(bundle_text) + except YAMLError: return [] ih = hash_text("bundle_coverage", bundle_text, agent_excerpt)