Skip to content
15 changes: 10 additions & 5 deletions agentrun/agent_runtime/__runtime_async_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class AgentRuntime(
delete, update, query, and endpoint/version management.
"""

_data_api: Dict[str, AgentRuntimeDataAPI] = {}

@classmethod
def __get_client(cls):
"""获取客户端实例 / Get client instance
Expand Down Expand Up @@ -462,16 +464,19 @@ async def invoke_openai_async(
cfg = Config.with_configs(self._config, kwargs.get("config"))
kwargs["config"] = cfg

if not self.__data_api:
self.__data_api: Dict[str, AgentRuntimeDataAPI] = {}
if not self._data_api:
self._data_api: Dict[str, AgentRuntimeDataAPI] = {}

if self.__data_api[agent_runtime_endpoint_name] is None:
self.__data_api[agent_runtime_endpoint_name] = AgentRuntimeDataAPI(
if (
agent_runtime_endpoint_name not in self._data_api
or self._data_api[agent_runtime_endpoint_name] is None
):
self._data_api[agent_runtime_endpoint_name] = AgentRuntimeDataAPI(
agent_runtime_name=self.agent_runtime_name or "",
agent_runtime_endpoint_name=agent_runtime_endpoint_name or "",
config=cfg,
)

return await self.__data_api[
return await self._data_api[
agent_runtime_endpoint_name
].invoke_openai_async(**kwargs)
11 changes: 9 additions & 2 deletions agentrun/agent_runtime/api/__data_async_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,15 @@ async def invoke_openai_async(
config = kwargs.get("config", None)

cfg = Config.with_configs(self.config, config)
api_base = self.with_path("openai/v1")
_, headers, _ = self.auth(headers=cfg.get_headers())
api_base = self.with_path("openai/v1", config=cfg)
# Sign the actual request URL (OpenAI client will POST to base + /chat/completions)
chat_completions_url = api_base.rstrip("/") + "/chat/completions"
_, headers, _ = self.auth(
url=chat_completions_url,
headers=cfg.get_headers(),
config=cfg,
method="POST",
)

from httpx import AsyncClient
from openai import AsyncOpenAI
Expand Down
22 changes: 18 additions & 4 deletions agentrun/agent_runtime/api/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,15 @@ async def invoke_openai_async(
config = kwargs.get("config", None)

cfg = Config.with_configs(self.config, config)
api_base = self.with_path("openai/v1")
_, headers, _ = self.auth(headers=cfg.get_headers())
api_base = self.with_path("openai/v1", config=cfg)
# Sign the actual request URL (OpenAI client will POST to base + /chat/completions)
chat_completions_url = api_base.rstrip("/") + "/chat/completions"
_, headers, _ = self.auth(
url=chat_completions_url,
headers=cfg.get_headers(),
config=cfg,
method="POST",
)

from httpx import AsyncClient
from openai import AsyncOpenAI
Expand Down Expand Up @@ -77,8 +84,15 @@ def invoke_openai(
config = kwargs.get("config", None)

cfg = Config.with_configs(self.config, config)
api_base = self.with_path("openai/v1")
_, headers, _ = self.auth(headers=cfg.get_headers())
api_base = self.with_path("openai/v1", config=cfg)
# Sign the actual request URL (OpenAI client will POST to base + /chat/completions)
chat_completions_url = api_base.rstrip("/") + "/chat/completions"
_, headers, _ = self.auth(
url=chat_completions_url,
headers=cfg.get_headers(),
config=cfg,
method="POST",
)

from httpx import Client
from openai import OpenAI
Expand Down
28 changes: 18 additions & 10 deletions agentrun/agent_runtime/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class AgentRuntime(
delete, update, query, and endpoint/version management.
"""

_data_api: Dict[str, AgentRuntimeDataAPI] = {}

@classmethod
def __get_client(cls):
"""获取客户端实例 / Get client instance
Expand Down Expand Up @@ -867,17 +869,20 @@ async def invoke_openai_async(
cfg = Config.with_configs(self._config, kwargs.get("config"))
kwargs["config"] = cfg

if not self.__data_api:
self.__data_api: Dict[str, AgentRuntimeDataAPI] = {}
if not self._data_api:
self._data_api: Dict[str, AgentRuntimeDataAPI] = {}

if self.__data_api[agent_runtime_endpoint_name] is None:
self.__data_api[agent_runtime_endpoint_name] = AgentRuntimeDataAPI(
if (
agent_runtime_endpoint_name in self._data_api
and self._data_api[agent_runtime_endpoint_name] is None
):
self._data_api[agent_runtime_endpoint_name] = AgentRuntimeDataAPI(
agent_runtime_name=self.agent_runtime_name or "",
agent_runtime_endpoint_name=agent_runtime_endpoint_name or "",
config=cfg,
)

return await self.__data_api[
return await self._data_api[
agent_runtime_endpoint_name
].invoke_openai_async(**kwargs)

Expand All @@ -889,16 +894,19 @@ def invoke_openai(
cfg = Config.with_configs(self._config, kwargs.get("config"))
kwargs["config"] = cfg

if not self.__data_api:
self.__data_api: Dict[str, AgentRuntimeDataAPI] = {}
if not self._data_api:
self._data_api: Dict[str, AgentRuntimeDataAPI] = {}

if self.__data_api[agent_runtime_endpoint_name] is None:
self.__data_api[agent_runtime_endpoint_name] = AgentRuntimeDataAPI(
if (
agent_runtime_endpoint_name not in self._data_api
or self._data_api[agent_runtime_endpoint_name] is None
):
self._data_api[agent_runtime_endpoint_name] = AgentRuntimeDataAPI(
agent_runtime_name=self.agent_runtime_name or "",
agent_runtime_endpoint_name=agent_runtime_endpoint_name or "",
config=cfg,
)

return self.__data_api[agent_runtime_endpoint_name].invoke_openai(
return self._data_api[agent_runtime_endpoint_name].invoke_openai(
**kwargs
)
16 changes: 12 additions & 4 deletions agentrun/sandbox/api/__aio_data_async_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,13 @@ def sync_playwright(
from .playwright_sync import BrowserPlaywrightSync

cfg = Config.with_configs(self.config, config)
_, headers, _ = self.auth(headers=cfg.get_headers(), config=cfg)

url = self.get_cdp_url(record=record)
url, headers, _ = self.auth(
url=url, headers=cfg.get_headers(), config=cfg
)
return BrowserPlaywrightSync(
self.get_cdp_url(record=record),
url,
browser_type=browser_type,
headers=headers,
)
Expand All @@ -119,9 +123,13 @@ def async_playwright(
from .playwright_async import BrowserPlaywrightAsync

cfg = Config.with_configs(self.config, config)
_, headers, _ = self.auth(headers=cfg.get_headers(), config=cfg)

url = self.get_cdp_url(record=record)
url, headers, _ = self.auth(
url=url, headers=cfg.get_headers(), config=cfg
)
return BrowserPlaywrightAsync(
self.get_cdp_url(record=record),
url,
browser_type=browser_type,
headers=headers,
)
Expand Down
16 changes: 12 additions & 4 deletions agentrun/sandbox/api/__browser_data_async_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,13 @@ def sync_playwright(
from .playwright_sync import BrowserPlaywrightSync

cfg = Config.with_configs(self.config, config)
_, headers, _ = self.auth(headers=cfg.get_headers(), config=cfg)

url = self.get_cdp_url(record=record)
url, headers, _ = self.auth(
url=url, headers=cfg.get_headers(), config=cfg
)
return BrowserPlaywrightSync(
self.get_cdp_url(record=record),
url,
browser_type=browser_type,
headers=headers,
)
Expand All @@ -108,9 +112,13 @@ def async_playwright(
from .playwright_async import BrowserPlaywrightAsync

cfg = Config.with_configs(self.config, config)
_, headers, _ = self.auth(headers=cfg.get_headers(), config=cfg)

url = self.get_cdp_url(record=record)
url, headers, _ = self.auth(
url=url, headers=cfg.get_headers(), config=cfg
)
return BrowserPlaywrightAsync(
self.get_cdp_url(record=record),
url,
browser_type=browser_type,
headers=headers,
)
Expand Down
16 changes: 12 additions & 4 deletions agentrun/sandbox/api/aio_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,13 @@ def sync_playwright(
from .playwright_sync import BrowserPlaywrightSync

cfg = Config.with_configs(self.config, config)
_, headers, _ = self.auth(headers=cfg.get_headers(), config=cfg)

url = self.get_cdp_url(record=record)
url, headers, _ = self.auth(
url=url, headers=cfg.get_headers(), config=cfg
)
return BrowserPlaywrightSync(
self.get_cdp_url(record=record),
url,
browser_type=browser_type,
headers=headers,
)
Expand All @@ -129,9 +133,13 @@ def async_playwright(
from .playwright_async import BrowserPlaywrightAsync

cfg = Config.with_configs(self.config, config)
_, headers, _ = self.auth(headers=cfg.get_headers(), config=cfg)

url = self.get_cdp_url(record=record)
url, headers, _ = self.auth(
url=url, headers=cfg.get_headers(), config=cfg
)
return BrowserPlaywrightAsync(
self.get_cdp_url(record=record),
url,
browser_type=browser_type,
headers=headers,
)
Expand Down
16 changes: 12 additions & 4 deletions agentrun/sandbox/api/browser_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,13 @@ def sync_playwright(
from .playwright_sync import BrowserPlaywrightSync

cfg = Config.with_configs(self.config, config)
_, headers, _ = self.auth(headers=cfg.get_headers(), config=cfg)

url = self.get_cdp_url(record=record)
url, headers, _ = self.auth(
url=url, headers=cfg.get_headers(), config=cfg
)
return BrowserPlaywrightSync(
self.get_cdp_url(record=record),
url,
browser_type=browser_type,
headers=headers,
)
Expand All @@ -118,9 +122,13 @@ def async_playwright(
from .playwright_async import BrowserPlaywrightAsync

cfg = Config.with_configs(self.config, config)
_, headers, _ = self.auth(headers=cfg.get_headers(), config=cfg)

url = self.get_cdp_url(record=record)
url, headers, _ = self.auth(
url=url, headers=cfg.get_headers(), config=cfg
)
return BrowserPlaywrightAsync(
self.get_cdp_url(record=record),
url,
browser_type=browser_type,
headers=headers,
)
Expand Down
47 changes: 36 additions & 11 deletions agentrun/toolset/__toolset_async_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,17 @@ def _get_openapi_auth_defaults(
return headers, query

def _get_openapi_base_url(self) -> Optional[str]:
return pydash.get(
self,
"status.outputs.urls.intranet_url",
None,
) or pydash.get(self, "status.outputs.urls.internet_url", None)
import os

fc_region = os.getenv("FC_REGION")
if fc_region:
intranet_url: Optional[str] = pydash.get(
self, "status.outputs.urls.intranet_url", None
)
if intranet_url:
return intranet_url

return pydash.get(self, "status.outputs.urls.internet_url", None)

async def get_async(self, config: Optional[Config] = None):
if self.name is None:
Expand Down Expand Up @@ -154,6 +160,25 @@ async def call_tool_async(
logger.debug("invoke tool %s got result %s", name, result)
return result

def _get_mcp_url(self) -> str:
"""获取 MCP 工具的最佳 URL / Get the best URL for MCP tool

优先使用 agentrun-data 代理入口(支持 RAM 签名认证),
回退到 mcp_server_config.url(直连)。
Priority: agentrun-data proxy endpoint (with RAM auth) > mcp_server_config.url (direct).
"""
proxy_url = self._get_openapi_base_url()
if proxy_url:
return proxy_url

mcp_server_config: MCPServerConfig = pydash.get(
self, "status.outputs.mcp_server_config", None
)
if mcp_server_config and mcp_server_config.url:
return mcp_server_config.url

raise ValueError("MCP server URL is missing.")

def to_apiset(self, config: Optional[Config] = None):
"""将 ToolSet 转换为统一的 ApiSet 对象

Expand All @@ -168,16 +193,16 @@ def to_apiset(self, config: Optional[Config] = None):
mcp_server_config: MCPServerConfig = pydash.get(
self, "status.outputs.mcp_server_config", None
)
assert (
mcp_server_config.url is not None
), "MCP server URL is missing."

cfg = Config.with_configs(
config, Config(headers=mcp_server_config.headers)
mcp_url = self._get_mcp_url()

mcp_headers = (
mcp_server_config.headers if mcp_server_config else None
)
cfg = Config.with_configs(config, Config(headers=mcp_headers))

mcp_client = MCPToolSet(
url=mcp_server_config.url,
url=mcp_url,
config=cfg,
)

Expand Down
Loading
Loading