Add broadcast, subscribe_buffered, and get_inbox to agent-tools#2
Merged
Conversation
…ction Adds fleet-level methods to _DeviceConnectConnection matching the Zenoh mesh DX: broadcast() invokes a function on all discovered devices, subscribe_buffered() buffers messages as (subject, data) tuples matching Zenoh mesh inbox format, and get_inbox() returns buffered messages.
- Replace hardcoded nats_url in test_strands_agent.py with messaging_url fixture so Zenoh-parameterized runs use the correct URL - Increase SETTLE_TIME in test_sensor_device.py from 0.3s to 0.5s to reduce Zenoh D2D discovery flakiness under load
3 tasks
soupat
added a commit
that referenced
this pull request
May 19, 2026
Addresses items #1 and #2 from atsyplikhin's PR #29 review. #1 — broadcast() now emits a logger.warning when any matched row carries labels.safety == "critical". Per the discovery design doc this layer is explicitly advisory, not a gate, because broadcast IS the canonical async-critical workload (ESTOP) and must not be blocked. The WARN surfaces typo'd selectors or buggy where-masks that sweep across critical functions; edge self-election means the agent never sees the matched set otherwise. Log line shape (matches the sibling [broadcast::%s::%d targets] bracket convention used elsewhere in the function): [broadcast::<fn>::<correlation_id>] matched N row(s) labeled safety:critical (sample devices: [...]); where=... proceeding (advisory only) #2 — docs/discovery.md broadcast worked-example updated from the bare ``where="mask[seat_row][seat_col] == 1 && status.battery > 30"`` form to the namespaced ``where="bindings.mask[identity.seat_row][identity.seat_col] == 1 && status.battery > 30"``. The PR's predicate context (identity, labels, status, bindings) is the right design — collision-safe, mirrors the K8s admission request.object idiom — so the example, not the implementation, is what was out of step. Tests: 4 new unit tests in TestBroadcastSafetyCriticalAdvisory cover the WARN-emission positive case, the no-critical-rows negative case, the return-envelope-unchanged invariant, and where= truncation. 1 new integration test in test_tools_broadcast.py spawns a robot (whose dispatch_robot carries safety:critical) and pins the advisory end-to-end on real NATS + Zenoh backends, asserting replies still arrive (advisory does not block). Review-chain follow-ups applied before commit: symmetric repr() of where=, square-bracket prefix, caplog filter pinned to the tools logger by name, sample_ids deduped before slicing, and the implementation comment trimmed to intent only.
soupat
added a commit
that referenced
this pull request
May 19, 2026
Addresses items #1 and #2 from atsyplikhin's PR #29 review. #1 — broadcast() now emits a logger.warning when any matched row carries labels.safety == "critical". Per the discovery design doc this layer is explicitly advisory, not a gate, because broadcast IS the canonical async-critical workload (ESTOP) and must not be blocked. The WARN surfaces typo'd selectors or buggy where-masks that sweep across critical functions; edge self-election means the agent never sees the matched set otherwise. Log line shape (matches the sibling [broadcast::%s::%d targets] bracket convention used elsewhere in the function): [broadcast::<fn>::<correlation_id>] matched N row(s) labeled safety:critical (sample devices: [...]); where=... proceeding (advisory only) #2 — docs/discovery.md broadcast worked-example updated from the bare ``where="mask[seat_row][seat_col] == 1 && status.battery > 30"`` form to the namespaced ``where="bindings.mask[identity.seat_row][identity.seat_col] == 1 && status.battery > 30"``. The PR's predicate context (identity, labels, status, bindings) is the right design — collision-safe, mirrors the K8s admission request.object idiom — so the example, not the implementation, is what was out of step. Tests: 4 new unit tests in TestBroadcastSafetyCriticalAdvisory cover the WARN-emission positive case, the no-critical-rows negative case, the return-envelope-unchanged invariant, and where= truncation. 1 new integration test in test_tools_broadcast.py spawns a robot (whose dispatch_robot carries safety:critical) and pins the advisory end-to-end on real NATS + Zenoh backends, asserting replies still arrive (advisory does not block). Review-chain follow-ups applied before commit: symmetric repr() of where=, square-bracket prefix, caplog filter pinned to the tools logger by name, sample_ids deduped before slicing, and the implementation comment trimmed to intent only.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
broadcast()to invoke a function on all discovered devices, collecting resultssubscribe_buffered()usingsubscribe_with_subjectto buffer messages as(subject, data)tuples — matching Zenoh mesh inbox formatunsubscribe_buffered()andget_inbox()for reading/managing buffered subscriptionsThese methods close the DX gap between the agent-tools connection and the Zenoh mesh, enabling
strands-robotsto use Device Connect as a drop-in replacement for fleet coordination (see strands-gtc-nvidia#feat/device-connect-integration).Test plan
pytest tests/test_connection_unit.py tests/test_tools_unit.py -v)pytest tests/ -v -m "not llm")(topic, data)convention