diff --git a/.github/workflows/cookbook.yml b/.github/workflows/cookbook.yml
index 3880796d6..181455c49 100644
--- a/.github/workflows/cookbook.yml
+++ b/.github/workflows/cookbook.yml
@@ -24,7 +24,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
- pip install -q -e ".[dev,langgraph,agno,a2a,autogen,aliyun_tablestore_ext,memory_ext]"
+ pip install -q -e ".[dev,ext]"
- name: Add execute permission to build.sh
run: |
chmod +x cookbook/build.sh
diff --git a/.github/workflows/integrated_test.yml b/.github/workflows/integrated_test.yml
index 4415a0666..2163e36e2 100644
--- a/.github/workflows/integrated_test.yml
+++ b/.github/workflows/integrated_test.yml
@@ -4,6 +4,7 @@ on:
push:
branches:
- 'main'
+ - 'dev'
jobs:
@@ -61,7 +62,7 @@ jobs:
- name: Install dependencies
run: |
export PIP_DEFAULT_TIMEOUT=300
- pip install -q -e ".[dev,langgraph,agno,autogen,langchain_rag,llamaindex_rag,aliyun_tablestore_ext,memory_ext]"
+ pip install -q -e ".[dev,ext]"
- name: Run integrated tests with coverage
env:
diff --git a/.github/workflows/unit_test.yml b/.github/workflows/unit_test.yml
index ddc7f3f5f..234b3c45a 100644
--- a/.github/workflows/unit_test.yml
+++ b/.github/workflows/unit_test.yml
@@ -4,9 +4,11 @@ on:
push:
branches:
- 'main'
+ - 'dev'
pull_request:
branches:
- 'main'
+ - 'dev'
jobs:
test:
@@ -48,7 +50,7 @@ jobs:
- name: Install dependencies
run: |
export PIP_DEFAULT_TIMEOUT=300
- pip install -q -e ".[dev,langchain_rag,llamaindex_rag,aliyun_tablestore_ext,memory_ext]"
+ pip install -q -e ".[dev,ext]"
- name: Run tests with coverage
run: |
diff --git a/.github/workflows/unit_test_deploy.yml b/.github/workflows/unit_test_deploy.yml
index 303981545..d6e50ab74 100644
--- a/.github/workflows/unit_test_deploy.yml
+++ b/.github/workflows/unit_test_deploy.yml
@@ -4,9 +4,11 @@ on:
push:
branches:
- 'main'
+ - 'dev'
pull_request:
branches:
- 'main'
+ - 'dev'
jobs:
test:
@@ -48,7 +50,7 @@ jobs:
- name: Install dependencies
run: |
export PIP_DEFAULT_TIMEOUT=300
- pip install -q -e ".[dev,langchain_rag,llamaindex_rag,aliyun_tablestore_ext,memory_ext,deployment]"
+ pip install -q -e ".[dev,ext]"
- name: Run tests with coverage
run: |
diff --git a/.github/workflows/unit_test_sandbox.yml b/.github/workflows/unit_test_sandbox.yml
index 199ef0037..637d34251 100644
--- a/.github/workflows/unit_test_sandbox.yml
+++ b/.github/workflows/unit_test_sandbox.yml
@@ -4,9 +4,11 @@ on:
push:
branches:
- 'main'
+ - 'dev'
pull_request:
branches:
- 'main'
+ - 'dev'
jobs:
test:
@@ -67,7 +69,7 @@ jobs:
- name: Run tests with coverage
run: |
- coverage run -m pytest tests/sandbox/test_sandbox.py tests/sandbox/test_tool.py
+ coverage run -m pytest tests/sandbox/test_sandbox.py tests/sandbox/test_sandbox_service.py
- name: Generate coverage report
run: |
diff --git a/.github/workflows/unit_test_tool.yml b/.github/workflows/unit_test_tool.yml
index e30fe4870..9c1e7e9c0 100644
--- a/.github/workflows/unit_test_tool.yml
+++ b/.github/workflows/unit_test_tool.yml
@@ -4,6 +4,11 @@ on:
push:
branches:
- 'main'
+ - 'dev'
+ pull_request:
+ branches:
+ - 'main'
+ - 'dev'
jobs:
test:
@@ -45,11 +50,11 @@ jobs:
- name: Install dependencies
run: |
export PIP_DEFAULT_TIMEOUT=300
- pip install -q -e ".[dev,tool]"
+ pip install -q -e ".[dev,ext]"
- name: Run tests with coverage
run: |
- coverage run -m pytest tests/unit
+ coverage run -m pytest tests/tools
- name: Generate coverage report
run: |
diff --git a/.github/workflows/unit_test_training_sandbox.yml b/.github/workflows/unit_test_training_sandbox.yml
index 21984111f..41c7cadd6 100644
--- a/.github/workflows/unit_test_training_sandbox.yml
+++ b/.github/workflows/unit_test_training_sandbox.yml
@@ -4,9 +4,11 @@ on:
push:
branches:
- 'main'
+ - 'dev'
pull_request:
branches:
- 'main'
+ - 'dev'
jobs:
test:
@@ -49,7 +51,6 @@ jobs:
- name: Pull Docker images
run: |
DOCKER_IMAGES=(
- "agentscope/runtime-sandbox-bfcl:latest"
"agentscope/runtime-sandbox-appworld:latest"
)
@@ -83,7 +84,7 @@ jobs:
- name: Run tests with coverage
run: |
- coverage run -m pytest tests/sandbox/test_sandbox_appworld.py tests/sandbox/test_sandbox_bfcl.py
+ coverage run -m pytest tests/sandbox/test_sandbox_appworld.py
- name: Generate coverage report
run: |
diff --git a/README.md b/README.md
index b7a1b51ee..1392283ca 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,9 @@
**A Production-Ready Runtime Framework for Intelligent Agent Applications**
-*AgentScope Runtime tackles two critical challenges in agent development: secure sandboxed tool execution and scalable agent deployment. Built with a dual-core architecture, it provides framework-agnostic infrastructure for deploying agents with full observability and safe tool interactions. In addition, the tools module offers a variety of out-of-the-box tools, which are adapted by the framework’s adapters for seamless compatibility with different native intelligent agent frameworks, ensuring developers can retain their original development experience.*
+***AgentScope Runtime** is a full-stack agent runtime that tackles two core challenges: **efficient agent deployment** and **secure sandbox execution**. It ships with foundational services such as short- and long-term memory plus agent state persistence, along with hardened sandbox infrastructure. Whether you need to orchestrate production-grade agents or guarantee safe tool interactions, AgentScope Runtime provides developer-friendly workflows with complete observability.*
+
+*In V1.0, these services are exposed via an **adapter pattern**, enabling seamless integration with the native modules of different agent frameworks while preserving their native interfaces and behaviors, ensuring both compatibility and flexibility.*
@@ -32,7 +34,7 @@
## 🆕 NEWS
-* **[2025-11]** We released **AgentScope Runtime V1.0**, which ensures the native development experience of agent frameworks, allowing them to fully leverage their expressive power. In this version, we further simplified certain abstractions and modules to streamline the architecture. For the complete list of changes, please refer to the changelog.
+* **[2025-12]** We have released **AgentScope Runtime v1.0**, introducing a unified “Agent as API” white-box development experience, with enhanced multi-agent collaboration, state persistence, and cross-framework integration. This release also streamlines abstractions and modules to ensure consistency between development and production environments. Please refer to the **[CHANGELOG](https://runtime.agentscope.io/en/CHANGELOG.html)** for full update details and migration guide.
---
@@ -85,6 +87,9 @@ From PyPI:
# Install core dependencies
pip install agentscope-runtime
+# Install extension
+pip install "agentscope-runtime[ext]"
+
# Install preview version
pip install --pre agentscope-runtime
```
diff --git a/README_zh.md b/README_zh.md
index cc82b81fd..bca53d29a 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -24,7 +24,9 @@
**智能体应用的生产就绪运行时框架**
-*AgentScope Runtime 解决了智能体开发中的两个关键挑战:安全的沙盒化工具执行和可扩展的智能体部署。其双核心架构为智能体提供了与框架无关的基础设施,支持在部署过程中实现完整的可观测性和安全的工具交互。此外,工具模块提供了丰富的开箱即用工具,并通过适配器适配到不同的原生智能体框架,从而确保兼容性,同时保留原有的开发体验。*
+***AgentScope Runtime** 是一个全面的智能体运行时框架,旨在解决两个关键挑战:**高效的智能体部署**和**沙箱执行**。它内置了基础服务(长短期记忆、智能体状态持久化)和安全沙箱基础设施。无论您需要大规模部署智能体还是确保安全的工具交互,AgentScope Runtime 都能提供具有完整可观测性和开发者友好部署的核心基础设施。*
+
+*在 V1.0 中,这些运行时服务通过 **适配器模式** 对外开放,允许开发者在保留原有智能体框架接口与行为的基础上,将 AgentScope 的状态管理、会话记录、工具调用等模块按需嵌入到应用生命周期中。从过去的 “黑盒化替换” 变为 “白盒化集成”,开发者可以显式地控制服务初始化、工具注册与状态持久化流程,从而在不同框架间实现无缝整合,同时获得更高的扩展性与灵活性。*
@@ -32,7 +34,7 @@
## 🆕 新闻
-* **[2025-11]** 我们发布了 **AgentScope Runtime V1.0**,该版本保证了 agent 框架的原生开发体验,从而能够最大程度发挥其表达能力。同时,我们对部分抽象及模块进行了进一步简化,以优化整体架构。完整更新内容请参考 changelog。
+* **[2025-12]** 我们发布了 **AgentScope Runtime v1.0**,该版本引入统一的 “Agent 作为 API” 白盒化开发体验,并全面强化多智能体协作、状态持久化与跨框架组合能力,同时对抽象与模块进行了简化优化,确保开发与生产环境一致性。完整更新内容与迁移说明请参考 **[CHANGELOG](https://runtime.agentscope.io/zh/CHANGELOG.html)**。
---
@@ -85,6 +87,9 @@
# 安装核心依赖
pip install agentscope-runtime
+# 安装拓展
+pip install "agentscope-runtime[ext]"
+
# 安装预览版本
pip install --pre agentscope-runtime
```
diff --git a/cookbook/en/advanced_deployment.md b/cookbook/en/advanced_deployment.md
index 227e3a33e..3d584af90 100644
--- a/cookbook/en/advanced_deployment.md
+++ b/cookbook/en/advanced_deployment.md
@@ -56,7 +56,7 @@ Install AgentScope Runtime with all deployment dependencies:
pip install agentscope-runtime>=1.0.0
# For Kubernetes deployment
-pip install "agentscope-runtime[deployment]>=1.0.0"
+pip install "agentscope-runtime[ext]>=1.0.0"
```
### 🔑 Environment Setup
diff --git a/cookbook/en/agent_app.md b/cookbook/en/agent_app.md
index de5801c3e..97706567c 100644
--- a/cookbook/en/agent_app.md
+++ b/cookbook/en/agent_app.md
@@ -14,13 +14,18 @@ kernelspec:
# Simple Deployment
-`AgentApp` is the all-in-one agent service wrapper in **AgentScope Runtime**. Any agent that matches its interface can be exposed as an API service supporting:
+`AgentApp` is the all-in-one application service wrapper in **AgentScope Runtime**.
+It provides the HTTP service framework for your agent logic and can expose it as an API with features such as:
-- Streaming responses (SSE)
-- Health-check endpoints
-- Lifecycle hooks (`before_start` / `after_finish`)
-- Celery asynchronous task queues
-- Deployments to local or remote targets
+- **Streaming responses (SSE)** for real-time output
+- Built-in **health-check** endpoints
+- **Lifecycle hooks** (`@app.init` / `@app.shutdown`) for startup and cleanup logic
+- Optional **Celery** asynchronous task queues
+- Deployment to local or remote targets
+
+**Important**:
+In the current version, `AgentApp` does not automatically include a `/process` endpoint.
+You must explicitly register a request handler using decorators (e.g., `@app.query(...)`) before your service can process incoming requests.
The sections below dive into each capability with concrete examples.
@@ -30,30 +35,31 @@ The sections below dive into each capability with concrete examples.
**What it does**
-Starts an HTTP API service that wraps your agent, listens on the configured port, and serves the primary handler (default `/process`).
+Creates a minimal `AgentApp` instance and starts a FastAPI-based HTTP service skeleton.
+In its initial state, the service only provides:
+
+- Welcome page `/`
+- Health check `/health`
+- Readiness probe `/readiness`
+- Liveness probe `/liveness`
+
+**Note**:
+
+- By default, no `/process` or other business endpoints are exposed.
+- You **must** register at least one handler using decorators such as `@app.query(...)` or `@app.task(...)` before the service can process requests.
+- Handlers can be regular or async functions, and may support streaming output via async generators.
**Example**
```{code-cell}
from agentscope_runtime.engine import AgentApp
-from agentscope_runtime.engine.agents.agentscope_agent import AgentScopeAgent
-from agentscope.model import OpenAIChatModel
-from agentscope.agent import ReActAgent
-# Build an Agent
-agent = AgentScopeAgent(
- name="Friday",
- model=OpenAIChatModel(
- "gpt-4",
- api_key="YOUR_OPENAI_KEY",
- ),
- agent_config={"sys_prompt": "You are a helpful assistant."},
- agent_builder=ReActAgent,
+agent_app = AgentApp(
+ app_name="Friday",
+ app_description="A helpful assistant",
)
-# Create and launch AgentApp
-app = AgentApp(agent=agent, endpoint_path="/process", response_type="sse", stream=True)
-app.run(host="0.0.0.0", port=8090)
+agent_app.run(host="127.0.0.1", port=8090)
```
------
@@ -122,7 +128,11 @@ app = AgentApp(
### Method 2: Use Decorators (Recommended)
-Decorators are more flexible and keep the logic close to the app definition:
+In addition to passing hook functions via constructor parameters, you can also register lifecycle hooks using decorators.
+This approach has the following advantages:
+
+1. **More flexible and intuitive** — The lifecycle logic is placed directly alongside the application definition, making the structure clearer and code more readable.
+2. **Shared member variables** — Functions defined with decorators receive `self`, allowing access to the attributes and services of the `AgentApp` instance (for example, state services or session services started in `@app.init`), enabling convenient sharing and reuse of resources across different lifecycle stages or request handlers.
```{code-cell}
from agentscope_runtime.engine import AgentApp
@@ -429,7 +439,7 @@ async def query_func(
app.run(host="0.0.0.0", port=8090)
```
-### Comparison with the `agent` Parameter Approach
+### Comparison with the V0 version`agent` Parameter Approach
| Feature | Pre-built `agent` Parameter | Custom `@app.query` |
|---------|----------------------------|---------------------|
@@ -440,6 +450,52 @@ app.run(host="0.0.0.0", port=8090)
------
+## Custom Endpoints via `@app.endpoint`
+
+In addition to using `@app.query(...)` for the unified `/process` entry point, `AgentApp` also supports registering arbitrary HTTP endpoints via the `@app.endpoint(...)` decorator.
+
+**Key Features**:
+
+1. **High flexibility** — Define dedicated API paths for different business needs, rather than routing all traffic through `/process`.
+
+2. Multiple return modes— Supports:
+
+ - Regular sync/async functions returning JSON
+ - Generators (sync or async) returning **streaming data** over SSE
+
+3. Automatic parameter parsing— Endpoints can accept:
+
+ - URL query parameters
+ - JSON bodies mapped to Pydantic models
+ - `fastapi.Request` objects
+ - `AgentRequest` objects (convenient for accessing unified session/user info)
+
+4. **Error handling** — Exceptions raised in streaming generators are automatically wrapped into SSE error events and sent to the client.
+
+**Example**:
+
+```python
+app = AgentApp()
+
+@app.endpoint("/hello")
+def hello_endpoint():
+ return {"msg": "Hello world"}
+
+@app.endpoint("/stream_numbers")
+async def stream_numbers():
+ for i in range(5):
+ yield f"number: {i}\n"
+```
+
+Client calls:
+
+```bash
+curl -X POST http://localhost:8090/hello
+curl -X POST http://localhost:8090/stream_numbers
+```
+
+---
+
## Deploy Locally or Remotely
Use the unified `deploy()` method to ship the same app to different environments:
diff --git a/cookbook/en/install.md b/cookbook/en/install.md
index 60ea78766..74924849f 100644
--- a/cookbook/en/install.md
+++ b/cookbook/en/install.md
@@ -26,6 +26,9 @@ To install the stable release of Agentscope Runtime via PyPI, use:
```bash
pip install agentscope-runtime
+
+# For additional extensions, install with extras:
+pip install "agentscope-runtime[ext]"
```
### (Optional) Install preview version (Beta/RC)
@@ -75,8 +78,9 @@ You should see the version number printed out.
The core runtime (`agentscope-runtime`) includes AgentScope Framework and Sandbox dependencies. See details about all installation options at [pyproject.toml](https://github.com/agentscope-ai/agentscope-runtime/blob/main/pyproject.toml).
-| **Component** | **Package** | **Use-Case** | **Dependencies** |
-| --------------------- | -------------------- | ------------- | ------------------------------------------------------------ |
-| Core Runtime | `agentscope-runtime` | Core runtime | Minimal including AgentScope Framework and Sandbox Dependencies |
-| Development Tools | `dev` | Dev utilities | Testing, Linting, Docs |
+| **Component** | **Package** | **Use-Case** | **Dependencies** |
+| ----------------- | -------------------- | ------------- | ------------------------------------------------------------ |
+| Core Runtime | `agentscope-runtime` | Core runtime | Minimal including AgentScope Framework and Sandbox Dependencies |
+| Development Tools | `dev` | Dev utilities | Testing, Linting, Docs |
+| Extention | `ext` | Deployment | REME AI, Mem0, Alibaba Cloud services, TableStore, LangChain, Azure Speech, OSS, Authentication, Build tools |
diff --git a/cookbook/en/service.md b/cookbook/en/service.md
index fa0849acb..2db3404c9 100644
--- a/cookbook/en/service.md
+++ b/cookbook/en/service.md
@@ -221,7 +221,7 @@ is_healthy = await sandbox_service.health()
await sandbox_service.stop()
```
-See {doc}`sandbox` for details.
+See {doc}`sandbox/sandbox` for details.
### StateService
diff --git a/cookbook/zh/advanced_deployment.md b/cookbook/zh/advanced_deployment.md
index 39d280227..f6e7f82e0 100644
--- a/cookbook/zh/advanced_deployment.md
+++ b/cookbook/zh/advanced_deployment.md
@@ -57,7 +57,7 @@ await app.deploy(
pip install agentscope-runtime>=1.0.0
# Kubernetes部署依赖
-pip install "agentscope-runtime[deployment]>=1.0.0"
+pip install "agentscope-runtime[ext]>=1.0.0"
```
diff --git a/cookbook/zh/agent_app.md b/cookbook/zh/agent_app.md
index dd1c24ef6..65d9d8134 100644
--- a/cookbook/zh/agent_app.md
+++ b/cookbook/zh/agent_app.md
@@ -14,46 +14,52 @@ kernelspec:
# 简单部署
-`AgentApp` 是 **AgentScope Runtime** 中的完整 Agent 服务封装器。
-它可以将任何符合接口的 Agent 变成一个 API 服务,支持:
+`AgentApp` 是 **AgentScope Runtime** 中的全能型应用服务封装器。
+它为你的 agent 逻辑提供 HTTP 服务框架,并可将其作为 API 暴露,支持以下功能:
-- 流式输出(SSE)
-- 健康检查接口
-- 生命周期钩子(`before_start` / `after_finish`)
-- Celery 异步任务队列
-- 部署到本地或远程
+- **流式响应(SSE)**,实现实时输出
+- 内置 **健康检查** 接口
+- **生命周期钩子**(`@app.init` / `@app.shutdown`),用于启动与清理逻辑
+- 可选的 **Celery** 异步任务队列
+- 部署到本地或远程目标
-下面对每个功能做深入介绍,并提供用法示例。
+**重要说明**:
+在当前版本中,`AgentApp` 不会自动包含 `/process` 端点。
+你必须显式地使用装饰器(例如 `@app.query(...)`)注册一个请求处理函数,服务才能处理传入的请求。
+
+下面的章节将通过具体示例深入介绍每项功能。
------
## 初始化与基本运行
**功能**
-启动一个包含 Agent 的 HTTP API 服务,监听指定端口,提供主处理接口(默认 `/process`)。
+
+创建一个最小的 `AgentApp` 实例,并启动基于 FastAPI 的 HTTP 服务骨架。
+初始状态下,服务只提供:
+
+- 欢迎页 `/`
+- 健康检查 `/health`
+- 就绪探针 `/readiness`
+- 存活探针 `/liveness`
+
+**注意**:
+
+- 默认不会暴露 `/process` 或其它业务处理端点。
+- 必须使用如 `@app.query(...)` 装饰器、`@app.task(...)` 等方法注册至少一个 handler,才能对外提供处理请求的 API。
+- 处理函数可以是普通函数或 async 函数,也可以支持流式(async generator)输出。
**用法示例**
```{code-cell}
from agentscope_runtime.engine import AgentApp
-from agentscope_runtime.engine.agents.agentscope_agent import AgentScopeAgent
-from agentscope.model import OpenAIChatModel
-from agentscope.agent import ReActAgent
-# 创建 Agent
-agent = AgentScopeAgent(
- name="Friday",
- model=OpenAIChatModel(
- "gpt-4",
- api_key="YOUR_OPENAI_KEY",
- ),
- agent_config={"sys_prompt": "You are a helpful assistant."},
- agent_builder=ReActAgent,
+agent_app = AgentApp(
+ app_name="Friday",
+ app_description="A helpful assistant",
)
-# 创建并运行 AgentApp
-app = AgentApp(agent=agent, endpoint_path="/process", response_type="sse", stream=True)
-app.run(host="0.0.0.0", port=8090)
+agent_app.run(host="127.0.0.1", port=8090)
```
------
@@ -123,9 +129,11 @@ app = AgentApp(
### 方式2:使用装饰器(推荐)
-除了使用参数传递,还可以使用装饰器方式注册生命周期钩子,这种方式更加灵活和直观:
+除了通过构造函数参数传递钩子函数外,还可以使用装饰器的方式来注册生命周期钩子。
+这种写法有以下优点:
-**用法示例**
+1. **更灵活直观** —— 生命周期逻辑直接贴近应用定义,结构更清晰,可读性更高;
+2. **可共享成员变量** —— 装饰器定义的函数会接收 `self`,可以访问 `AgentApp` 实例的属性和服务(例如 `@app.init` 中启动的状态服务、会话服务等),方便在不同生命周期或请求处理逻辑中共享和复用资源;
```{code-cell}
from agentscope_runtime.engine import AgentApp
@@ -439,7 +447,7 @@ async def query_func(
app.run(host="0.0.0.0", port=8090)
```
-### 与标准 Agent 参数方式的区别
+### 与 V0 版本 Agent 参数方式的区别
| 特性 | 标准方式(agent 参数) | 自定义查询(@app.query) |
|------|----------------------|------------------------|
@@ -449,6 +457,47 @@ app.run(host="0.0.0.0", port=8090)
| 多框架支持 | 有限 | 支持多种框架 |
------
+## 通过 `@app.endpoint` 自定义接口
+
+`AgentApp` 除了可以用 `@app.query(...)` 定义统一的 `/process` 请求入口外,还支持通过 `@app.endpoint(...)` 装饰器为应用注册任意路径的 HTTP 接口。
+
+**主要特点**:
+
+1. **灵活性高** —— 你可以为不同业务定义专门的 API 路径,而不是都走 `/process`;
+2. 多种返回模式—— 支持
+ - 普通同步/异步函数返回 JSON 对象
+ - 生成器(同步或异步)返回 **流式数据**(SSE)
+3. 参数解析——`@app.endpoint`装饰的函数可以自动解析
+ - URL 查询参数
+ - JSON 请求体(自动映射到 Pydantic 模型)
+ - `fastapi.Request` 对象
+ - `AgentRequest` 对象(方便统一 session、用户信息等)
+4. **异常处理** —— 流式生成器抛出的异常会自动封装到 SSE 错误事件中返回给客户端。
+
+**示例**:
+
+```python
+app = AgentApp()
+
+@app.endpoint("/hello")
+def hello_endpoint():
+ return {"msg": "Hello world"}
+
+@app.endpoint("/stream_numbers")
+async def stream_numbers():
+ for i in range(5):
+ yield f"number: {i}\n"
+```
+
+调用:
+
+```bash
+curl -X POST http://localhost:8090/hello
+curl -X POST http://localhost:8090/stream_numbers
+```
+
+---
+
## 部署到本地或远程
**功能**
diff --git a/cookbook/zh/install.md b/cookbook/zh/install.md
index 10ec44d2e..98c3942f9 100644
--- a/cookbook/zh/install.md
+++ b/cookbook/zh/install.md
@@ -24,6 +24,9 @@ kernelspec:
```bash
pip install agentscope-runtime
+
+# 若需额外扩展,请使用 extras 安装:
+pip install "agentscope-runtime[ext]"
```
### (可选)安装预览版本(Beta/RC)
@@ -73,7 +76,8 @@ print(f"AgentScope Runtime {agentscope_runtime.__version__} is ready!")
核心运行时(`agentscope-runtime`)包含 AgentScope 框架和 Sandbox 依赖。查看所有安装选项的详细信息,请参见 [pyproject.toml](https://github.com/agentscope-ai/agentscope-runtime/blob/main/pyproject.toml)。
-| **组件** | **软件包** | **用途** | **依赖项** |
-| -------------- | -------------------- | ------------ | ---------------------------------------------- |
-| 核心运行时 | `agentscope-runtime` | 核心运行环境 | 最小依赖,包括 AgentScope 框架 和 Sandbox 依赖 |
-| 开发工具 | `dev` | 开发工具集 | 测试、代码检查(Linting)、文档 |
+| **组件** | **软件包** | **用途** | **依赖项** |
+| ---------- | -------------------- | ------------ | ------------------------------------------------------------ |
+| 核心运行时 | `agentscope-runtime` | 核心运行环境 | 最小依赖,包括 AgentScope 框架 和 Sandbox 依赖 |
+| 开发工具 | `dev` | 开发工具集 | 测试、代码检查(Linting)、文档 |
+| Extension | `ext` | 部署扩展 | REME AI、Mem0、阿里云服务、表格存储、LangChain、Azure 语音、对象存储、身份认证、构建工具 |
diff --git a/cookbook/zh/service.md b/cookbook/zh/service.md
index 079c1c1aa..89cdc79d1 100644
--- a/cookbook/zh/service.md
+++ b/cookbook/zh/service.md
@@ -220,7 +220,7 @@ is_healthy = await sandbox_service.health()
await sandbox_service.stop()
```
-详细信息请参见 {doc}`sandbox` 。
+详细信息请参见 {doc}`sandbox/sandbox` 。
### StateService
diff --git a/examples/agentbay_sandbox/README.md b/examples/agentbay_sandbox/README.md
index 6d84411fb..a4b46973e 100644
--- a/examples/agentbay_sandbox/README.md
+++ b/examples/agentbay_sandbox/README.md
@@ -1,92 +1,104 @@
-# AgentBay SDK 集成进 Agentscope-Runtime 调研方案
+# AgentBay SDK Integration into Agentscope-Runtime – Research Proposal
-## AgentBay 是什么:
+## What is AgentBay?
-AgentBay 是一个阿里云上的 GUI 沙箱环境。
-AgentBay 能够提供 Code Space、Browser Use、Computer Use、Mobile Use 四种沙箱环境。提供 MCP Server 和 AgentBay SDK 的方式接入,目前 AgentBay SDK 已开源。
-AgentBay SDK 开源地址: [AgentBay SDK 开源地址](https://github.com/aliyun/wuying-agentbay-sdk)
-AgentBay 云产品地址: [AgentBay 云产品地址](https://www.aliyun.com/product/agentbay)
+AgentBay is a GUI sandbox environment provided by Alibaba Cloud.
+It offers four types of sandbox environments: **Code Space**, **Browser Use**, **Computer Use**, and **Mobile Use**.
-## AgentBay 能力
+AgentBay can be integrated via **MCP Server** or **AgentBay SDK**. The SDK is open source.
-- **新增沙箱类型**: Code Space、Browser Use、Computer Use、Mobile Use
-- **接入方式**: MCP Server 和 AgentBay SDK;
+- **AgentBay SDK GitHub Repository**: https://github.com/aliyun/wuying-agentbay-sdk
+- **AgentBay Cloud Product Page**: https://www.aliyun.com/product/agentbay
-### 镜像类型支持
+## AgentBay Capabilities
-- `linux_latest` - Linux 环境
-- `windows_latest` - Windows 环境
-- `browser_latest` - 浏览器自动化环境
-- `code_latest` - 代码执行环境
-- `mobile_latest` - 移动端环境
+- **New Sandbox Types**: Code Space, Browser Use, Computer Use, Mobile Use
+- **Integration Methods**: MCP Server and AgentBay SDK
-### 支持的工具操作
+### Supported Image Types
-- **基础操作**:`run_shell_command`, `run_ipython_cell`, `screenshot`
-- **文件操作**:`read_file`, `write_file`, `list_directory`, `create_directory`, `move_file`, `delete_file`
-- **浏览器操作**:`browser_navigate`, `browser_click`, `browser_input` (browser_latest 镜像)
+- `linux_latest` – Linux environment
+- `windows_latest` – Windows environment
+- `browser_latest` – Browser automation environment
+- `code_latest` – Code execution environment
+- `mobile_latest` – Mobile device environment
-## AgentBay 集成进 Agentscope-Runtime:
+### Supported Tool Operations
-目前,Agentscope-Runtime 的沙箱容器基于 docker 实现,云上容器基于 k8s 实现;AgentBay 集成进 AgentScope-Runtime,能够给使用 Agentscope-Runtime 提供另外一种云上沙箱环境的选择,可以使用除了 docker 容器沙箱之外,也可以选择使用 AgentBay 的 GUI 沙箱;
+- **Basic Operations**: `run_shell_command`, `run_ipython_cell`, `screenshot`
+- **File Operations**: `read_file`, `write_file`, `list_directory`, `create_directory`, `move_file`, `delete_file`
+- **Browser Operations** *(browser_latest image)*: `browser_navigate`, `browser_click`, `browser_input`
-### 核心思路:
+## Integrating AgentBay into Agentscope-Runtime
-AgentBay 这个云产品是对标国外 e2b、daytona 等云沙箱产品做的,使用 api_key 就开箱即用,无需部署;
-核心思路是把 AgentBay 封装成 AgentBay Sandbox 集成进 AgentScope-Runtime,作为另外一种云沙箱的选择,其实 e2b 也可以复用这套逻辑;
-由于 AgentBay Sandbox 并不依赖容器,所以创建 CloudSandbox 基类继承 Sandbox 类,这样就使得 Agentscope-Runtime 能够同时支持传统容器沙箱和云原生沙箱,在使用上与传统容器沙箱尽量保持一致;
+Currently, the sandbox containers for Agentscope-Runtime are implemented based on Docker, and the cloud containers are managed via Kubernetes.
-### 1. 核心架构集成
+Integrating AgentBay into Agentscope-Runtime allows users to choose **AgentBay’s GUI cloud sandbox** in addition to Docker-based sandboxes.
-- **新增沙箱类型**: `SandboxType.AGENTBAY` 枚举,用于创建 Agentbay Sandbox,支持动态枚举扩展;
-- **CloudSandbox 基类**: 抽象基类,为云服务沙箱提供统一接口,不依赖容器管理,直接通过云 API 通信,可以支持不同云提供商扩展;
-- **AgentbaySandbox 实现**: 继承自 CloudSandbox,直接通过 AgentBay API 访问云端沙箱,实现完整的工具映射和错误处理;
-- **SandboxService 支持**: 保持与原有 sandbox_service 调用方式的兼容性,特殊处理 AgentBay 沙箱类型,支持会话管理和资源清理;
+### Key Idea
-### 2. 类层次结构
+AgentBay is similar to cloud sandbox products like **e2b** or **Daytona**, offering **API-key based access without deployment**.
+
+We can wrap AgentBay as an **AgentBaySandbox** inside Agentscope-Runtime, serving as another cloud sandbox option.
+The same logic could be reused for e2b integration.
+
+Since the AgentBay sandbox does not depend on local containers, we introduce a `CloudSandbox` base class (inheriting from `Sandbox`), allowing Agentscope-Runtime to support both container-based and cloud-native sandboxes, with consistent usage patterns.
+
+------
+
+### 1. Core Architecture Integration
+
+- **Add Sandbox Type**: `SandboxType.AGENTBAY` enum for creating AgentBay sandboxes, supporting dynamic extension.
+- **CloudSandbox Base Class**: Abstract base class for cloud-based sandboxes, using cloud APIs instead of container management. Extensible for other cloud providers.
+- **AgentbaySandbox Implementation**: Inherits from `CloudSandbox`, uses AgentBay API to access the cloud sandbox, implementing full tool mapping and error handling.
+- **SandboxService Support**: Maintains compatibility with existing `sandbox_service` calls, includes special handling for AgentBay sandbox type, supports session management and resource cleanup.
+
+### 2. Class Hierarchy
```
-Sandbox (基类)
-└── CloudSandbox (云沙箱基类)
- └── AgentbaySandbox (AgentBay 实现)
+Sandbox (base class)
+└── CloudSandbox (cloud sandbox base class)
+ └── AgentbaySandbox (AgentBay implementation)
```
-### 3. 文件结构
+### 3. File Structure
```
src/agentscope_runtime/sandbox/
-├── enums.py # 新增 AGENTBAY 枚举
+├── enums.py # Add AGENTBAY enum
├── box/
│ ├── cloud/
-│ │ ├── __init__.py # 新增
-│ │ └── cloud_sandbox.py # 新增 CloudSandbox 基类
+│ │ ├── __init__.py # New
+│ │ └── cloud_sandbox.py # New CloudSandbox base class
│ └── agentbay/
-│ ├── __init__.py # 新增
-│ └── agentbay_sandbox.py # 新增 AgentbaySandbox 实现
-└── __init__.py # 更新导出
+│ ├── __init__.py # New
+│ └── agentbay_sandbox.py # New AgentbaySandbox implementation
+└── __init__.py # Update exports
```
-### 4. 服务层集成
+------
-- **注册机制**:使用 `@SandboxRegistry.register` 装饰器注册
-- **服务集成**:在 `SandboxService` 中特殊处理 AgentBay 类型
-- **兼容性**:保持与现有沙箱接口的完全兼容
-- **生命周期管理**: 支持创建、连接、释放 AgentBay 会话
+### 4. Service Layer Integration
-## AgentBay Sandbox 如何使用
+- **Registration Mechanism**: Use `@SandboxRegistry.register` decorator for sandbox registration.
+- **Service Integration**: Add special handling for AgentBay in `SandboxService`.
+- **Compatibility**: Ensure full compatibility with existing sandbox APIs.
+- **Lifecycle Management**: Support creation, connection, and cleanup of AgentBay sessions.
-### 0. 设置环境变量
+## Using AgentBay Sandbox
+
+### 0. Set Environment Variables
```bash
-pip install wuying-agentbay-sdk
+pip install "agentscope-runtime[ext]"
export AGENTBAY_API_KEY='your_agentbay_api_key'
-export DASHSCOPE_API_KEY='your_dashscope_api_key' # 可选
+export DASHSCOPE_API_KEY='your_dashscope_api_key' # optional
```
-### 1. 直接使用
+### 1. Direct Usage
```python
-from agentscope_runtime.sandbox.box.agentbay.agentbay_sandbox import AgentbaySandbox
+from agentscope_runtime.sandbox import AgentbaySandbox
sandbox = AgentbaySandbox(
api_key="your_api_key",
@@ -96,27 +108,26 @@ sandbox = AgentbaySandbox(
result = sandbox.call_tool("run_shell_command", {"command": "echo 'Hello'"})
```
-### 2. 通过 SandboxService
+### 2. Using SandboxService
```python
from agentscope_runtime.sandbox.enums import SandboxType
-from agentscope_runtime.engine.services.sandbox_service import SandboxService
+from agentscope_runtime.engine.services.sandbox import SandboxService
sandbox_service = SandboxService(bearer_token="your_api_key")
sandboxes = sandbox_service.connect(
session_id="session1",
user_id="user1",
- types=[SandboxType.AGENTBAY.value]
+ sandbox_types=[SandboxType.AGENTBAY]
)
```
-## 运行演示 demo
+## Demo Execution
```bash
-# agentbay 沙箱演示
+# AgentBay sandbox demo
python examples/agentbay_sandbox/agentbay_sandbox_demo.py
-# 模型调用sandbox 演示
+# Model calls using AgentBay sandbox demo
python examples/agentbay_sandbox/agentscope_use_agentbay_sandbox.py
-
```
diff --git a/examples/agentbay_sandbox/README_zh.md b/examples/agentbay_sandbox/README_zh.md
new file mode 100644
index 000000000..6228213a4
--- /dev/null
+++ b/examples/agentbay_sandbox/README_zh.md
@@ -0,0 +1,122 @@
+# AgentBay SDK 集成进 Agentscope-Runtime 调研方案
+
+## AgentBay 是什么:
+
+AgentBay 是一个阿里云上的 GUI 沙箱环境。
+AgentBay 能够提供 Code Space、Browser Use、Computer Use、Mobile Use 四种沙箱环境。提供 MCP Server 和 AgentBay SDK 的方式接入,目前 AgentBay SDK 已开源。
+AgentBay SDK 开源地址: [AgentBay SDK 开源地址](https://github.com/aliyun/wuying-agentbay-sdk)
+AgentBay 云产品地址: [AgentBay 云产品地址](https://www.aliyun.com/product/agentbay)
+
+## AgentBay 能力
+
+- **新增沙箱类型**: Code Space、Browser Use、Computer Use、Mobile Use
+- **接入方式**: MCP Server 和 AgentBay SDK;
+
+### 镜像类型支持
+
+- `linux_latest` - Linux 环境
+- `windows_latest` - Windows 环境
+- `browser_latest` - 浏览器自动化环境
+- `code_latest` - 代码执行环境
+- `mobile_latest` - 移动端环境
+
+### 支持的工具操作
+
+- **基础操作**:`run_shell_command`, `run_ipython_cell`, `screenshot`
+- **文件操作**:`read_file`, `write_file`, `list_directory`, `create_directory`, `move_file`, `delete_file`
+- **浏览器操作**:`browser_navigate`, `browser_click`, `browser_input` (browser_latest 镜像)
+
+## AgentBay 集成进 Agentscope-Runtime:
+
+目前,Agentscope-Runtime 的沙箱容器基于 docker 实现,云上容器基于 k8s 实现;AgentBay 集成进 AgentScope-Runtime,能够给使用 Agentscope-Runtime 提供另外一种云上沙箱环境的选择,可以使用除了 docker 容器沙箱之外,也可以选择使用 AgentBay 的 GUI 沙箱;
+
+### 核心思路:
+
+AgentBay 这个云产品是对标国外 e2b、daytona 等云沙箱产品做的,使用 api_key 就开箱即用,无需部署;
+核心思路是把 AgentBay 封装成 AgentBay Sandbox 集成进 AgentScope-Runtime,作为另外一种云沙箱的选择,其实 e2b 也可以复用这套逻辑;
+由于 AgentBay Sandbox 并不依赖容器,所以创建 CloudSandbox 基类继承 Sandbox 类,这样就使得 Agentscope-Runtime 能够同时支持传统容器沙箱和云原生沙箱,在使用上与传统容器沙箱尽量保持一致;
+
+### 1. 核心架构集成
+
+- **新增沙箱类型**: `SandboxType.AGENTBAY` 枚举,用于创建 Agentbay Sandbox,支持动态枚举扩展;
+- **CloudSandbox 基类**: 抽象基类,为云服务沙箱提供统一接口,不依赖容器管理,直接通过云 API 通信,可以支持不同云提供商扩展;
+- **AgentbaySandbox 实现**: 继承自 CloudSandbox,直接通过 AgentBay API 访问云端沙箱,实现完整的工具映射和错误处理;
+- **SandboxService 支持**: 保持与原有 sandbox_service 调用方式的兼容性,特殊处理 AgentBay 沙箱类型,支持会话管理和资源清理;
+
+### 2. 类层次结构
+
+```
+Sandbox (基类)
+└── CloudSandbox (云沙箱基类)
+ └── AgentbaySandbox (AgentBay 实现)
+```
+
+### 3. 文件结构
+
+```
+src/agentscope_runtime/sandbox/
+├── enums.py # 新增 AGENTBAY 枚举
+├── box/
+│ ├── cloud/
+│ │ ├── __init__.py # 新增
+│ │ └── cloud_sandbox.py # 新增 CloudSandbox 基类
+│ └── agentbay/
+│ ├── __init__.py # 新增
+│ └── agentbay_sandbox.py # 新增 AgentbaySandbox 实现
+└── __init__.py # 更新导出
+```
+
+### 4. 服务层集成
+
+- **注册机制**:使用 `@SandboxRegistry.register` 装饰器注册
+- **服务集成**:在 `SandboxService` 中特殊处理 AgentBay 类型
+- **兼容性**:保持与现有沙箱接口的完全兼容
+- **生命周期管理**: 支持创建、连接、释放 AgentBay 会话
+
+## AgentBay Sandbox 如何使用
+
+### 0. 设置环境变量
+
+```bash
+pip install "agentscope-runtime[ext]"
+export AGENTBAY_API_KEY='your_agentbay_api_key'
+export DASHSCOPE_API_KEY='your_dashscope_api_key' # 可选
+```
+
+### 1. 直接使用
+
+```python
+from agentscope_runtime.sandbox import AgentbaySandbox
+
+sandbox = AgentbaySandbox(
+ api_key="your_api_key",
+ image_id="linux_latest"
+)
+
+result = sandbox.call_tool("run_shell_command", {"command": "echo 'Hello'"})
+```
+
+### 2. 通过 SandboxService
+
+```python
+from agentscope_runtime.sandbox.enums import SandboxType
+from agentscope_runtime.engine.services.sandbox import SandboxService
+
+sandbox_service = SandboxService(bearer_token="your_api_key")
+sandboxes = sandbox_service.connect(
+ session_id="session1",
+ user_id="user1",
+ sandbox_types=[SandboxType.AGENTBAY]
+)
+```
+
+## 运行演示 demo
+
+```bash
+# agentbay 沙箱演示
+python examples/agentbay_sandbox/agentbay_sandbox_demo.py
+
+# 模型调用sandbox 演示
+python examples/agentbay_sandbox/agentscope_use_agentbay_sandbox.py
+
+```
diff --git a/examples/deployments/agentrun_deploy/README.md b/examples/deployments/agentrun_deploy/README.md
index 004f62cbb..3274a7b47 100644
--- a/examples/deployments/agentrun_deploy/README.md
+++ b/examples/deployments/agentrun_deploy/README.md
@@ -24,7 +24,7 @@ Before running this example, ensure you have:
1. **Install dependencies**:
```bash
- pip install "agentscope-runtime[deployment]>=1.0.0"
+ pip install "agentscope-runtime[ext]>=1.0.0"
```
2. **Set environment variables**:
diff --git a/examples/deployments/k8s_deploy/README.md b/examples/deployments/k8s_deploy/README.md
index 5d29e3810..ff8b952ac 100644
--- a/examples/deployments/k8s_deploy/README.md
+++ b/examples/deployments/k8s_deploy/README.md
@@ -25,7 +25,7 @@ Before running this example, ensure you have:
1. **Install dependencies**:
```bash
- pip install "agentscope-runtime[deployment]>=1.0.0"
+ pip install "agentscope-runtime[ext]>=1.0.0"
```
diff --git a/examples/deployments/modelstudio_deploy/README.md b/examples/deployments/modelstudio_deploy/README.md
index bf0335cbc..ec77e9fdf 100644
--- a/examples/deployments/modelstudio_deploy/README.md
+++ b/examples/deployments/modelstudio_deploy/README.md
@@ -25,7 +25,7 @@ Before running this example, ensure you have:
1. **Install dependencies**:
```bash
- pip install "agentscope-runtime[deployment]>=1.0.0"
+ pip install "agentscope-runtime[ext]>=1.0.0"
```
2. **Set environment variables**:
diff --git a/pyproject.toml b/pyproject.toml
index e01ec1684..2d2bde170 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -21,6 +21,9 @@ dependencies = [
"shortuuid>=1.0.13",
"celery[redis]>=5.3.1",
"a2a-sdk>=0.3.0",
+ "jinja2",
+ "psutil",
+ "dashscope>=1.25.0",
]
[tool.setuptools]
@@ -55,46 +58,25 @@ dev = [
"sphinxcontrib-mermaid>=1.2.3",
]
-agentrun = [
+ext = [
+ "reme-ai>=0.2.0.2",
+ "mem0ai>=0.1.117",
"alibabacloud-agentrun20250910>=2.0.1",
- "alibabacloud_tea_openapi>=0.4.0"
-]
-
-aliyun_tablestore_ext=[
+ "alibabacloud_tea_openapi>=0.4.0",
"tablestore-for-agent-memory>=1.1.0",
- "dashscope>=1.24.4",
"langchain-community>=0.3.27",
-]
-
-memory-ext = [
- "reme-ai>=0.2.0.2",
- "mem0ai>=0.1.117"
-]
-
-
-deployment = [
- "alibabacloud-agentrun20250910>=2.0.1",
- "alibabacloud-oss-v2",
- "alibabacloud-bailian20231229>=2.6.0",
- "build",
- "setuptools>=40.8.0",
- "wheel",
- "steel-sdk>=0.1.0",
- "alibabacloud-credentials",
- "jinja2",
- "psutil",
- "shortuuid>=1.0.13",
- "PyYAML",
- "oss2>=2.19.1",
"wuying-agentbay-sdk>=0.5.0",
-]
-
-tool = [
- "dashscope>=1.25.0",
"alipay-sdk-python",
"cryptography",
"gunicorn>=20.0.0",
"starlette>=0.37.0",
"asgiref>=3.11.0",
"azure-cognitiveservices-speech>=1.47.0",
-]
+ "alibabacloud-oss-v2",
+ "alibabacloud-bailian20231229>=2.6.0",
+ "build",
+ "setuptools>=40.8.0",
+ "wheel",
+ "alibabacloud-credentials",
+ "PyYAML",
+]
\ No newline at end of file
diff --git a/src/agentscope_runtime/common/utils/lazy_loader.py b/src/agentscope_runtime/common/utils/lazy_loader.py
index 9d5acbc67..b8d086686 100644
--- a/src/agentscope_runtime/common/utils/lazy_loader.py
+++ b/src/agentscope_runtime/common/utils/lazy_loader.py
@@ -36,6 +36,11 @@ def __getattr__(name):
msg = f"Failed to import {name}. Possible missing dependency."
if hint:
msg += f" Please install dependency: {hint}"
+ else:
+ msg += (
+ " Please install dependency: pip install "
+ "agentscope-runtime[ext]"
+ )
raise ImportError(msg) from e
obj = getattr(module, name)
diff --git a/src/agentscope_runtime/engine/services/memory/__init__.py b/src/agentscope_runtime/engine/services/memory/__init__.py
index a8258ea62..ff8747107 100644
--- a/src/agentscope_runtime/engine/services/memory/__init__.py
+++ b/src/agentscope_runtime/engine/services/memory/__init__.py
@@ -16,21 +16,9 @@
"MemoryService": ".memory_service",
"InMemoryMemoryService": ".memory_service",
"RedisMemoryService": ".redis_memory_service",
- "ReMeTaskMemoryService": {
- "module": ".reme_task_memory_service",
- "hint": "pip install agentscope-runtime[memory-ext]",
- },
- "ReMePersonalMemoryService": {
- "module": ".reme_personal_memory_service",
- "hint": "pip install agentscope-runtime[memory-ext]",
- },
- "Mem0MemoryService": {
- "module": ".mem0_memory_service",
- "hint": "pip install agentscope-runtime[memory-ext]",
- },
- "TablestoreMemoryService": {
- "module": ".tablestore_memory_service",
- "hint": "pip install agentscope-runtime[aliyun_tablestore_ext]",
- },
+ "ReMeTaskMemoryService": ".reme_task_memory_service",
+ "ReMePersonalMemoryService": ".reme_personal_memory_service",
+ "Mem0MemoryService": ".mem0_memory_service",
+ "TablestoreMemoryService": ".tablestore_memory_service",
},
)
diff --git a/src/agentscope_runtime/engine/services/session_history/__init__.py b/src/agentscope_runtime/engine/services/session_history/__init__.py
index 2abbd0663..c70077982 100644
--- a/src/agentscope_runtime/engine/services/session_history/__init__.py
+++ b/src/agentscope_runtime/engine/services/session_history/__init__.py
@@ -18,9 +18,6 @@
"SessionHistoryService": ".session_history_service",
"InMemorySessionHistoryService": ".session_history_service",
"RedisSessionHistoryService": ".redis_session_history_service",
- "TablestoreSessionHistoryService": {
- "module": ".tablestore_session_history_service",
- "hint": "pip install agentscope-runtime[aliyun_tablestore_ext]",
- },
+ "TablestoreSessionHistoryService": ".tablestore_session_history_service", # noqa
},
)
diff --git a/src/agentscope_runtime/sandbox/__init__.py b/src/agentscope_runtime/sandbox/__init__.py
index 495ec6c03..ec9c04b13 100644
--- a/src/agentscope_runtime/sandbox/__init__.py
+++ b/src/agentscope_runtime/sandbox/__init__.py
@@ -1,22 +1,28 @@
# -*- coding: utf-8 -*-
+from typing import TYPE_CHECKING
+from ..common.utils.lazy_loader import install_lazy_loader
from .custom import *
-from .box.base.base_sandbox import BaseSandbox
-from .box.browser.browser_sandbox import BrowserSandbox
-from .box.filesystem.filesystem_sandbox import FilesystemSandbox
-from .box.gui.gui_sandbox import GuiSandbox
-from .box.training_box.training_box import TrainingSandbox
-from .box.cloud.cloud_sandbox import CloudSandbox
-from .box.agentbay.agentbay_sandbox import AgentbaySandbox
-from .box.mobile.mobile_sandbox import MobileSandbox
+if TYPE_CHECKING:
+ from .box.base.base_sandbox import BaseSandbox
+ from .box.browser.browser_sandbox import BrowserSandbox
+ from .box.filesystem.filesystem_sandbox import FilesystemSandbox
+ from .box.gui.gui_sandbox import GuiSandbox
+ from .box.training_box.training_box import TrainingSandbox
+ from .box.cloud.cloud_sandbox import CloudSandbox
+ from .box.agentbay.agentbay_sandbox import AgentbaySandbox
+ from .box.mobile.mobile_sandbox import MobileSandbox
-__all__ = [
- "BaseSandbox",
- "BrowserSandbox",
- "FilesystemSandbox",
- "GuiSandbox",
- "TrainingSandbox",
- "CloudSandbox",
- "AgentbaySandbox",
- "MobileSandbox",
-]
+install_lazy_loader(
+ globals(),
+ {
+ "BaseSandbox": ".box.base.base_sandbox",
+ "BrowserSandbox": ".box.browser.browser_sandbox",
+ "FilesystemSandbox": ".box.filesystem.filesystem_sandbox",
+ "GuiSandbox": ".box.gui.gui_sandbox",
+ "TrainingSandbox": ".box.training_box.training_box",
+ "CloudSandbox": ".box.cloud.cloud_sandbox",
+ "AgentbaySandbox": ".box.agentbay.agentbay_sandbox",
+ "MobileSandbox": ".box.mobile.mobile_sandbox",
+ },
+)
diff --git a/src/agentscope_runtime/sandbox/box/mobile/adbmcp/src/adb-tool.ts b/src/agentscope_runtime/sandbox/box/mobile/adbmcp/src/adb-tool.ts
index 908424cf3..78511fac1 100644
--- a/src/agentscope_runtime/sandbox/box/mobile/adbmcp/src/adb-tool.ts
+++ b/src/agentscope_runtime/sandbox/box/mobile/adbmcp/src/adb-tool.ts
@@ -1,10 +1,9 @@
// src/adb-tool.ts
-import Adb from 'adbkit';
+import Adb from "adbkit";
const client: Adb.Client = Adb.createClient();
-
let deviceId: string;
export async function initializeAdb(): Promise {
@@ -12,42 +11,53 @@ export async function initializeAdb(): Promise {
const deviceDescriptors = await client.listDevices();
if (deviceDescriptors.length === 0) {
- throw new Error('No Android devices found. Please connect a device or start an emulator.');
+ throw new Error(
+ "No Android devices found. Please connect a device or start an emulator.",
+ );
}
-
const firstDeviceDesc = deviceDescriptors[0]!;
-
deviceId = firstDeviceDesc.id;
- console.error('Found devices:', deviceDescriptors.map(d => d.id));
+ console.error(
+ "Found devices:",
+ deviceDescriptors.map((d) => d.id),
+ );
console.error(`Connected to device: ${deviceId} (${firstDeviceDesc.type})`);
-
} catch (err) {
- console.error('Failed to initialize ADB:', err);
- process.exit(1);
+ console.error("Failed to initialize ADB:", err);
+ process.exit(1);
}
}
-
function ensureDeviceId(): string {
if (!deviceId) {
- throw new Error('ADB device ID is not initialized. Call initializeAdb() first.');
+ throw new Error(
+ "ADB device ID is not initialized. Call initializeAdb() first.",
+ );
}
return deviceId;
}
-
export async function tap(x: number, y: number): Promise {
const id = ensureDeviceId();
await client.shell(id, `input tap ${x} ${y}`);
return `Tapped at (${x}, ${y})`;
}
-export async function swipe(startX: number, startY: number, endX: number, endY: number, durationMs: number = 300): Promise {
+export async function swipe(
+ startX: number,
+ startY: number,
+ endX: number,
+ endY: number,
+ durationMs: number = 300,
+): Promise {
const id = ensureDeviceId();
- await client.shell(id, `input swipe ${startX} ${startY} ${endX} ${endY} ${durationMs}`);
+ await client.shell(
+ id,
+ `input swipe ${startX} ${startY} ${endX} ${endY} ${durationMs}`,
+ );
return `Swiped from (${startX}, ${startY}) to (${endX}, ${endY})`;
}
@@ -64,11 +74,14 @@ export async function keyEvent(keyCode: number | string): Promise {
return `Sent key event: ${keyCode}`;
}
-export async function getScreenResolution(): Promise<{ width: number, height: number }> {
+export async function getScreenResolution(): Promise<{
+ width: number;
+ height: number;
+}> {
const id = ensureDeviceId();
- const output = await client.shell(id, 'wm size');
+ const output = await client.shell(id, "wm size");
const outputStr = await streamToString(output);
-
+
const match = outputStr.match(/Physical size: (\d+)x(\d+)/);
if (match && match[1] && match[2]) {
return {
@@ -76,32 +89,32 @@ export async function getScreenResolution(): Promise<{ width: number, height: nu
height: parseInt(match[2], 10),
};
}
- throw new Error('Could not determine screen resolution from ADB output.');
+ throw new Error("Could not determine screen resolution from ADB output.");
}
/**
- * @returns {Promise} - Base64
+ * @returns {Promise} - Base64
*/
export async function getScreenshot(): Promise {
const id = ensureDeviceId();
-
+
const stream = await client.screencap(id);
const chunks: Buffer[] = [];
return new Promise((resolve, reject) => {
- stream.on('data', (chunk: Buffer) => chunks.push(chunk));
- stream.on('error', (err) => reject(err));
- stream.on('end', () => {
- resolve(Buffer.concat(chunks).toString('base64'));
+ stream.on("data", (chunk: Buffer) => chunks.push(chunk));
+ stream.on("error", (err) => reject(err));
+ stream.on("end", () => {
+ resolve(Buffer.concat(chunks).toString("base64"));
});
});
}
async function streamToString(stream: NodeJS.ReadableStream): Promise {
- const chunks: Buffer[] = [];
- return new Promise((resolve, reject) => {
- stream.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
- stream.on('error', (err) => reject(err));
- stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
- });
+ const chunks: Buffer[] = [];
+ return new Promise((resolve, reject) => {
+ stream.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
+ stream.on("error", (err) => reject(err));
+ stream.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
+ });
}
diff --git a/src/agentscope_runtime/sandbox/box/mobile/adbmcp/src/index.ts b/src/agentscope_runtime/sandbox/box/mobile/adbmcp/src/index.ts
index 080d47c03..1dc04a093 100644
--- a/src/agentscope_runtime/sandbox/box/mobile/adbmcp/src/index.ts
+++ b/src/agentscope_runtime/sandbox/box/mobile/adbmcp/src/index.ts
@@ -1,22 +1,21 @@
// src/index.ts
-import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
-import { server } from './server.js';
-import { initializeAdb } from './adb-tool.js';
+import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
+import { server } from "./server.js";
+import { initializeAdb } from "./adb-tool.js";
async function main() {
await initializeAdb();
const transport = new StdioServerTransport();
- process.on('SIGINT', () => {
- console.log('Caught interrupt signal, shutting down.');
+ process.on("SIGINT", () => {
+ console.log("Caught interrupt signal, shutting down.");
transport.close();
process.exit(0);
});
-
- await server.connect(transport);
- console.error('ADB MCP server running on stdio');
+ await server.connect(transport);
+ console.error("ADB MCP server running on stdio");
}
main().catch(console.error);
diff --git a/src/agentscope_runtime/sandbox/box/mobile/adbmcp/src/server.ts b/src/agentscope_runtime/sandbox/box/mobile/adbmcp/src/server.ts
index 86c48e6fe..8f91e909f 100644
--- a/src/agentscope_runtime/sandbox/box/mobile/adbmcp/src/server.ts
+++ b/src/agentscope_runtime/sandbox/box/mobile/adbmcp/src/server.ts
@@ -1,154 +1,198 @@
// src/server.ts
-import { Server } from '@modelcontextprotocol/sdk/server/index.js';
+import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import {
- CallToolRequestSchema,
- ListToolsRequestSchema,
- type Tool,
-} from '@modelcontextprotocol/sdk/types.js';
-import { z } from 'zod';
-import * as adb from './adb-tool.js';
-
-import { zodToJsonSchema } from 'zod-to-json-schema';
-
-
-const adbToolParams = z.discriminatedUnion('action', [
- z.object({
- action: z.literal('get_screen_resolution'),
- }).describe("Get the physical screen resolution of the device."),
-
- z.object({
- action: z.literal('tap'),
- coordinate: z.tuple([z.number().int(), z.number().int()])
- .describe("The [x, y] pixel coordinates on the screen to tap."),
- }).describe("Simulate a single tap on the screen at a specified coordinate."),
-
- z.object({
- action: z.literal('swipe'),
- start: z.tuple([z.number().int(), z.number().int()])
- .describe("The starting [x, y] pixel coordinates of the swipe."),
- end: z.tuple([z.number().int(), z.number().int()])
- .describe("The ending [x, y] pixel coordinates of the swipe."),
- duration: z.number().int().optional()
- .describe("The duration of the swipe in milliseconds (optional, defaults to 300ms)."),
- }).describe("Simulate a swipe gesture on the screen from a start to an end coordinate."),
-
- z.object({
- action: z.literal('input_text'),
- text: z.string().describe("The text to be typed into the focused input field."),
- }).describe("Input a string of text. A text field must be focused on the device screen first."),
-
- z.object({
- action: z.literal('key_event'),
- code: z.union([z.number().int(), z.string().regex(/^\d+$/).transform(Number)])
- .describe("The key code to send. Common codes: 3 (Home), 4 (Back), 66 (Enter)."),
- }).describe("Send a key event to the device, simulating a button press."),
+ CallToolRequestSchema,
+ ListToolsRequestSchema,
+ type Tool,
+} from "@modelcontextprotocol/sdk/types.js";
+import { z } from "zod";
+import * as adb from "./adb-tool.js";
+
+import { zodToJsonSchema } from "zod-to-json-schema";
+
+const adbToolParams = z.discriminatedUnion("action", [
+ z
+ .object({
+ action: z.literal("get_screen_resolution"),
+ })
+ .describe("Get the physical screen resolution of the device."),
+
+ z
+ .object({
+ action: z.literal("tap"),
+ coordinate: z
+ .tuple([z.number().int(), z.number().int()])
+ .describe("The [x, y] pixel coordinates on the screen to tap."),
+ })
+ .describe("Simulate a single tap on the screen at a specified coordinate."),
+
+ z
+ .object({
+ action: z.literal("swipe"),
+ start: z
+ .tuple([z.number().int(), z.number().int()])
+ .describe("The starting [x, y] pixel coordinates of the swipe."),
+ end: z
+ .tuple([z.number().int(), z.number().int()])
+ .describe("The ending [x, y] pixel coordinates of the swipe."),
+ duration: z
+ .number()
+ .int()
+ .optional()
+ .describe(
+ "The duration of the swipe in milliseconds (optional, defaults to 300ms).",
+ ),
+ })
+ .describe(
+ "Simulate a swipe gesture on the screen from a start to an end coordinate.",
+ ),
+
+ z
+ .object({
+ action: z.literal("input_text"),
+ text: z
+ .string()
+ .describe("The text to be typed into the focused input field."),
+ })
+ .describe(
+ "Input a string of text. A text field must be focused on the device screen first.",
+ ),
+
+ z
+ .object({
+ action: z.literal("key_event"),
+ code: z
+ .union([z.number().int(), z.string().regex(/^\d+$/).transform(Number)])
+ .describe(
+ "The key code to send. Common codes: 3 (Home), 4 (Back), 66 (Enter).",
+ ),
+ })
+ .describe("Send a key event to the device, simulating a button press."),
// get_screenshot
- z.object({
- action: z.literal('get_screenshot'),
- }).describe("Take a screenshot of the current device screen and return it as a Base64 encoded PNG image."),
+ z
+ .object({
+ action: z.literal("get_screenshot"),
+ })
+ .describe(
+ "Take a screenshot of the current device screen and return it as a Base64 encoded PNG image.",
+ ),
]);
-
const legacyAdbTool = {
- name: 'adb',
- description: 'A tool to control an Android device using the Android Debug Bridge (ADB).',
-
+ name: "adb",
+ description:
+ "A tool to control an Android device using the Android Debug Bridge (ADB).",
+
inputSchema: {
properties: {
action: {
- type: 'string',
- description: 'The specific action to perform.'
+ type: "string",
+ description: "The specific action to perform.",
+ },
+ coordinate: { type: "array", description: 'For "tap" action.' },
+ start: { type: "array", description: 'For "swipe" action.' },
+ end: { type: "array", description: 'For "swipe" action.' },
+ duration: {
+ type: "number",
+ description: 'For "swipe" action (optional).',
},
- coordinate: { type: 'array', description: 'For "tap" action.' },
- start: { type: 'array', description: 'For "swipe" action.' },
- end: { type: 'array', description: 'For "swipe" action.' },
- duration: { type: 'number', description: 'For "swipe" action (optional).' },
- text: { type: 'string', description: 'For "input_text" action.' },
- code: { type: 'string | number', description: 'For "key_event" action.' }
+ text: { type: "string", description: 'For "input_text" action.' },
+ code: { type: "string | number", description: 'For "key_event" action.' },
},
- required: ['action'],
+ required: ["action"],
},
};
-
-
-
class InvalidToolError extends Error {
constructor(message: string) {
super(message);
- this.name = 'InvalidToolError';
+ this.name = "InvalidToolError";
}
}
-export const server = new Server({
- name: 'mobile-use-mcp',
- version: '0.0.1',
-}, {
- capabilities: {
- tools: {},
- },
-});
+export const server = new Server(
+ {
+ name: "mobile-use-mcp",
+ version: "0.0.1",
+ },
+ {
+ capabilities: {
+ tools: {},
+ },
+ },
+);
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
- tools: [legacyAdbTool],
+ tools: [legacyAdbTool],
};
});
-server.setRequestHandler(
- CallToolRequestSchema,
- async (request) => {
- const { name, arguments: args } = request.params;
+server.setRequestHandler(CallToolRequestSchema, async (request) => {
+ const { name, arguments: args } = request.params;
- if (name !== 'adb') {
- throw new InvalidToolError(`Tool '${name}' not supported. Only 'adb' is available.`);
- }
+ if (name !== "adb") {
+ throw new InvalidToolError(
+ `Tool '${name}' not supported. Only 'adb' is available.`,
+ );
+ }
- try {
- const validatedArgs = adbToolParams.parse(args);
-
- switch (validatedArgs.action) {
- case 'get_screen_resolution': {
- const resolution = await adb.getScreenResolution();
- return { content: [{ type: 'text', text: JSON.stringify(resolution) }] };
- }
- case 'tap': {
- const [x, y] = validatedArgs.coordinate;
- const result = await adb.tap(x, y);
- return { content: [{ type: 'text', text: result }] };
- }
- case 'swipe': {
- const [startX, startY] = validatedArgs.start;
- const [endX, endY] = validatedArgs.end;
- const result = await adb.swipe(startX, startY, endX, endY, validatedArgs.duration);
- return { content: [{ type: 'text', text: result }] };
- }
- case 'input_text': {
- const result = await adb.inputText(validatedArgs.text);
- return { content: [{ type: 'text', text: result }] };
- }
- case 'key_event': {
- const result = await adb.keyEvent(validatedArgs.code);
- return { content: [{ type: 'text', text: result }] };
- }
- case 'get_screenshot': {
- const base64Image = await adb.getScreenshot();
+ try {
+ const validatedArgs = adbToolParams.parse(args);
+
+ switch (validatedArgs.action) {
+ case "get_screen_resolution": {
+ const resolution = await adb.getScreenResolution();
return {
- content: [{
- type: 'image',
- data: base64Image,
- mimeType: 'image/png'
- }]
+ content: [{ type: "text", text: JSON.stringify(resolution) }],
};
}
+ case "tap": {
+ const [x, y] = validatedArgs.coordinate;
+ const result = await adb.tap(x, y);
+ return { content: [{ type: "text", text: result }] };
+ }
+ case "swipe": {
+ const [startX, startY] = validatedArgs.start;
+ const [endX, endY] = validatedArgs.end;
+ const result = await adb.swipe(
+ startX,
+ startY,
+ endX,
+ endY,
+ validatedArgs.duration,
+ );
+ return { content: [{ type: "text", text: result }] };
+ }
+ case "input_text": {
+ const result = await adb.inputText(validatedArgs.text);
+ return { content: [{ type: "text", text: result }] };
+ }
+ case "key_event": {
+ const result = await adb.keyEvent(validatedArgs.code);
+ return { content: [{ type: "text", text: result }] };
}
- } catch (error) {
- if (error instanceof z.ZodError) {
- throw new InvalidToolError(`Invalid arguments for tool '${name}': ${error.message}`);
+ case "get_screenshot": {
+ const base64Image = await adb.getScreenshot();
+ return {
+ content: [
+ {
+ type: "image",
+ data: base64Image,
+ mimeType: "image/png",
+ },
+ ],
+ };
}
- throw error;
}
+ } catch (error) {
+ if (error instanceof z.ZodError) {
+ throw new InvalidToolError(
+ `Invalid arguments for tool '${name}': ${error.message}`,
+ );
+ }
+ throw error;
}
-);
+});
diff --git a/src/agentscope_runtime/sandbox/box/mobile/adbmcp/src/types.d.ts b/src/agentscope_runtime/sandbox/box/mobile/adbmcp/src/types.d.ts
index c69f85766..324cf7336 100644
--- a/src/agentscope_runtime/sandbox/box/mobile/adbmcp/src/types.d.ts
+++ b/src/agentscope_runtime/sandbox/box/mobile/adbmcp/src/types.d.ts
@@ -1,10 +1,10 @@
// src/types.d.ts
-declare module 'adbkit' {
+declare module "adbkit" {
namespace Adb {
interface Device {
id: string;
- type: 'device' | 'emulator' | 'offline';
+ type: "device" | "emulator" | "offline";
}
/**
@@ -16,11 +16,13 @@ declare module 'adbkit' {
/**
*/
- shell(id: string, command: string | string[]): Promise;
+ shell(
+ id: string,
+ command: string | string[],
+ ): Promise;
/**
*/
screencap(id: string): Promise;
-
}
function createClient(options?: { host?: string; port?: number }): Client;
diff --git a/src/agentscope_runtime/sandbox/box/mobile/adbmcp/tsconfig.build.json b/src/agentscope_runtime/sandbox/box/mobile/adbmcp/tsconfig.build.json
index 84cd5e0c4..96ce8f128 100644
--- a/src/agentscope_runtime/sandbox/box/mobile/adbmcp/tsconfig.build.json
+++ b/src/agentscope_runtime/sandbox/box/mobile/adbmcp/tsconfig.build.json
@@ -2,9 +2,9 @@
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "dist",
- "declaration": true,
+ "declaration": true
},
"exclude": [
- "**/*.test.ts",
- ],
-}
+ "**/*.test.ts"
+ ]
+}
\ No newline at end of file
diff --git a/tests/integrated/README.md b/tests/integrated/README.md
index d84c38cfe..2ea5c0d0d 100644
--- a/tests/integrated/README.md
+++ b/tests/integrated/README.md
@@ -11,7 +11,7 @@ Ensure the health check endpoint at localhost:8080/health is healthy during test
- Install runtime and required cloud SDKs:
#### 1. Download agentscope-runtime
```bash
-pip install agentscope-runtime && pip install "agentscope-runtime[deployment]"
+pip install "agentscope-runtime[ext]"
```
#### 2. Set the required environment variables:
```bash
diff --git a/tests/integrated/README_zh.md b/tests/integrated/README_zh.md
index 60be7e039..517e0f870 100644
--- a/tests/integrated/README_zh.md
+++ b/tests/integrated/README_zh.md
@@ -11,7 +11,7 @@
- 安装运行时以及所需的云 SDK:
#### 1. 下载 agentscope-runtime
```bash
-pip install agentscope-runtime && pip install "agentscope-runtime[deployment]"
+pip install "agentscope-runtime[ext]"
```
#### 2. 设置所需的环境变量:
```bash
diff --git a/tests/integrated/test_bailian_fc_deploy/README.md b/tests/integrated/test_bailian_fc_deploy/README.md
index 769c704df..7d5266dc8 100644
--- a/tests/integrated/test_bailian_fc_deploy/README.md
+++ b/tests/integrated/test_bailian_fc_deploy/README.md
@@ -12,7 +12,7 @@ The flow includes:
- Python >= 3.10
- Install runtime and required cloud SDKs:
```bash
-pip install agentscope-runtime && pip install "agentscope-runtime[deployment]"
+pip install "agentscope-runtime[ext]"
```
- Set the required environment variables:
diff --git a/tests/integrated/test_bailian_fc_deploy/README_zh.md b/tests/integrated/test_bailian_fc_deploy/README_zh.md
index 48253a58c..31eaf20b2 100644
--- a/tests/integrated/test_bailian_fc_deploy/README_zh.md
+++ b/tests/integrated/test_bailian_fc_deploy/README_zh.md
@@ -12,7 +12,7 @@
- Python >= 3.10
- 安装运行时与云端 SDK:
```bash
-pip install agentscope-runtime && pip install "agentscope-runtime[deployment]"
+pip install "agentscope-runtime[ext]"
```
- 配置所需环境变量: