Skip to main content

Migrating from Google ADK

Adopting SwarmD doesn’t require rewriting your agents. Your agent logic, tools, and prompts stay the same — what changes is how agents discover and connect to each other.

Before: Hardcoded remote agents

With standalone Google ADK, you wire up remote agents by hardcoding their URLs directly:
from google.adk.agents import LlmAgent
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
from google.adk.models.lite_llm import LiteLlm
from google.adk.tools.function_tool import FunctionTool

def get_weather(city: str) -> str:
    """Get the current weather for a city."""
    return f"The weather in {city} is sunny"

# Every remote agent is hardcoded
time_agent = RemoteA2aAgent(
    name="time_agent",
    description="Provides time information",
    agent_card="https://time-agent.internal:8080/.well-known/agent-card.json",
)

calendar_agent = RemoteA2aAgent(
    name="calendar_agent",
    description="Manages calendar events",
    agent_card="https://calendar-agent.internal:8080/.well-known/agent-card.json",
)

agent = LlmAgent(
    model=LiteLlm(model="openai/gpt-4o"),
    name="weather_agent",
    description="A weather agent that collaborates with other agents",
    instruction="You are a helpful weather agent.",
    tools=[FunctionTool(get_weather)],
    sub_agents=[time_agent, calendar_agent],
)
Problems with this approach:
  • Agent URLs are hardcoded — adding or removing agents requires a code change and redeployment
  • No centralized authentication between agents
  • No visibility into inter-agent traffic
  • No policy enforcement or approval workflows

After: Discovery through SwarmD

With SwarmD, remote agents are discovered from the registry at startup. Your agent logic is identical — only the wiring changes:
from uuid import UUID

from google.adk.agents import LlmAgent
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
from google.adk.models.lite_llm import LiteLlm
from google.adk.tools.function_tool import FunctionTool

from swarmd_sdk import SwarmDClient

def get_weather(city: str) -> str:
    """Get the current weather for a city."""
    return f"The weather in {city} is sunny"

# Discover remote agents from the SwarmD registry
client = SwarmDClient.from_env()
agent_id = UUID("your-agent-uuid")

subscriptions = client.get_agent_subscriptions(agent_id)
remote_agents = [
    RemoteA2aAgent(
        name=a.name,
        description=a.description,
        agent_card=a.agent_card_url,  # Routes through SwarmD relay
    )
    for a in subscriptions
]

agent = LlmAgent(
    model=LiteLlm(model="openai/gpt-4o"),
    name="weather_agent",
    description="A weather agent that collaborates with other agents",
    instruction="You are a helpful weather agent.",
    tools=[FunctionTool(get_weather)],
    sub_agents=remote_agents,  # Dynamically discovered
)
.env
SWARMD_AGENT_ID=your-agent-id
SWARMD_CLIENT_SECRET=your-client-secret
What you get:
  • Agents are discovered at runtime from the registry — no hardcoded URLs
  • OAuth2 authentication is handled by the SDK
  • All traffic routes through the relay with audit logging, policy enforcement, and HITL approval support
  • Adding or removing agents is a subscription change in the dashboard, not a code change

What stays the same

  • Your LlmAgent definition (model, name, instruction, tools)
  • Your tool functions
  • Your A2A server setup (Starlette, runner, task store)
  • The RemoteA2aAgent interface — you’re still passing name, description, and agent_card

Migration steps

  1. Install the SDKpip install swarmd-sdk
  2. Register your agent on SwarmD via the dashboard or Registry API
  3. Subscribe to the downstream agents your agent needs
  4. Set credentials — add SWARMD_AGENT_ID and SWARMD_CLIENT_SECRET to your environment
  5. Replace hardcoded RemoteA2aAgent lists with the discovery pattern shown above