Skip to main content
This page describes the three authoring styles we want LangGraph developers to be able to choose from. The goal is not to force one SDK shape onto every graph. Aion should work well for plain LangGraph graphs, for explicit A2A-aware graphs, and for a higher-level fluent SDK surface.

1. Plain LangGraph

Use plain LangGraph when you only need normal conversational input and output.
from typing import Annotated, TypedDict

from langchain_core.messages import AIMessage, AnyMessage
from langgraph.graph import END, START, StateGraph
from langgraph.graph.message import add_messages


class State(TypedDict):
    messages: Annotated[list[AnyMessage], add_messages]


def reply_node(state: State) -> dict:
    reply = model.invoke(state["messages"])
    return {"messages": [reply]}


builder = StateGraph(State)
builder.add_node("reply", reply_node)
builder.add_edge(START, "reply")
builder.add_edge("reply", END)
graph = builder.compile()
In this mode:
  • Aion maps inbound text into state.messages
  • Aion infers the final reply from streamed model output or the last agent-authored AIMessage
  • the graph does not need any Aion-specific dependency
This is the best fit for basic chat agents.

2. Hybrid A2A

Use hybrid authoring when you want raw protocol access without adopting the higher-level fluent SDK.
from typing import Annotated, Optional, TypedDict

from a2a.types import Message, Part, Role
from aion.shared.types import A2AInbox, A2AOutbox
from langchain_core.messages import AnyMessage
from langgraph.graph.message import add_messages


class State(TypedDict):
    messages: Annotated[list[AnyMessage], add_messages]
    a2a_inbox: Optional[A2AInbox]
    a2a_outbox: Optional[A2AOutbox]


def reply_node(state: State) -> dict:
    return {
        "a2a_outbox": A2AOutbox(
            message=Message(
                role=Role.ROLE_AGENT,
                parts=[Part(text="Structured reply")],
            )
        )
    }
In this mode:
  • a2a_inbox gives you direct access to the inbound task, message, and request metadata
  • a2a_outbox gives you direct control over the outbound A2A object
  • LangGraph still provides ordinary state.messages for model-facing logic
This is the best fit when you need structured parts, explicit metadata, or fine-grained protocol control.

3. SDK-aware LangGraph

Use the planned aion-langgraph fluent surface when you want normalized messaging primitives without hand-assembling A2A envelopes.
from typing import Annotated, TypedDict

from langchain_core.messages import AnyMessage
from langgraph.graph import END, START, StateGraph
from langgraph.graph.message import add_messages
from langgraph.runtime import Runtime

from aion.langgraph import AionContext


class State(TypedDict):
    messages: Annotated[list[AnyMessage], add_messages]


async def reply_node(state: State, runtime: Runtime[AionContext]) -> dict:
    thread = runtime.context.thread
    recent = await thread.history(limit=5)

    await thread.reply("I checked the last five messages.")
    return {}


builder = StateGraph(State, context_schema=AionContext)
builder.add_node("reply", reply_node)
builder.add_edge(START, "reply")
builder.add_edge("reply", END)
graph = builder.compile()
In this mode:
  • request-scoped routing data stays in LangGraph runtime context, not graph state
  • helper APIs write into the shared response buffer first
  • thread.reply(...), thread.post(...), and streamed helper output all feed the same response compiler
This is the best fit when you want a Vercel-style authoring experience while still mapping to Aion’s generic A2A extensions.

Which Pattern to Choose

PatternBest forMain tradeoff
Plain LangGraphSimple text-first chat flowsLeast control over protocol details
Hybrid A2AFull A2A control with minimal new abstractionsMore verbose authoring
SDK-aware LangGraphFluent thread and message helpersDepends on the planned SDK surface
It is important that these modes compose cleanly. A graph should be able to use the fluent SDK for one turn, a2a_outbox for another, and plain LangGraph fallback for the rest without switching adapters.