Building Multi-Agent Systems with Vertex AI and Llama model

Source notebook

Repo path: agents/agent_engine/tutorial_multi_agent_systems_vertexai_llama_arize.ipynb · Open on GitHub · advanced

Builds a traced Vertex AI multi-agent trading analyst with Gemini, Llama, ADK, A2A, and MCP tools.

Summary

It teaches how to create a trading analysis platform with a Bear risk analyst in Pydantic AI and a Bull opportunity analyst in Google ADK, coordinated through an ADK orchestrator using A2A. The workflow covers synthetic OHLCV market data generation, MCP tools for risk and opportunity analysis, local agent testing, and packaging agents for Vertex AI Agent Engine. It also configures Arize Phoenix and OpenInference tracing to monitor agent behavior, tool usage, and performance.

Key code patterns

Vertex AI notebook setup

PROJECT_ID = "[your-project-id]"
LOCATION = "us-central1"
os.environ["GOOGLE_CLOUD_PROJECT"] = PROJECT_ID
os.environ["GOOGLE_CLOUD_LOCATION"] = LOCATION
os.environ["GOOGLE_GENAI_USE_VERTEXAI"] = "TRUE"
nest_asyncio.apply()
client = vertexai.Client(project=PROJECT_ID, location=LOCATION)

Sets the Vertex AI project, region, GenAI-on-Vertex mode, and async notebook support.

Phoenix tracing

os.environ["PHOENIX_PROJECT_NAME"] = "trading-agent"
tracer_provider = register(
    project_name=os.environ["PHOENIX_PROJECT_NAME"],
    auto_instrument=True,
)

Enables automatic observability for agent behavior, tool calls, and performance.

MCP tool definition

bear_mcp = FastMCP("bear-agent-tools")
 
@bear_mcp.tool()
async def risk_scanner(symbol: str) -> str:
    prices = market_generator.generate_price_series(symbol, days=30)
    current_price = prices[-1]["close"]
    closes = [p["close"] for p in prices]
    rsi = market_generator._calculate_rsi(closes)
    return f"RISK ANALYSIS FOR {symbol}\nCurrent Price: ${current_price}\nRSI: {rsi:.1f}"

Wraps specialized market-analysis logic as MCP tools callable by agents.

Pydantic AI Bear agent

provider = GoogleProvider(vertexai=True)
model = GoogleModel("gemini-2.5-flash", provider=provider)
 
bear_agent = Agent(
    model=model,
    system_prompt=bear_system_prompt,
    tools=[risk_scanner, divergence_detector, exit_signal_monitor],
    retries=2,
    instrument=True,
)

Builds the risk-focused agent on Gemini through Vertex AI with tracing enabled.

ADK Bull agent with Llama

llama_model = "vertex_ai/meta/llama-3.3-70b-instruct-maas"
litellm.vertex_project = os.environ.get("GOOGLE_CLOUD_PROJECT")
litellm.vertex_location = os.environ.get("GOOGLE_CLOUD_REGION")
 
bull_agent = LlmAgent(
    name="bull_agent",
    model=LiteLlm(llama_model),
    tools=[find_breakout_patterns, momentum_screener, entry_signal_detector],
)

Routes an ADK agent to a Llama model on Vertex AI through LiteLLM.

A2A agent card

skills = [
    AgentSkill(
        id="risk_analysis",
        name="Risk Factor Scanner",
        description="Identifies potential downside catalysts and risk factors",
        tags=["Risk-Analysis", "Market-Analysis"],
    )
]
 
bear_agent_card = create_agent_card(
    agent_name="Bear Risk Analyst (Pydantic AI + MCP)",
    skills=skills,
)

Advertises agent capabilities for A2A discovery and routing.

Deployed executor lazy init

class BearAgentExecutor(AgentExecutor):
    def __init__(self):
        self.agent = None
        self.register = None
 
    def _init_agent(self):
        if self.agent is None:
            provider = GoogleProvider(vertexai=True)
            model = GoogleModel("gemini-2.5-flash", provider=provider)
            mcp_server = MCPServerStdio("python", args=["mcp_tools/bear_mcp_server.py"], timeout=60)

Initializes deployed agent resources only at runtime to avoid pickling issues.

Models & APIs used

  • Models: gemini-2.5-flash, vertex_ai/meta/llama-3.3-70b-instruct-maas
  • APIs / services: Vertex AI API, Vertex AI Agent Engine, Cloud Storage
  • SDKs / libraries: vertexai, google-cloud-aiplatform[agent_engines,adk], google-adk, google-genai, a2a-sdk, litellm, pydantic-ai, fastmcp, arize-phoenix, openinference-instrumentation-google-adk, openinference-instrumentation-pydantic-ai, opentelemetry, nest-asyncio, numpy

When to use this

Use this pattern when building a Vertex AI Agent Engine multi-agent system with ADK, Pydantic AI, A2A coordination, MCP tools, and tracing.

Gotchas & caveats

  • Requires an Arize Phoenix Cloud account and updated PHOENIX_API_KEY, PHOENIX_BASE_URL, and PHOENIX_COLLECTOR_ENDPOINT values.
  • Requires a Google Cloud project with Vertex AI API enabled and permissions to deploy agents to Vertex AI Agent Engine.
  • Colab users must restart the runtime after installing packages.
  • Async code in Jupyter relies on nest_asyncio.apply().
  • The notebook uses synthetic random market data, not live financial data.
  • LiteLLM reads GOOGLE_CLOUD_REGION while setup defines GOOGLE_CLOUD_LOCATION, so region configuration must be consistent.
  • The deployed Bear agent starts MCP with python mcp_tools/bear_mcp_server.py, so package paths and dependencies must be available in deployment.
  • BearAgentExecutor.cancel raises UnsupportedOperationError, so cancellation is not supported.

Best practices

  • Test the Bear and Bull agents locally before deployment.
  • Use separate role-specific prompts for risk-focused and opportunity-focused agents.
  • Expose agent capabilities through A2A Agent Cards with skills, tags, and examples.
  • Package MCP tools as importable modules with a separate stdio server entry point.
  • Use lazy initialization in deployed executors to avoid pickling issues.
  • Enable Phoenix/OpenInference tracing for agent behavior, tool usage, and performance monitoring.
  • Use ADK Runner with an in-memory session service to test local conversation flow.