Adapters
Which agent frameworks are supported today — LangGraph, Google ADK, and Pydantic AI, plus the reference protocol — and what adopting each costs.
PartialPartly implemented. The page states what is missing.
Agent authoring belongs to frameworks; execution guarantees belong here. That split only works if the adapters exist. Today three do, and each holds a seat on the same conformance matrix.
| Framework | Status |
|---|---|
| LangGraph | Implemented — src/beam_agents/adapters/langgraph/, langgraph extra |
| Google ADK | Implemented — src/beam_agents/adapters/adk/, adk extra |
| Pydantic AI | Implemented — src/beam_agents/adapters/pydantic_ai/, pydantic-ai extra |
| Reference protocol agent (a plain async function) | Implemented — no adapter needed |
Each adapter is an optional extra, imported lazily: without the extra
installed, accessing its entry point raises an ImportError naming the extra
to install.
The LangGraph adapter
Adopting an existing graph takes three changes, none to its topology:
- Re-declare side-effectful tools with the runtime decorator:
@tool(side_effect=True). - Swap LangGraph's prebuilt
ToolNodeforBeamToolNode(tools). - Wrap the graph:
RunAgent(LangGraphAgent(graph, chat_models=[model])).
def build_agent() -> LangGraphAgent:
"""An ordinary model/tools graph, wrapped rather than rewritten."""
model = _ChatModel(httpx.MockTransport(_tripwire))
graph: StateGraph = StateGraph(GraphState)
async def call_model(state: GraphState) -> GraphState:
response = await model.root_async_client._client.post(
"https://provider.example/v1/chat",
json={"model": "demo", "messages": _to_wire(state["messages"]), "temperature": 0},
)
data = response.json()
if "tool_call" in data:
return {"messages": [AIMessage(content="", tool_calls=[data["tool_call"]])]}
return {"messages": [AIMessage(content=data["content"])]}
def route(state: GraphState) -> str:
last = state["messages"][-1]
return "tools" if isinstance(last, AIMessage) and last.tool_calls else END
graph.add_node("model", call_model)
# The only topology-adjacent change: BeamToolNode in place of ToolNode.
graph.add_node("tools", BeamToolNode([page_oncall]))
graph.add_edge(START, "model")
graph.add_conditional_edges("model", route, {"tools": "tools", END: END})
graph.add_edge("tools", "model")
return LangGraphAgent(graph, chat_models=[model], encode_output=encode_output)A user-compiled graph is never mutated — the per-activation checkpointer is injected into a copy.
What the graph gains
Durable keyed checkpoints, side effects behind deduplicated intents,
replay-cached model calls, and per-key serialization. interrupt(...) suspends
the activation as an approval intent and resumes via Command(resume=...).
One suspension covers all pending graph work: each pending interrupt stages an intent, and re-injected results accumulate — the activation re-suspends, staging nothing new — until every pending intent is answered. The graph then resumes once, from the committed checkpoint.
What to know before relying on it
Two caveats, both documented by the adapter itself:
- Checkpoints persist latest-only inside working memory, and the 1 MiB per-key cap applies. Long message histories must be trimmed or summarized on the LangGraph side.
- An interrupted node re-runs from its start when the graph resumes — this
is LangGraph's own resume semantics, not something the adapter adds. Code
before an
interrupt()executes again. Side effects can only live behind intents and model calls are replay-cached, so re-execution is deterministic and cheap, but pre-interrupt node code should be idempotent regardless. - Model transport. Recognized httpx-backed chat models are served through
the runtime's replay-cached client. An unrecognized one falls back to direct
calls with a one-time warning and a
transport_fallbackmetric — so it still works, but without the replay guarantee.
The Google ADK adapter
AdkAgent runs an ADK agent's Runner inside the activation, against a
per-key BeamSessionService — the session lives one-per-key under the
reserved __adk__/ memory namespace, so it commits and replays with
everything else. Side-effect tools become long-running function calls staged
as intents, one suspension covers all pending work, the event stream is teed
onto the runtime's trace vocabulary, and recognized google-genai clients are
routed through the replay-cached model path with a warning fallback for the
rest. Installed from the adk extra.
The Pydantic AI adapter
PydanticAIAgent runs one Agent.run segment per activation. Message history
persists latest-only under the reserved __pydantic_ai__/ namespace, deferred
tool calls map to intents with one suspension covering all of them, and
runtime tools ride BeamToolset — read-only tools execute inline, side
effects go external, approvals are gated. Recognized httpx-backed models are
served through the replay-cached model path, with the same warning fallback as
the other adapters. Installed from the pydantic-ai extra.
The conformance matrix
Adapters are not trusted on assertion. Seven lifecycle scenarios run against every registered adapter — the reference protocol agent, LangGraph, Google ADK, and Pydantic AI — across the DirectRunner and Flink legs, and a meta-test audits registry × scenario × leg against the collected cells so the matrix cannot silently shrink. An importable adapter subpackage without a registration fails collection outright.
That is why this page can say "implemented" three times with more confidence than a support table usually deserves.
Not yet implemented
- Read-only MCP. Named in the module map under
tools/; no code.
Related
What backs this page
- Symbol
- beam_agents.LangGraphAgent
- Symbol
- beam_agents.AdkAgent
- Symbol
- beam_agents.PydanticAIAgent
- Source
- src/beam_agents/adapters/langgraph/agent.py
- Source
- src/beam_agents/adapters/langgraph/toolnode.py
- Source
- src/beam_agents/adapters/langgraph/checkpoint.py
- Source
- src/beam_agents/adapters/adk/agent.py
- Source
- src/beam_agents/adapters/adk/session.py
- Source
- src/beam_agents/adapters/adk/tools.py
- Source
- src/beam_agents/adapters/pydantic_ai/agent.py
- Source
- src/beam_agents/adapters/pydantic_ai/toolset.py
- Source
- src/beam_agents/adapters/pydantic_ai/history.py
- Source
- docs/adapters.md
- Specification
- openspec/specs/tool-registry/spec.md
- Specification
- openspec/specs/langgraph-adapter/spec.md
- Specification
- openspec/specs/pydantic-ai-adapter/spec.md
- Specification
- openspec/specs/adapter-conformance-matrix/spec.md
- Test
- tests/adapters/test_e2e_pipeline.py
- Test
- tests/adapters/adk/test_agent_fast_path.py
- Test
- tests/adapters/pydantic_ai/test_agent_fast_path.py
- Test
- tests/conformance/test_matrix.py
- Test
- tests/conformance/test_adk_registration.py
- Example
- langgraph_adapter.py
Cited sources
LangGraph is an agent-authoring framework maintained by LangChain.
https://github.com/langchain-ai/langgraph — retrieved
The Agent Development Kit (ADK) is an agent-authoring framework maintained by Google.
https://github.com/google/adk-python — retrieved
Pydantic AI is an agent-authoring framework maintained by the Pydantic team.
https://github.com/pydantic/pydantic-ai — retrieved