Skip to content

Configurable Context Builder for RemoteA2aAgent #3301

@eranco74

Description

@eranco74

Is your feature request related to a problem? Please describe.

The current implementation of RemoteA2aAgent uses a fixed method, _construct_message_parts_from_session, to build the context for remote A2A calls.
This logic iterates through session events to construct the conversation history to be sent to the remote agent.
all session events, including user messages, agent replies, function_calls and function_response with "For context:" string prepended to each message part.

While the current implementation correctly optimizes by excluding the current agent's own previous response from the history it sends, this fixed behavior leads to several limitations:

  • Lack of Flexibility: Different specialized agents require different context strategies. A stateless agent only needs the current message, while a complex agent might benefit from a summarized history.

  • Token Inefficiency and Cost: Passing the full history consumes significant tokens for every remote A2A invocation, leading to increased latency and operational costs, especially in long conversations.

  • Maintenance Overhead: The only way for users to implement custom context strategies (like sliding windows or summarization) is by using high-boilerplate, less-discoverable methods like monkey-patching the internal _construct_message_parts_from_session method.

Describe the solution you'd like

I propose adding a new optional parameter, context_builder, to the RemoteA2aAgent.init() method to enable flexible, user-defined context generation.

This new parameter will accept a callable that will replace the entire functionality of the fixed context generation method (i.e., _construct_message_parts_from_session) when provided.

  1. API Design: ContextBuilder Protocol
    The custom callable must adhere to the following ContextBuilder Protocol:
from typing import Callable, Protocol
from google.adk.agents.invocation_context import InvocationContext
from a2a.types import Part as A2APart

class ContextBuilder(Protocol):
    """Protocol for custom context builder functions."""
    
    def __call__(
        self,
        ctx: InvocationContext,
        agent_name: str,
        genai_part_converter: Callable
    ) -> tuple[list[A2APart], str | None]:
        """
        Build A2A message parts from the ADK session context.
        
        Args:
            ctx: The invocation context containing session events.
            agent_name: Name of the current RemoteA2aAgent instance.
            genai_part_converter: Function to convert ADK GenAI parts to A2A parts.
            
        Returns:
            Tuple of (message_parts, context_id).
        """
        ...
  1. Implementation Logic and Benefits
    When context_builder is provided, the RemoteA2aAgent will execute this custom function to determine the message_parts and context_id. This grants the developer full control to:
  • Implement summarization (using an LLM to condense history).
  • Use sliding windows (sending only the last $N$ turns).
  • Selectively filter history based on message metadata or author.
  • Preserve the existing optimization (or customize it) by controlling which messages are sent.

If context_builder is None, the agent will fall back to the existing logic in _construct_message_parts_from_session, preserving backward compatibility.

Describe alternatives you've considered

  • Subclassing: Requiring users to inherit from RemoteA2aAgent and override the protected method _construct_message_parts_from_session is overly verbose, non-composable, and requires deeper knowledge of internal methods.

  • Enum-based Strategy Selection: Implementing a fixed set of strategies (e.g., FULL_HISTORY, SUMMARY, CURRENT_ONLY) is too restrictive and would not allow for custom, domain-specific logic, such as incorporating token budget limits or selective filtering based on message metadata.

Additional context

#2956 (comment)
The existing fixed implementation of _construct_message_parts_from_session is responsible for iterating through the session history and utilizing functions like _present_other_agent_message (found in google/adk/flows/llm_flows/contents.py) to properly format user and agent messages into the structured A2APart format, ensuring the agent and user roles are correctly maintained for the remote agent.

The custom context_builder function will take over this entire process, allowing the developer to control which events are included and how they are formatted (using the provided genai_part_converter) before the A2A request is sent.

Metadata

Metadata

Assignees

No one assigned

    Labels

    a2a[Component] This issue is related a2a support inside ADK.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions