Skip to content

feat: Add DNS-AID tools for agent discovery via DNS#4856

Open
IngmarVG-IB wants to merge 2 commits intogoogle:mainfrom
IngmarVG-IB:feat/dns-aid-integration
Open

feat: Add DNS-AID tools for agent discovery via DNS#4856
IngmarVG-IB wants to merge 2 commits intogoogle:mainfrom
IngmarVG-IB:feat/dns-aid-integration

Conversation

@IngmarVG-IB
Copy link

@IngmarVG-IB IngmarVG-IB commented Mar 17, 2026

Resolves #4859

Summary

  • Add DNS-AID tools for agent discovery and publishing via DNS SVCB records
  • Implements async FunctionTool wrappers following Google ADK conventions
  • Includes A2A bridge to convert DNS-discovered agents into ADK RemoteAgent references
  • Enables agents to discover and connect with other agents using the DNS-AID protocol (IETF draft-mozleywilliams-dnsop-dnsaid-01)

What is DNS-AID?

DNS-AID (DNS-based Agent Identification and Discovery) is an IETF draft that uses DNS SVCB records to enable AI agents to discover and connect with each other. Agents publish their capabilities, endpoints, and protocols to DNS, and other agents query DNS to find available services.

Test plan

  • Unit tests with mocked DNS backend
  • Integration test with mock backend
  • Test A2A bridge converts records correctly

Add native DNS-AID tools that enable AI agents to discover, publish,
and unpublish other agents using DNS SVCB records (IETF draft-mozleywilliams-dnsop-dnsaid-01).

DNS-AID provides decentralized agent discovery without centralized
registries, using existing DNS infrastructure.

Requires: dns-aid>=0.12.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request integrates DNS-AID (DNS-based Agent Identification and Discovery) into the Google ADK framework. It provides a decentralized discovery mechanism for AI agents, allowing ADK to find and interact with agents published via DNS SVCB records, specifically bridging DNS-AID discovered agents to ADK's existing A2A protocol support. This enhances ADK's ability to discover and connect with a broader range of agents.

Highlights

  • DNS-AID FunctionTools: Asynchronous discover_agents, publish_agent, and unpublish_agent functions were added and wrapped as FunctionTool objects for Google ADK.
  • Tool Factory: A get_dns_aid_tools() factory function was introduced, supporting DNS backend binding for publish/unpublish operations.
  • A2A Bridge: An A2A bridge was implemented to convert agents discovered via DNS-AID into ADK-compatible RemoteAgent references.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/google/adk/tools/dns_aid_a2a_bridge.py
    • Added a new module to facilitate the conversion of DNS-AID AgentRecord objects, specifically those using the A2A protocol, into a dictionary format suitable for ADK's RemoteAgent construction.
  • src/google/adk/tools/dns_aid_tool.py
    • Introduced a new module containing discover_agents, publish_agent, and unpublish_agent asynchronous functions. These functions leverage the dns-aid library for agent management via DNS and are exposed as FunctionTool objects for use within Google ADK.
    • Added get_dns_aid_tools factory function to retrieve these tools, with support for binding a specific DNS backend for publishing and unpublishing operations.
Activity
  • No human activity has been recorded on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@google-cla
Copy link

google-cla bot commented Mar 17, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@adk-bot adk-bot added the tools [Component] This issue is related to tools label Mar 17, 2026
@adk-bot
Copy link
Collaborator

adk-bot commented Mar 17, 2026

Hello @IngmarVG-IB, thank you for your contribution!

This PR is a new feature, could you please create a GitHub issue and associate it with this PR?

In addition, could you please provide the results of the unit tests as mentioned in your testing plan?

This information will help reviewers to review your PR more efficiently. Thanks!

Response from ADK Triaging Agent

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces DNS-AID tools for agent discovery, publishing, and unpublishing, along with a bridge to make discovered agents compatible with ADK's A2A protocol. The changes are well-structured. I've identified a critical issue in how function wrappers are created, which would prevent the tools from working correctly with the language model. I've also included some suggestions to improve type safety and maintainability.

Comment on lines +131 to +135
async def _publish(**kwargs): # type: ignore[no-untyped-def]
return await publish_agent(backend_name=backend_name, **kwargs)

async def _unpublish(**kwargs): # type: ignore[no-untyped-def]
return await unpublish_agent(backend_name=backend_name, **kwargs)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The use of **kwargs in the _publish and _unpublish wrapper functions is a critical issue. FunctionTool relies on inspecting the function's signature to generate the tool definition for the language model. With a generic **kwargs signature, the model won't know which arguments to provide, causing tool calls to fail. The wrapper functions must explicitly define all the parameters of the original functions (except for the bound backend_name) to ensure correct introspection.

Suggested change
async def _publish(**kwargs): # type: ignore[no-untyped-def]
return await publish_agent(backend_name=backend_name, **kwargs)
async def _unpublish(**kwargs): # type: ignore[no-untyped-def]
return await unpublish_agent(backend_name=backend_name, **kwargs)
async def _publish(agent_name: str, domain: str, protocol: str = "mcp", endpoint: str = "", port: int = 443, capabilities: Optional[list[str]] = None, version: str = "1.0.0", description: Optional[str] = None, ttl: int = 3600):
return await publish_agent(backend_name=backend_name, agent_name=agent_name, domain=domain, protocol=protocol, endpoint=endpoint, port=port, capabilities=capabilities, version=version, description=description, ttl=ttl)
async def _unpublish(agent_name: str, domain: str, protocol: str = "mcp"):
return await unpublish_agent(backend_name=backend_name, agent_name=agent_name, domain=domain, protocol=protocol)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a7adb4c. Both _publish and _unpublish now have explicit parameter signatures matching the original functions (minus backend_name), so FunctionTool can correctly introspect them for LLM tool schemas.

from typing import Any


async def a2a_agent_from_record(agent_record: Any) -> dict[str, Any]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using Any for agent_record reduces type safety. It's better to use the specific AgentRecord type. You'll need to import it from dns_aid.core.models at the top of the file. Using a string forward reference here avoids forcing an import change in this suggestion, but the import should be added.

Suggested change
async def a2a_agent_from_record(agent_record: Any) -> dict[str, Any]:
async def a2a_agent_from_record(agent_record: "AgentRecord") -> dict[str, Any]:

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a7adb4c. Changed to agent_record: AgentRecord with the import moved to the top of the file.

Raises:
ValueError: If the agent record is not using A2A protocol.
"""
from dns_aid.core.models import Protocol
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Local imports should be avoided unless strictly necessary (e.g., to prevent circular dependencies). For better readability and consistency, please move this import to the top of the file.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a7adb4c. Imports moved to module level.

"capabilities": agent_record.capabilities or [],
"description": agent_record.description,
"protocol": "a2a",
"a2a_card_url": f"{base_url}/.well-known/agent-card.json",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This hardcoded URL path should be extracted into a module-level constant to improve maintainability and avoid magic strings. For example:

A2A_AGENT_CARD_PATH = "/.well-known/agent-card.json"

Then you can use f"{base_url}{A2A_AGENT_CARD_PATH}" here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a7adb4c. Extracted A2A_AGENT_CARD_PATH = "/.well-known/agent-card.json" as a module-level constant.

)


def get_dns_aid_tools(backend_name: Optional[str] = None) -> list:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The return type hint list is too generic. For better type safety and readability, please specify the type of elements in the list. Since FunctionTool is lazy-loaded in this package, you can use a string forward reference: list["FunctionTool"].

Suggested change
def get_dns_aid_tools(backend_name: Optional[str] = None) -> list:
def get_dns_aid_tools(backend_name: Optional[str] = None) -> list["FunctionTool"]:

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a7adb4c. Return type is now list["FunctionTool"].

- Fix critical **kwargs issue in get_dns_aid_tools() wrappers: _publish
  and _unpublish now have explicit parameter signatures so FunctionTool
  can introspect them for LLM tool schemas
- Add proper type hints: AgentRecord instead of Any, list['FunctionTool']
  return type
- Move imports to module level in A2A bridge
- Extract A2A_AGENT_CARD_PATH constant (no magic strings)
@IngmarVG-IB
Copy link
Author

Thanks for the review @gemini-code-assist and @adk-bot!

Fixes Applied (commit a7adb4c)

Critical: **kwargs in wrapper functions — Fixed. _publish and _unpublish now have explicit parameter signatures matching the original functions (minus backend_name). This ensures FunctionTool can introspect parameters correctly for LLM tool schemas.

Type hintsa2a_agent_from_record now uses AgentRecord instead of Any. get_dns_aid_tools returns list["FunctionTool"].

Imports — Moved dns_aid.core.models imports to top of dns_aid_a2a_bridge.py.

Magic string — Extracted A2A_AGENT_CARD_PATH = "/.well-known/agent-card.json" constant.

Will create a GitHub issue and provide unit test results as requested.

@gemini-code-assist
Copy link
Contributor

Thanks for the update, @IngmarVG-IB!

It's great to see these improvements addressing key aspects of code quality and maintainability:

  • Explicit Parameter Signatures for Wrapper Functions: This is a critical improvement for the FunctionTool to correctly introspect parameters and generate accurate LLM tool schemas. It significantly enhances the reliability and usability of the DNS-AID tools within the ADK framework.
  • Improved Type Hints: Using more specific type hints like AgentRecord and list["FunctionTool"] greatly improves code readability, makes the code easier to understand, and allows for better static analysis, which is beneficial for long-term maintainability.
  • Consolidated Imports: Moving imports to the top of the file aligns with Python best practices (PEP 8) and contributes to better code organization and readability.
  • Extracted Magic String: Replacing the magic string with a named constant (A2A_AGENT_CARD_PATH) is an excellent practice that enhances readability and makes future modifications safer and easier.

I also note your plan to create a GitHub issue and provide unit test results, which will be very helpful for the review process. Keep up the great work!

@rohityan
Copy link
Collaborator

Hi @IngmarVG-IB , Thank you for your contribution! It appears you haven't yet signed the Contributor License Agreement (CLA). Please visit https://cla.developers.google.com/ to complete the signing process. Once the CLA is signed, we'll be able to proceed with the review of your PR. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tools [Component] This issue is related to tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Add DNS-AID tools for agent discovery via DNS

3 participants