From 968a990a172e3c52b1d8262ffcb682667d1c9ce9 Mon Sep 17 00:00:00 2001 From: "fangyaozheng@bytedance.com" Date: Mon, 4 Aug 2025 13:26:34 +0800 Subject: [PATCH] feat: add remote agent --- docs/docs/agent.md | 29 ++++++++++++++++++++++++++++- veadk/a2a/remote_ve_agent.py | 21 +++++++++++++++++++++ veadk/runner.py | 18 ++++++++---------- 3 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 veadk/a2a/remote_ve_agent.py diff --git a/docs/docs/agent.md b/docs/docs/agent.md index 70b9d5e1..ae0b064f 100644 --- a/docs/docs/agent.md +++ b/docs/docs/agent.md @@ -15,6 +15,28 @@ Agent中主要包括如下属性: | knowledgebase | Vector database | 知识库,后端通常为一个向量数据库(Vector database),能够检索 | | tracers | list | 追踪器列表,能够定义不同的追踪方式,并在Agent执行完毕后对整体Tracing信息保存至本地 | +## A2A智能体 + +当你的智能体部署到云上后,可以在本地被初始化为一个Remote Agent,也就是能够通过A2A协议来访问的智能体,初始化方法如下: + +```python +remote_agent = RemoteVeAgent( + name="a2a_agent", + url="..." # <--- url from cloud platform +) + +short_term_memory = ShortTermMemory() +runner = Runner( + agent=remote_agent, + short_term_memory=short_term_memory + ) + +res = await runner.run( + messages="...", + session_id="sample_session" + ) +``` + ## 运行 在生产环境中,我们推荐您使用`Runner`来进行多租户服务: @@ -29,6 +51,11 @@ USER_ID = "" SESSION_ID = "" agent = Agent() -runner = Runner(agent=agent, short_term_memory=ShortTermMemory()) + +runner = Runner( + agent=agent, + short_term_memory=ShortTermMemory() + ) + response = await runner.run(messages=prompt, session_id=session_id) ``` diff --git a/veadk/a2a/remote_ve_agent.py b/veadk/a2a/remote_ve_agent.py new file mode 100644 index 00000000..1be9d347 --- /dev/null +++ b/veadk/a2a/remote_ve_agent.py @@ -0,0 +1,21 @@ +import json + +import requests +from a2a.types import AgentCard +from google.adk.agents.remote_a2a_agent import RemoteA2aAgent + +AGENT_CARD_WELL_KNOWN_PATH = "/.well-known/agent-card.json" + + +class RemoteVeAgent(RemoteA2aAgent): + def __init__(self, name: str, url: str): + agent_card_dict = requests.get(url + AGENT_CARD_WELL_KNOWN_PATH).json() + agent_card_dict["url"] = url + + agent_card_json_str = json.dumps(agent_card_dict, ensure_ascii=False, indent=2) + + agent_card_object = AgentCard.model_validate_json(str(agent_card_json_str)) + + super().__init__( + name=name, description="weather reporter", agent_card=agent_card_object + ) diff --git a/veadk/runner.py b/veadk/runner.py index cf1f1612..f0d6db50 100644 --- a/veadk/runner.py +++ b/veadk/runner.py @@ -19,6 +19,7 @@ from google.genai import types from google.genai.types import Blob +from veadk.a2a.remote_ve_agent import RemoteVeAgent from veadk.agent import Agent from veadk.evaluation import EvalSetRecorder from veadk.memory.short_term_memory import ShortTermMemory @@ -41,7 +42,7 @@ class Runner: def __init__( self, - agent: Agent, + agent: Agent | RemoteVeAgent, short_term_memory: ShortTermMemory, app_name: str = "veadk_default_app", user_id: str = "veadk_default_user", @@ -56,7 +57,10 @@ def __init__( self.short_term_memory = short_term_memory self.session_service = short_term_memory.session_service - self.long_term_memory = self.agent.long_term_memory + if isinstance(self.agent, Agent): + self.long_term_memory = self.agent.long_term_memory + else: + self.long_term_memory = None # maintain a in-memory runner for fast inference self.runner = ADKRunner( @@ -67,13 +71,6 @@ def __init__( ) def _convert_messages(self, messages) -> list: - # RunnerMessage = Union[ - # str, # single turn text-based prompt - # list[str], # multiple turn text-based prompt - # dict, # single turn prompt with media - # list[dict], # multiple turn prompt with media - # list[dict | str], # multiple turn prompt with media and text-based prompt - # ] if isinstance(messages, str): messages = [types.Content(role="user", parts=[types.Part(text=messages)])] elif isinstance(messages, MediaMessage): @@ -159,7 +156,8 @@ async def run( final_output = await self._run(session_id, message, stream) # try to save tracing file - self.save_tracing_file(session_id) + if isinstance(self.agent, Agent): + self.save_tracing_file(session_id) return final_output