Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions packages/uipath-google-adk/samples/multi-agent-remote/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Multi-Agent Remote (A2A) Sample

This sample demonstrates how to orchestrate **remote UiPath agents** via the [A2A protocol](https://google.github.io/A2A/) using Google ADK. A local coordinator agent delegates tasks to remote specialist agents hosted in UiPath, combining local orchestration with remote execution.

## Architecture

```
SequentialAgent (pipeline)
+-- Agent (coordinator) ........... local, delegates to remote sub-agents
| +-- RemoteA2aAgent (research_agent) ... UiPath Studio Web agent
| +-- RemoteA2aAgent (code_agent) ....... UiPath Studio Web agent
+-- Agent (formatter) ............. local, structures output as JSON
```

## Prerequisites

- [UiPath CLI](https://docs.uipath.com/cli) installed and configured
- Access to [UiPath Studio Web](https://cloud.uipath.com/)
- Python 3.10+

## Step 1: Create the Agents in UiPath Studio Web

Go to **UiPath Studio Web** and create a new solution (e.g. `MultiAgentSolution 1`) with two agents:

![UiPath Studio Web - ResearcherAgent](studio_web_screenshot.png)

### ResearcherAgent (Conversational Agent)

- **Model:** `anthropic.claude-sonnet-4-5-20250929-v1:0` (or any supported model)
- **System prompt:**

```
You are a research specialist. Use the search_web tool to find information about the given topic. Provide a thorough summary of your findings.
```

### PythonCoderAgent (Conversational Agent)

- **Model:** any supported model
- **System prompt:**

```
You are a Python developer. Given a topic, write a short, practical Python code example that demonstrates or relates to the topic. Use the run_python tool to execute your code and verify it works. Return both the code and its output.
```

## Step 2: Deploy and Configure

1. **Publish** the solution from Studio Web
2. **Deploy** the solution to a folder in Orchestrator
3. Note down the **folder key** (from the folder URL) and the **release IDs** for each agent
4. Update [main.py](main.py) with your values:

```python
ORG_NAME = "YourOrgName"
TENANT_NAME = "YourTenantName"
RESEARCH_AGENT_FOLDER_KEY = "<your-folder-key>"
RESEARCH_AGENT_RELEASE_ID = "<your-release-id>"
CODE_AGENT_FOLDER_KEY = "<your-folder-key>"
CODE_AGENT_RELEASE_ID = "<your-release-id>"
```

## Step 3: Run

```bash
uipath auth
uipath dev web
```

This authenticates with UiPath Cloud and starts the local dev server with the ADK agent pipeline.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
flowchart TB
__start__(__start__)
pipeline(pipeline)
coordinator(coordinator)
research_agent(research_agent)
code_agent(code_agent)
formatter(formatter)
__end__(__end__)
coordinator --> research_agent
research_agent --> coordinator
coordinator --> code_agent
code_agent --> coordinator
pipeline --> coordinator
coordinator --> pipeline
pipeline --> formatter
formatter --> pipeline
__start__ --> |input|pipeline
pipeline --> |output|__end__
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"agents": {
"agent": "main.py:agent"
}
}
127 changes: 127 additions & 0 deletions packages/uipath-google-adk/samples/multi-agent-remote/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
"""Google ADK multi-agent-remote example: same pipeline as multi-agent but with sub-agents hosted remotely via A2A.

Demonstrates how to mix local orchestration with remote agent implementations:
- Coordinator and formatter run locally (they hold the orchestration logic)
- Specialist sub-agents (research, code) are RemoteA2aAgent instances hosted elsewhere
- The remote services don't need to know about each other — coordination stays local

Compare with the multi-agent sample:
multi-agent: Agent(tools=[search_web]) Agent(tools=[run_python])
multi-agent-remote: RemoteA2aAgent(agent_card=...) for each specialist

The key insight: RemoteA2aAgent cannot have sub_agents (it's not an LlmAgent),
but a local Agent CAN have RemoteA2aAgent instances as its sub_agents. This lets
you keep orchestration logic local while moving implementations to remote services.
"""

import os

import httpx
from a2a.client.client import ClientConfig as A2AClientConfig
from a2a.client.client_factory import ClientFactory as A2AClientFactory
from a2a.types import TransportProtocol as A2ATransport
from google.adk.agents import Agent, SequentialAgent
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
from pydantic import BaseModel, Field


class ReportInput(BaseModel):
"""Structured input for the report generation pipeline."""

topic: str = Field(
default="Natural Language Processing fundamentals",
description="The topic to research and analyze",
)
depth: str = Field(
default="standard",
description="How deep the analysis should be: 'brief', 'standard', or 'detailed'",
)


class ReportOutput(BaseModel):
"""Structured output from the report generation pipeline."""

title: str = Field(description="Report title")
summary: str = Field(description="Executive summary of findings")
key_findings: list[str] = Field(description="Key findings as bullet points")
code_snippet: str = Field(description="A relevant Python code example")


# UIPATH_ACCESS_TOKEN is set automatically by `uipath auth`
_access_token = os.environ.get("UIPATH_ACCESS_TOKEN", "")

_http_client = httpx.AsyncClient(
headers={"Authorization": f"Bearer {_access_token}"},
timeout=httpx.Timeout(300.0),
)

_a2a_client_factory = A2AClientFactory(
config=A2AClientConfig(
httpx_client=_http_client,
supported_transports=[A2ATransport.jsonrpc],
streaming=False,
polling=False,
accepted_output_modes=["text"],
),
)

# --- Remote Sub-agents ---
# Replace the URLs with your actual deployed agent endpoints.
ORG_NAME = "YourOrgName"
TENANT_NAME = "YourTenantName"
RESEARCH_AGENT_FOLDER_KEY = "a11f72b1-90fd-4b30-b733-f0285cbf4a19"
RESEARCH_AGENT_RELEASE_ID = "1234"
CODE_AGENT_FOLDER_KEY = "b22f83c2-91fe-5c41-c844-g1396dcg5b2a"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we commit these ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those are just example guids not real

CODE_AGENT_RELEASE_ID = "5678"

research_agent = RemoteA2aAgent(
name="research_agent",
agent_card=f"https://cloud.uipath.com/{ORG_NAME}/{TENANT_NAME}/agenthub_/a2a/{RESEARCH_AGENT_FOLDER_KEY}/{RESEARCH_AGENT_RELEASE_ID}/.well-known/agent-card.json",
description="Remote research specialist that searches the web and summarizes findings",
a2a_client_factory=_a2a_client_factory,
)

code_agent = RemoteA2aAgent(
name="code_agent",
agent_card=f"https://cloud.uipath.com/{ORG_NAME}/{TENANT_NAME}/agenthub_/a2a/{CODE_AGENT_FOLDER_KEY}/{CODE_AGENT_RELEASE_ID}/.well-known/agent-card.json",
description="Remote Python developer that writes and executes code examples",
a2a_client_factory=_a2a_client_factory,
)


# --- Coordinator (local Agent, sub_agents are remote) ---
coordinator = Agent(
name="coordinator",
model="gemini-2.5-flash",
instruction=(
"You are a report coordinator. Given a topic:\n"
"1. Delegate research to research_agent to gather information\n"
"2. Delegate to code_agent to write a relevant Python code example\n"
"3. Compile all findings into a comprehensive text report\n"
"Include the research findings and the code example in your response."
),
sub_agents=[research_agent, code_agent],
input_schema=ReportInput,
output_key="research_results",
)


# --- Formatter (local Agent with output_schema) ---
formatter = Agent(
name="formatter",
model="gemini-2.5-flash",
instruction=(
"You are a report formatter. Take the research results from the previous "
"step and format them into a structured report with a title, summary, "
"key findings, and a code snippet. Output valid JSON matching the schema."
),
output_schema=ReportOutput,
output_key="report",
)


# --- Root: SequentialAgent pipeline ---
agent = SequentialAgent(
name="pipeline",
sub_agents=[coordinator, formatter],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[project]
name = "multi-agent-remote"
version = "0.0.1"
description = "Google ADK multi-agent example with RemoteA2aAgent sub-agents via A2A protocol"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"uipath-google-adk",
"google-adk[a2a]>=1.25.0",
"uipath>=2.8.18, <2.9.0",
]

[dependency-groups]
dev = [
"uipath-dev",
]

[tool.uv]
override-dependencies = ["opentelemetry-sdk>=1.39.0,<1.40.0"]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions packages/uipath-google-adk/samples/multi-agent-remote/uipath.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"$schema": "https://cloud.uipath.com/draft/2024-12/uipath",
"runtimeOptions": {
"isConversational": false
},
"packOptions": {
"fileExtensionsIncluded": [],
"filesIncluded": [],
"filesExcluded": [],
"directoriesExcluded": [],
"includeUvLock": true
},
"functions": {}
}