diff --git a/agent/devagentic_memory.py b/agent/devagentic_memory.py index 81823c1165e5..124ed5541a08 100644 --- a/agent/devagentic_memory.py +++ b/agent/devagentic_memory.py @@ -30,6 +30,12 @@ failure (network, parse, no facts, etc.); callers MUST keep their existing file fallback so a transient devagentic outage doesn't brick memory retrieval. + +Transport caveat: this adapter assumes devagentic exposes +`/graphql` over HTTP. Some canonical deployments don't (see +TechDevGroup/hermes-agent#21); query_user_facts returns [] +silently on every call there. Run `hermes doctor` for a probe ++ actionable hint when graph mode is enabled. """ from __future__ import annotations diff --git a/agent/devagentic_skills.py b/agent/devagentic_skills.py index 012f061febd2..2c19f1a8de39 100644 --- a/agent/devagentic_skills.py +++ b/agent/devagentic_skills.py @@ -29,6 +29,13 @@ (network, parse, missing-skill, etc.); callers MUST keep their existing file fallback so a transient devagentic outage doesn't brick `/skill-name`. + +Transport caveat: this adapter assumes devagentic exposes +`/graphql` over HTTP. Some canonical deployments don't (see +TechDevGroup/hermes-agent#21); the resolver silently falls back +to None on every call there, and the file fallback kicks in. +Run `hermes doctor` for a probe + actionable hint when graph +mode is enabled. """ from __future__ import annotations diff --git a/hermes_cli/doctor.py b/hermes_cli/doctor.py index 66653cec0e8e..079d19aa0512 100644 --- a/hermes_cli/doctor.py +++ b/hermes_cli/doctor.py @@ -318,8 +318,13 @@ def _check_devagentic_graph() -> None: elif exc.code == 404: check_fail( "Devagentic GraphQL: not found", - f"{base}/graphql returned 404 — verify " - "DEVAGENTIC_BASE_URL points at a graph-enabled instance", + f"{base}/graphql returned 404. Some devagentic " + "deployments expose REST (e.g. /v1/canvases) but " + "not /graphql over HTTP. See " + "TechDevGroup/hermes-agent#21 for the known gap; " + "verify with `curl -X POST /graphql -d " + "'{\"query\":\"{__typename}\"}'` before assuming " + "DEVAGENTIC_BASE_URL is wrong.", ) else: check_fail( diff --git a/plugins/devagentic-docs/README.md b/plugins/devagentic-docs/README.md index 658fb37d3846..7f5aa2335b83 100644 --- a/plugins/devagentic-docs/README.md +++ b/plugins/devagentic-docs/README.md @@ -54,6 +54,29 @@ context goes on the user side, not the system prompt). Capped at 8000 chars by the hermes-side ceiling; devagentic's `renderContext` does its own bounding upstream. +## Requires `/graphql` over HTTP + +This plugin talks to devagentic's GraphQL surface at +`/graphql`. Some devagentic +deployments expose REST (e.g. `/v1/canvases`) but **not** +`/graphql` over HTTP — in that case every `/doc` and `/fork` +command surfaces `Reason: not found at /graphql.` See +[hermes-agent#21](https://github.com/TechDevGroup/hermes-agent/issues/21). + +Verify with: + +```bash +curl -X POST /graphql \ + -H "Content-Type: application/json" \ + -H "X-User-Id: " \ + -d '{"query":"{__typename}"}' +``` + +A `200` with `{"data":{"__typename":"Query"}}` means the surface +is present. A `404` means it isn't — the plugin won't work +against that deployment until devagentic-side ships the HTTP +transport. + ## Configuration Reuses the devagentic-local provider's environment, same as diff --git a/tests/hermes_cli/test_doctor_devagentic_graph.py b/tests/hermes_cli/test_doctor_devagentic_graph.py index 16f9e5773701..706ee928351c 100644 --- a/tests/hermes_cli/test_doctor_devagentic_graph.py +++ b/tests/hermes_cli/test_doctor_devagentic_graph.py @@ -111,6 +111,11 @@ def _raise(*a, **k): fail = [c for c in calls if c[0] == "fail"] assert any("not found" in c[1].lower() for c in fail), calls + # #21: 404 detail should point at the known transport gap so + # operators don't chase env-var mismatches before checking + # whether /graphql is exposed at all. + assert any("#21" in c[2] for c in fail), \ + f"expected #21 reference in detail; got {fail}" def test_reports_unreachable_on_urlerror(monkeypatch):