Skip to main content
This page explains message mapping at a higher level than ADK Message Mapping. The goal is to show what an ADK agent receives, how Aion interprets the response on the way back out, and how messaging distributions keep the reply anchored to the original context.

Overview

The default Google ADK message-mapping flow is:
  1. A distribution or client sends an A2A request into Aion Server.
  2. Aion exposes the request through ctx.a2a_inbox.
  3. Your agent yields events that may populate the SDK response buffer or provide an explicit A2A outbox.
  4. Aion resolves those events into a final A2A Message or Task.
  5. The caller or distribution delivers the response into the original context.

What Your Agent Receives

The main integration surface is ctx.a2a_inbox:
from google.adk.agents import BaseAgent


class MyAgent(BaseAgent):
    async def _run_async_impl(self, ctx):
        inbox = ctx.a2a_inbox
        task = inbox.task
        message = inbox.message
        metadata = inbox.metadata
This keeps the framework-facing API simple while still exposing the full transport envelope when a distribution needs to preserve channel, thread, or provider-specific context.

Default Response Precedence

Google ADK should follow the same general precedence as the other framework adapters:
  1. SDK-managed response buffer This is authoritative when populated. It includes helper-emitted reply content, final non-partial message content, and partial stream output that is intended to become the durable reply for the current turn.
  2. a2a_outbox Use this when you want full control over the outbound A2A payload.
  3. Framework-native fallback If neither the SDK buffer nor a2a_outbox is used, Aion falls back to the current turn’s partial stream accumulation first and then to the final non-partial agent-authored event content.

Explicit A2A Outbox

from a2a.types import Message, Part, Role
from aion.shared.types import A2AOutbox
from google.adk.events import Event, EventActions


class ExplicitAgent(BaseAgent):
    async def _run_async_impl(self, ctx):
        yield Event(
            author=self.name,
            actions=EventActions(
                state_delta={
                    "a2a_outbox": A2AOutbox(
                        message=Message(
                            role=Role.ROLE_AGENT,
                            parts=[Part(text="Done!")],
                        )
                    )
                }
            ),
        )

Framework-Native Fallback

from google.adk.agents import BaseAgent
from google.adk.events import Event


class SimpleAgent(BaseAgent):
    async def _run_async_impl(self, ctx):
        yield Event(
            author=self.name,
            content={"parts": [{"text": "Here is the answer."}]},
        )

What Happens in a Distribution Flow

For messaging distributions, the default routing target should be preserved automatically:
  • DM in, DM out
  • reply in, reply out
  • shared conversation in, same shared conversation out
That routing information lives in the inbound distribution payload and event parts. Your agent does not need to re-specify it unless it wants to override the default behavior.

Example: Slack Mention

from google.adk.agents import BaseAgent
from google.adk.events import Event


class SlackMentionAgent(BaseAgent):
    async def _run_async_impl(self, ctx):
        text = ctx.a2a_inbox.message.parts[0].text
        yield Event(
            author=self.name,
            content={"parts": [{"text": f"Slack mention received: {text}"}]},
        )
Default behavior:
  1. Slack distribution receives a configured mention event.
  2. Aion exposes that request through ctx.a2a_inbox.
  3. The agent emits a normal text response.
  4. Slack distribution replies in the same conversation or thread.

Example: Telegram DM

from google.adk.agents import BaseAgent
from google.adk.events import Event


class TelegramDMAgent(BaseAgent):
    async def _run_async_impl(self, ctx):
        text = ctx.a2a_inbox.message.parts[0].text
        yield Event(
            author=self.name,
            content={"parts": [{"text": f"Telegram DM received: {text}"}]},
        )
Because the inbound request carries the Telegram chat context, the distribution can return the final reply to that same DM automatically.

When to Reach for a2a_outbox

Use a2a_outbox when:
  • you need structured parts rather than plain text
  • you want to emit a provider-neutral card payload
  • you need to override the default outbound target
  • you want to return a task patch instead of a single message
If you only want a normal text reply, a straightforward final ADK event should be enough.

Next Step

For the lower-level adapter rules, see ADK Message Mapping.