feat(a2a-nats): add server Bridge and dispatch wiring#362
Conversation
yordis
commented
Jun 19, 2026
- Binaries need a single entry point that subscribes to the agent wildcard subject and routes each inbound request to the matching per-op handler. Audit, push-dispatch, and cancellation tracking are runtime concerns that land in follow-ups so this slice stays focused on the subscribe + route path.
Binaries need a single entry point that subscribes to the agent wildcard subject and routes each inbound JSON-RPC request to the matching per-op handler; landing the minimal Bridge first lets the binaries come up before audit, push-dispatch, and cancellation tracking land in follow-ups. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
PR SummaryMedium Risk Overview
The crate gains Reviewed by Cursor Bugbot for commit 0d96191. Bugbot is set up for automated code reviews on this repo. Configure here. |
|
Warning Review limit reached
More reviews will be available in 39 minutes and 24 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
WalkthroughAdds an agent-side NATS bridge to the ChangesNATS Agent Bridge and Dispatch
Sequence Diagram(s)sequenceDiagram
participant Client as A2A Client
participant NATS as NATS Server
participant Bridge as Bridge::run_with_agent_id
participant Dispatch as dispatch_message
participant Handler as A2aExecutor Handler
Client->>NATS: publish to {prefix}.agents.{agent_id}.tasks/get
NATS->>Bridge: deliver message via wildcard subscription
Bridge->>Dispatch: dispatch_message(msg)
Dispatch->>Dispatch: A2aMethod::from_subject strips prefix, matches suffix
Dispatch->>Handler: call tasks_get(payload, reply_subject)
Handler->>NATS: publish JSON-RPC response to reply subject
NATS->>Client: deliver JSON-RPC response
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Code Coverage SummaryDetailsDiff against mainResults for commit: 0d96191 Minimum allowed coverage is ♻️ This comment has been updated with latest results |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
rsworkspace/crates/a2a-nats/src/server/dispatch.rs (1)
179-181: ⚡ Quick winMisleading test name.
The test
as_str_round_trips_for_message_senddoesn't verify a round trip—it only callsas_str()and checks the result. Sinceas_str()returns slash-separated strings (e.g.,"message/send") whilefrom_subject()parses dot-separated NATS suffixes (e.g.,"message.send"), these methods serve different purposes and cannot round-trip. Rename to something likeas_str_returns_expected_format_for_message_send.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rsworkspace/crates/a2a-nats/src/server/dispatch.rs` around lines 179 - 181, The test function `as_str_round_trips_for_message_send` has a misleading name because it does not perform a round-trip verification. The test only calls `as_str()` and validates the output, but since `as_str()` returns slash-separated strings while `from_subject()` parses dot-separated NATS suffixes, these methods cannot actually round-trip. Rename the test function to accurately reflect what it tests, such as `as_str_returns_expected_format_for_message_send`, to clarify that it validates the format returned by the `as_str()` method on the `A2aMethod::MessageSend` variant.rsworkspace/crates/a2a-nats/src/server/bridge.rs (1)
72-74: ⚡ Quick winAvoid duplicating subject construction logic.
Line 74 manually constructs the subject prefix string to compute its length, duplicating logic that
AgentAllSubject::new(&prefix, agent_id)likely already performs. If the subject format changes (e.g., different delimiter or structure), both locations must be updated.Consider exposing a method on
AgentAllSubjectto return the prefix length, or caching the computed prefix length withinBridge::new()ifAgentAllSubjectprovides access to the full subject string.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rsworkspace/crates/a2a-nats/src/server/bridge.rs` around lines 72 - 74, The prefix_len calculation on line 74 duplicates the subject construction logic that AgentAllSubject::new already performs internally. Instead of manually constructing the string format to compute the length, modify the AgentAllSubject type to expose either a method that directly returns the prefix length, or provide access to the full subject string so the length can be derived from it. This eliminates duplication and ensures that if the subject format changes in the future, you only need to update AgentAllSubject::new rather than maintaining the format in multiple locations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@rsworkspace/crates/a2a-nats/src/server/bridge.rs`:
- Around line 27-30: The BridgeError::Subscribe variant currently stores a
String instead of a typed error source, violating the error handling guidelines.
Refactor the BridgeError enum to have the Subscribe variant hold a typed error
field (following the A2aError pattern already established in this module)
instead of a String. Then locate where the error is created (around line 80) and
update it to wrap the actual typed error without converting to string via
.to_string(). Finally, update the corresponding test at line 231 to work with
the new typed error field structure.
---
Nitpick comments:
In `@rsworkspace/crates/a2a-nats/src/server/bridge.rs`:
- Around line 72-74: The prefix_len calculation on line 74 duplicates the
subject construction logic that AgentAllSubject::new already performs
internally. Instead of manually constructing the string format to compute the
length, modify the AgentAllSubject type to expose either a method that directly
returns the prefix length, or provide access to the full subject string so the
length can be derived from it. This eliminates duplication and ensures that if
the subject format changes in the future, you only need to update
AgentAllSubject::new rather than maintaining the format in multiple locations.
In `@rsworkspace/crates/a2a-nats/src/server/dispatch.rs`:
- Around line 179-181: The test function `as_str_round_trips_for_message_send`
has a misleading name because it does not perform a round-trip verification. The
test only calls `as_str()` and validates the output, but since `as_str()`
returns slash-separated strings while `from_subject()` parses dot-separated NATS
suffixes, these methods cannot actually round-trip. Rename the test function to
accurately reflect what it tests, such as
`as_str_returns_expected_format_for_message_send`, to clarify that it validates
the format returned by the `as_str()` method on the `A2aMethod::MessageSend`
variant.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5bfef5d2-d57e-457c-bcfa-33eb2014d371
⛔ Files ignored due to path filters (1)
rsworkspace/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (4)
rsworkspace/crates/a2a-nats/Cargo.tomlrsworkspace/crates/a2a-nats/src/server/bridge.rsrsworkspace/crates/a2a-nats/src/server/dispatch.rsrsworkspace/crates/a2a-nats/src/server/mod.rs
The subscribe error variant previously stored a String, dropping the underlying typed error and its Error::source chain. Boxing the original preserves the chain so downstream observability can still walk .source() instead of parsing prose. Also covered the per-op dispatch branches and the subscription-closed exit path the Bridge takes when the upstream stream terminates. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>