Conversation
Overall: strong feature work — the inbound returnImmediately path (flag parsing incl. legacy — reviewer-a · automated agent review (Hermes week-review) |
|
Yeah, item 1 was the one worth fixing. The background waiter now stops after 24 hours ( Item 2: there was no existing per-peer card cache. I added a 60s TTL for Item 3 is intentional. Unpolled outbound jobs write the prompt at send time and only write the reply when Item 4 comments are in. v1 GetTask uses |
a113c0c to
e4d7ddf
Compare
e4d7ddf to
100c0e1
Compare
|
I updated this on the refactored main and pushed 100c0e1 as one commit. I fixed duplicate history and metrics from repeated polls, preserved profile context in background completion, and included routed profiles in the nonblocking path. I also covered repeated clarifications after new input and kept streaming behavior intact. 144 targeted Python tests passed through scripts/run_tests.sh across A2A async tasks, protocol/adapter/client behavior, schemas, and deferred tool registration. One Linux-only shebang test was skipped on Windows. Loopback HTTP tests cover concurrent polling, repeated clarifications, and tenant separation; completion tests check local/routed profile history and audit isolation. |
|
Follow-up from #91687 (comment) The production report is the forwarded-profile kill path. This PR already covers that for Session wake into the originating Hermes session after it has moved on or restarted stays out of this PR. This branch last moved on 2026-09-14. Next step is rebase onto current main, then re-run the targeted A2A tests. P3 is the cosmetic bucket. This is dropped completed work. Maintainers, please move this PR and #91687 to P2. |
|
Hi @Adolanium, thanks for #91688 — returning a working task for While testing the branch at 100c0e1 we hit a reply-ownership problem that becomes much more visible once callers stop blocking on the socket:
We prepared a small complement on top of your head (not on main, so it stays mergeable into your branch; your commit and authorship are untouched):
Related open PRs we checked, so this does not duplicate them:
Evidence (local run, not CI: existing venv with Python 3.11.16 and pytest 9.1.1, not
Not covered / limits: full suite and GitHub CI not run; TaskStore stays in memory (a restart still loses active tasks); no exactly-once claim for SendMessage (§3.3.1 only makes idempotency optional); a The patch is ~250 changed lines in 4 files plus one new test file. Would you prefer we send it as a PR against your branch, or would you rather cherry-pick it? If maintainers prefer it on main instead, we can rebase — just say which. |
|
Follow-up: the complement described above is available as a single commit on top of your head
No PR opened yet; happy to open one against |
With returnImmediately, a peer can have several tasks in flight on one context. The adapter dispatched them all into the gateway, whose busy queue merges queued text for a session: three tasks became two turns, task 2 got task 3's answer, and task 3 stayed WORKING until the 24h waiter ceiling. send() also resolved the oldest pending task of the context, so a late final could answer a sibling. The adapter now dispatches one turn per context and hands the context on when the in-flight task is popped. send() resolves the task named by the final's reply anchor (the gateway anchors on the inbound message id, which is the task id), falling back to the in-flight task only when no anchor is present. Reported by Neomail2 on NousResearch#91688. Co-authored-by: Neomail2 <120675713+Neomail2@users.noreply.github.com>
|
@Neomail2 thank you for this. You tested the branch properly, wrote it up clearly, and checked it against the other open PRs. That saved me a lot of time, and the ownership bug is real. I pushed 8b52861 to this branch. It takes part of the complement and fixes one case it doesn't cover. What I found reproducing it. I sent three What landed (adapter only):
What I left out, and why:
Thanks again. The ownership part only got fixed because you tested this carefully. |
SendMessage with returnImmediately now returns a working task at once. A background waiter records the real result so GetTask can poll it. The watchdog skips tasks whose gateway turn is still running. Background waiters stop after 24 hours so a hung turn cannot wait forever. a2a_call accepts return_immediately. New a2a_get_task polls by id. Call and get_task reuse a 60s Agent Card cache. Discover still fetches fresh.
With returnImmediately, a peer can have several tasks in flight on one context. The adapter dispatched them all into the gateway, whose busy queue merges queued text for a session: three tasks became two turns, task 2 got task 3's answer, and task 3 stayed WORKING until the 24h waiter ceiling. send() also resolved the oldest pending task of the context, so a late final could answer a sibling. The adapter now dispatches one turn per context and hands the context on when the in-flight task is popped. send() resolves the task named by the final's reply anchor (the gateway anchors on the inbound message id, which is the task id), falling back to the in-flight task only when no anchor is present. Reported by Neomail2 on NousResearch#91688. Co-authored-by: Neomail2 <120675713+Neomail2@users.noreply.github.com>
8b52861 to
3c8b24e
Compare
|
Thanks for taking the anchored-final/same-context part into #91688 and crediting @Neomail2. We looked at the generic continuation signal you suggested. A small local spike can expose an opt-in, adapter-neutral Would you prefer a follow-up against your #91688 branch that includes both the generic gateway signal and its A2A consumer, or a separate generic core PR after #91688 merges? We will not submit the spike as-is; we want to match the interface and base you prefer before completing the missing paths. |
|
Thanks for checking those paths! I'd keep this as a separate follow-up PR with both the generic gateway signal and the A2A consumer. Feel free to build against the current #91688 branch, then rebase onto main once it lands. No need to wait for the merge to keep working on it. The important part is that a delegation ACK leaves the original task WORKING, including across further delegation, and the eventual final only completes that task. Please cover streaming, queued-first execution, cancellation/failure, and late finals. The core interface should stay opt-in and adapter-neutral, with existing adapters keeping their current behavior. We should also make the current limitation explicit before #91688 merges. If nested background delegation is part of the supported flow there, the consumer fix needs to be in place before we call that flow supported. |
What does this PR do?
Add nonblocking A2A SendMessage support. Callers can request a working task immediately and poll with
a2a_get_task. Routed profile agents are included. Blocking calls and streaming keep their current behavior. Background completion preserves profile context and stops after a 24-hour ceiling.On the forwarded-profile path, blocking SendMessage uses
subprocess.runwith the route timeout. When that timeout fires, Python kills the child and the answer is discarded.returnImmediatelyon that path waits up to 24 hours, then records the result for GetTask.Repeated polling records each peer/tenant task outcome once. A later reply, including another clarification after new user input, remains visible in history and metrics. The implementation uses the current active-task watchdog and tool registration APIs.
Follow-up from #91687 (comment). Session wake into the originating Hermes session stays out of this PR.
Related Issue
Fixes #91687
Type of Change
Changes Made
configuration.returnImmediatelyand legacyconfiguration.blocking: falseon inbound SendMessage_BACKGROUND_WAIT_SECONDS)hermes chatreturn_immediatelyona2a_calland a newa2a_get_taskpoll toolHow to Test
scripts/run_tests.sh tests/plugins/test_a2a_async_tasks.py tests/plugins/test_a2a_phase23.py tests/plugins/test_a2a_plugin.py tests/plugins/test_a2a_tools_gate.py tests/hermes_cli/test_deferred_platform_client_tools.pyreturnImmediatelytasks into one context through the realhandle_messageand checks that each gets its own reply. It fails without the per-context dispatch.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/A🤖 Generated with Claude Code