Skip to content

[NA] [SDK] fix: entry point resolves to module so pip-install works (0.1.1) + pip E2E coverage - #24

Merged
JetoPistola merged 5 commits into
mainfrom
danield/NA-fix-entrypoint-0.1.1
Jul 8, 2026
Merged

[NA] [SDK] fix: entry point resolves to module so pip-install works (0.1.1) + pip E2E coverage#24
JetoPistola merged 5 commits into
mainfrom
danield/NA-fix-entrypoint-0.1.1

Conversation

@JetoPistola

@JetoPistola JetoPistola commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

User description

Details

image

The bug: pip install opik-hermes produced no traces in Hermes. Root cause: the hermes_agent.plugins entry point was opik = opik_hermes:register, which resolves to the register function. Hermes loads a plugin via ep.load() then getattr(<result>, "register") — expecting a module. So it found no register(), wired 0 hooks, and the plugin silently did nothing. (The directory-install path imports __init__.py as a module and was unaffected — which is exactly why this slipped through CI.)

The fix (one line): point the entry point at the module — opik = opik_hermes. getattr(module, "register") then resolves (the package exports register). Verified end-to-end: real Hermes + pip-installed wheel, enabled via config.yaml plugins.enabled: [opik] → fresh staging trace, 7 spans (llm=4, tool=3, NA=0), OPIK: Started logging traces....

This makes both install paths work — pip/entry-point (fixed here) and directory (hermes plugins install …, already worked).

Change checklist

  • Bug fix (pip-install plugin activation)
  • CI / test coverage (new pip-entry-point E2E)
  • Documentation
  • Review feedback addressed (entry-point check consolidated into one shared guard)

Issues

NA — found during dogfood/release verification. Related: OPIK-7254 (dir/GitHub install path).

Testing

  • pyproject: entry point → opik_hermes; version → 0.1.1.
  • Single shared guard e2e/assert_entrypoint.py: reproduces Hermes' own loader — entry_points()["opik"].load() must return a module with a callable register. Used by ci.yml, publish.yml, and the E2E image, so a regression back to :register fails the build. (Consolidated from earlier per-file checks per review.)
  • ci.yml + publish.yml: build the wheel, install it, then run the shared behavioral check (previously only string-parsed the wheel metadata — now verifies real loadability).
  • New pip/wheel E2E (e2e/Dockerfile.wheel + e2e/run_e2e_wheel.sh + a CI job in e2e.yml): builds the wheel from source, pip installs it into Hermes, enables via config.yaml, drives a turn with entry-point discovery only (no plugin dir copied), asserts the journal. This is the coverage that would have caught the bug. The existing mock E2E keeps testing the directory-install path — CI now covers both.
  • CI: all checks green — build, E2E via pip (entry point), E2E against latest Hermes, E2E against real Opik, tests (3.11/3.12/3.13), lint; Baz re-reviewed clean.

Documentation

  • Root + plugin README: the pip path enables via ~/.hermes/config.yaml plugins.enabled: [opik] (entry-point name opik), not hermes plugins enable (that CLI only sees directory-installed plugins). The directory/GitHub install is noted as a separate path.

🤖 Generated with Claude Code


Generated description

Fixes the Hermes plugin entry point so opik maps to the opik_hermes module, allowing the loader’s getattr(<module>, "register") to succeed for both pip and directory installs while bumping the package to 0.1.1. Guards this contract through the shared assert_entrypoint.py check, plus new pip-entry-point E2E coverage and doc updates for the pip install path.

TopicDetails
Pip E2E Coverage Execute pip-installed wheel covers the entry-point path end-to-end: build/install the wheel in Docker, run Hermes on a mock network via run_e2e_wheel.sh, and wire CI/workflow steps to run the new scenario and reuse the entry-point assertion.
Modified files (6)
  • .github/workflows/ci.yml
  • .github/workflows/e2e.yml
  • .github/workflows/publish.yml
  • e2e/Dockerfile.wheel
  • e2e/assert_entrypoint.py
  • e2e/run_e2e_wheel.sh
Latest Contributors(1)
UserCommitDate
danield@comet.comci: make assert_entryp...July 08, 2026
Entry Point Fix Verify entry points by tagging opik to the opik_hermes module, documenting the pip workflow, and adding the shared assert_entrypoint.py guard so Hermes can always getattr(module, "register") when loading the plugin.
Modified files (4)
  • README.md
  • e2e/assert_entrypoint.py
  • observability/opik/README.md
  • pyproject.toml
Latest Contributors(1)
UserCommitDate
danield@comet.comci: make assert_entryp...July 08, 2026
Review this PR on Baz | Customize your next review

…upport) + 0.1.1

The hermes_agent.plugins entry point was 'opik = opik_hermes:register', which
resolves to the register FUNCTION. Hermes loads a plugin via ep.load() then
getattr(<result>, 'register') expecting a MODULE — so it found no register(),
wired 0 hooks, and a pip-installed plugin produced no traces (the directory-
install path was unaffected, which is why it slipped through). Fix: point the
entry point at the module ('opik = opik_hermes'); getattr(module, 'register')
then resolves. Verified end-to-end: real Hermes + pip-installed wheel, enabled
via config.yaml plugins.enabled:[opik], logs a fresh staging trace (7 spans).

- pyproject: entry point -> opik_hermes; version -> 0.1.1
- publish.yml: assert the built wheel's entry point == 'opik_hermes' (guards the regression)
- e2e: new pip/wheel path (Dockerfile.wheel + run_e2e_wheel.sh + CI job) that
  builds the wheel, pip-installs it, and drives a turn via ENTRY-POINT discovery
  (no plugin dir copied) — the coverage that would have caught this. The existing
  mock E2E keeps testing the directory-install path; both are supported.
- README (root + plugin): pip path enables via ~/.hermes/config.yaml
  plugins.enabled:[opik] (entry-point name 'opik'), not 'hermes plugins enable'
  (which only sees directory plugins); dir/GitHub install noted as separate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
baz-reviewer[bot]
baz-reviewer Bot previously approved these changes Jul 7, 2026
The build job's wheel check still asserted 'opik_hermes:register'; after the
entry-point fix the value is 'opik_hermes'. Update it (mirroring publish.yml) to
assert the entry point resolves to the module. This is the same guard the fix
adds — CI correctly failed on the stale string.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@baz-reviewer
baz-reviewer Bot dismissed their stale review July 8, 2026 00:31

Baz dismissed its prior approval because a re-review found new findings.

Comment thread e2e/Dockerfile.wheel Outdated
…view)

Baz flagged that the 'entry point must resolve to opik_hermes (module)' guard
was duplicated in ci.yml and publish.yml — an entry-point change would need
updating in both. Extract it into e2e/assert_entrypoint.py (single source of
truth) and call it from both workflows. Left e2e/Dockerfile.wheel's guard as-is:
it verifies the INSTALLED plugin loads in-container (a different check), and
copying a script into that build context isn't worth the coupling.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread e2e/assert_entrypoint.py Outdated
JetoPistola and others added 2 commits July 8, 2026 07:19
The previous edit replaced the heredoc body with a single command but left the
trailing 'PY' line, which YAML folded into the run: command (python
e2e/assert_entrypoint.py PY -> 'no wheel matched PY'). Remove it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… (address review)

Baz flagged that the entry-point check existed in two places — assert_entrypoint.py
(static wheel-metadata parse) and Dockerfile.wheel (behavioral ep.load()). Valid:
the behavioral check is strictly stronger (it verifies the plugin actually LOADS
as a module with a callable register, exactly as Hermes does), and it subsumes the
metadata check. Unify on the strong one:

- Rewrite assert_entrypoint.py to do the behavioral check against the INSTALLED
  package: entry_points()[opik].load() must be a module with callable register.
- ci.yml + publish.yml: install the built wheel, then run the shared check
  (previously they only string-parsed the wheel — now they verify real loadability).
- Dockerfile.wheel: COPY and run the same shared script instead of an inline
  duplicate; run_e2e_wheel.sh stages it into the build context.

One correct way to assert the contract, used everywhere, and stronger than before.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@JetoPistola
JetoPistola merged commit ddf0f30 into main Jul 8, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant