feat(hermes): add hermes-acp streaming harness (ACP transport) - #2211
feat(hermes): add hermes-acp streaming harness (ACP transport)#2211dosenr wants to merge 1 commit into
Conversation
b1eaefd to
fe326ea
Compare
|
#2152 (generic ACP harness) landed after this was opened and covers most of the client plumbing here. Reworking this PR to build on that instead: the hermes executor becomes a thin layer over the generic AcpExecutor, keeping only what hermes needs on top - the per-session HERMES_HOME policy-hook wiring (hermes raises session/request_permission for only a subset of its tools, so the pre_tool_call hook stays the complete gate) plus the adapter persistence fix for self-executed tool cards. Diff will shrink substantially. Updated branch shortly - hold review until then. |
fe326ea to
ed36de3
Compare
|
Rework done - this is now a thin layer over #2152's generic AcpExecutor, as promised above. Delta vs the original diff:
Ready for review. |
786eaca to
c3e7b40
Compare
|
/review |
|
We hope that AcpExecutor can cover all ACP compatible agents. For the extra logic in this PR, is this something we can generalize into AcpExecutor? |
|
Yes - most of it generalizes, and one piece arguably should regardless of hermes:
What stays vendor-specific is the per-session Happy to do 1-3 here - or the classification piece as its own PR first if you'd prefer, since it changes behavior for goose/qwen too and may be cleaner to review alone. Will start on the generalization so either way it lands quickly. (Coordination note: #2216, same author, refactors the hermes home plumbing this PR imports - whichever lands second I rebase promptly.) |
c3e7b40 to
350a96e
Compare
|
Split the generic half out as #2387: the tool-call classification and card persistence now live in I rebased this branch onto that change and removed the generic |
350a96e to
d7ecfb0
Compare
|
Post-restack validation on the final branch (d7ecfb0, stacked on #2387): one live turn through The native call renders, completes durably, and pairs under its own id; the bridged dispatch reuses the observed event's id (the correlation queue paired correctly with a native call in the same turn). The opt-in e2e ( The rerun caught one restack gap, fixed in d7ecfb0: this executor's overridden |
d7ecfb0 to
4624c56
Compare
|
Rebased onto the updated base branch (#2387 @ |
|
Status update:
|
cf529b0 to
397dfc3
Compare
| "kiro-native", | ||
| "kimi", | ||
| "kimi-native", | ||
| "hermes", |
There was a problem hiding this comment.
Also how does hermes-acp harness compare to hermes harness? I wonder if we should replace herness harness with this if hermes-acp works better
There was a problem hiding this comment.
Yes, I think hermes-acp should eventually replace the existing Hermes harness. It provides structured streaming, native tool progress, cancellation, usage, and the generic ACP integration instead of parsing final subprocess output. It also works headlessly, so I would not keep batch as a permanent headless architecture.
I would retain the current harness temporarily while proving a short parity checklist: process restart and Hermes session resume, cancellation during native and bridged tools, policy coverage, usage, text/thinking/tool-card persistence, and failure cleanup.
Exercising Hermes across native and bridged tools has already surfaced integration bugs in both the policy path (#2220, merged) and generic ACP correlation (#2387, in review; this PR stacks on it), so I'd prove parity rather than assume it.
I'm happy to own that follow-up, then make ACP the implementation behind hermes and retain the old executor briefly as hermes-batch for rollback.
One process note: I'm rebasing and tightening #2387 against current main with a smaller focused test set, then I'll restack this PR and re-run the Goose and Hermes live validations. I'll post the refreshed evidence here once the stack is stable.
397dfc3 to
20d6753
Compare
|
Following up on the ACP generalization and harness-replacement questions: I rebased both branches onto current main and reduced the stack to one generic commit ( The restack also fixed an integration gap in the previous receipt: the Hermes |
|
Marking this draft while the generic ACP prerequisite #2387 awaits merge. The Hermes-specific design and previous validation evidence remain documented here, but main has since changed runner initialization and harness readiness substantially. This branch therefore requires a fresh restack and renewed live validation before further review. I will avoid producing another moving target until the prerequisite lands or maintainers request a different direction. |
20d6753 to
7256544
Compare
2393297 to
7f10dd1
Compare
|
Fresh restack is up on current And yes, I think ACP should eventually replace the batch harness: better streaming and live-tool UX, less custom code to maintain. |
Signed-off-by: Robert Dosen <robert.dosen@gmail.com>
7f10dd1 to
01bd77f
Compare
|
Rebased onto current main now that #2387 has landed. Generic native-tool classification and dispatch correlation now come from the base; this PR remains the Hermes ACP integration. |
Related issue
Closes #2151
Summary
The current
hermesharness waits for a batch turn to finish. This adds a separatehermes-acpharness that carries Hermes' ACP stream through the shared
AcpExecutor, without changing whathermesmeans.lifecycle, streaming, and MCP delivery.
HERMES_HOMEthrough the existing Hermes bridge. It carries the selectedvendor model and the existing Omnigent policy hook, but no configured MCP. Require Hermes 0.19.1
and suppress managed configured MCP startup so the shared executor remains the sole owner of MCP
delivery through
session/new.permission request continues without evaluating policy again or creating a second card.
restriction therefore cannot silently widen.
or cannot evaluate policy. This correction also applies to the existing batch and native Hermes modes
that use the same hook.
Generic native-tool classification and dispatch correlation are provided by #2387 on
main.Test Plan
pytest -q tests/test_acp_cli_harnesses.py tests/inner/test_acp_executor.py tests/inner/test_hermes_policy_hook.py tests/test_hermes_native_bridge.py tests/cli/test_configure_models.py:312 passed.tests/e2e/test_hermes_acp_e2e.pydrives the catalog builder and generic ACP wrapperagainst a real configured Hermes CLI. It skipped because the live opt-in flag was absent.
0 errors.Demo
The surface remains the normal Omnigent streaming transcript and tool cards. These existing captures
show the Hermes ACP stream and the same cards after reload:
The restack changes the shared ACP integration point, not this rendered surface.
Type of change
Test coverage
Coverage notes
Unit tests cover catalog registration, the Hermes 0.19.1 minimum, per-session configuration,
user-config filtering, restrictive-skill rejection, managed environment filtering, MCP precedence, one
policy evaluation per Hermes tool call, and fail-closed hook boundaries. The opt-in E2E covers one real
streaming turn through the builtin row and shared executor.
Manual verification confirmed that the one-commit restack retains current ACP prompt injection,
permission scopes, permission mode, extension handling, and #2387 correlation behavior.
Changelog
Hermes sessions can use the shared streaming ACP harness without replacing the existing batch harness.