Skip to content

feat(tool): 添加工具相关的新模块和API接口#74

Open
Sodawyx wants to merge 4 commits intomainfrom
implement-new-tools
Open

feat(tool): 添加工具相关的新模块和API接口#74
Sodawyx wants to merge 4 commits intomainfrom
implement-new-tools

Conversation

@Sodawyx
Copy link
Copy Markdown
Collaborator

@Sodawyx Sodawyx commented Mar 27, 2026

此提交添加了一系列新的工具相关的模块和API接口,包括客户端模板、模型定义以及各种控制和OpenAPI接口等组件。同时更新了依赖版本并完善了初始化配置。

Co-developed-by: Aone Copilot noreply@alibaba-inc.com

Thank you for creating a pull request to contribute to Serverless Devs agentrun-sdk-python code! Before you open the request please answer the following questions to help it be more easily integrated. Please check the boxes "[ ]" with "[x]" when done too.
Please select one of the PR types below to complete


Fix bugs

Bug detail

The specific manifestation of the bug or the associated issue.

Pull request tasks

  • Add test cases for the changes
  • Passed the CI test

Update docs

Reason for update

Why do you need to update your documentation?

Pull request tasks

  • Update Chinese documentation
  • Update English documentation

Add contributor

Contributed content

  • Code
  • Document

Content detail

if content_type == 'code' || content_type == 'document':
    please tell us `PR url`,like: https://github.com/Serverless-Devs/agentrun-sdk-python/pull/1
else:
    please describe your contribution in detail

Others

Reason for update

Why do you need to update your documentation?

此提交添加了一系列新的工具相关的模块和API接口,包括客户端模板、模型定义以及各种控制和OpenAPI接口等组件。同时更新了依赖版本并完善了初始化配置。

Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
Signed-off-by: Sodawyx <sodawyx@126.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

该 PR 为 SDK 新增了完整的 Tool 相关模块与 API(管控链路 + 数据链路),并补齐了对应的单元测试,同时更新了底层依赖版本以支持新能力。

Changes:

  • 新增 agentrun.tool 模块:包含 Tool 资源类、客户端、模型定义,以及 Control/MCP/OpenAPI 三类 API 组件
  • 新增 Tool 模块的单元测试覆盖(model / mcp / openapi / tool & client)
  • 更新 alibabacloud-agentrun20250910 依赖版本要求

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pyproject.toml 升级底层 alibabacloud-agentrun20250910 版本以支持新 Tool 能力
agentrun/tool/__init__.py 聚合导出 tool 模块公共 API
agentrun/tool/model.py 新增 ToolType/McpConfig/ToolSchema/ToolInfo 等模型定义
agentrun/tool/api/__init__.py Tool API 子模块初始化
agentrun/tool/api/control.py 新增 Tool 管控链路 API(基于底层 SDK 获取 Tool 资源)
agentrun/tool/api/mcp.py 新增 MCP 数据链路会话封装(SSE/Streamable)
agentrun/tool/api/openapi.py 新增 FunctionCall(OpenAPI) 数据链路解析与 HTTP 调用客户端
agentrun/tool/client.py 新增 ToolClient(get/get_async)
agentrun/tool/tool.py 新增 Tool 资源类:支持 get、list_tools、call_tool(sync/async)
agentrun/tool/__client_async_template.py codegen 模板:ToolClient(async)
agentrun/tool/__tool_async_template.py codegen 模板:Tool 资源类(async)
agentrun/__init__.py 顶层导出 ToolResource/ToolResourceClient/ToolResourceControlAPI(避免与 server.Tool 冲突)
tests/unittests/tool/__init__.py Tool 测试包初始化
tests/unittests/tool/test_model.py Tool 模型单元测试
tests/unittests/tool/test_mcp.py MCP 会话单元测试
tests/unittests/tool/test_openapi.py OpenAPI 客户端单元测试
tests/unittests/tool/test_tool.py Tool 资源类与 ToolClient 单元测试

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +258 to +270
url = f"{base_url.rstrip('/')}{target_operation['path']}"
method = target_operation["method"]

logger.debug(
f"Calling FunctionCall tool: {method} {url} with args={arguments}"
)

with httpx.Client(headers=self.headers, timeout=30.0) as client:
if method in ("POST", "PUT", "PATCH"):
response = client.request(method, url, json=arguments or {})
else:
response = client.request(method, url, params=arguments or {})

Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

call_tool()/call_tool_async() currently build the request URL by concatenating server_url and the raw OpenAPI path (e.g. /users/{id}) without substituting path parameters. For endpoints that use templated path params, this will send requests to URLs containing {id} literally and pass id as query/body instead, which is incorrect.

Consider rendering the path by replacing {param} placeholders with values from arguments (and removing those keys from query/body), similar to how agentrun/toolset/api/openapi.py handles path rendering/joining.

Copilot uses AI. Check for mistakes.
Comment on lines +166 to +169
param_schema = param.get("schema", {"type": "string"})
param_schema["description"] = param.get(
"description", ""
)
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

In _parse_operations(), parameter handling assumes every parameter has a dict schema and then mutates it (param_schema["description"] = ...). In valid OpenAPI 3, a Parameter may omit schema and instead provide content, and schema can also be None/non-dict. This will raise at runtime.

Suggest defaulting to a new dict schema when missing/non-dict, avoiding in-place mutation of the original spec, and optionally supporting content['application/json'].schema for parameters.

Suggested change
param_schema = param.get("schema", {"type": "string"})
param_schema["description"] = param.get(
"description", ""
)
# Prefer explicit schema, fall back to content-based schema, then a default.
raw_schema = param.get("schema")
resolved_schema: Dict[str, Any] = {}
if isinstance(raw_schema, dict):
# Try to resolve $ref or composed schemas; fall back to the raw dict.
maybe_resolved = self._resolve_schema(raw_schema)
if isinstance(maybe_resolved, dict):
resolved_schema = dict(maybe_resolved)
else:
resolved_schema = dict(raw_schema)
else:
# OpenAPI 3 allows parameters to define schema under content.
param_content = param.get("content", {})
raw_content_schema = None
if isinstance(param_content, dict):
json_content = param_content.get("application/json", {})
if isinstance(json_content, dict):
raw_content_schema = json_content.get("schema")
if raw_content_schema is not None:
maybe_resolved = self._resolve_schema(raw_content_schema)
if isinstance(maybe_resolved, dict):
resolved_schema = dict(maybe_resolved)
if not isinstance(resolved_schema, dict) or not resolved_schema:
resolved_schema = {"type": "string"}
# Do not mutate the original spec; work on our own copy.
param_schema = dict(resolved_schema)
param_schema["description"] = param.get("description", "")

Copilot uses AI. Check for mistakes.
Comment on lines +95 to +97
return asyncio.get_event_loop().run_until_complete(
self.list_tools_async()
)
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

The synchronous wrappers list_tools() / call_tool() use asyncio.get_event_loop().run_until_complete(...). This is fragile on Python 3.10+ (can raise when no default loop is set) and will fail if called from within an already-running event loop.

Elsewhere in the repo (e.g. agentrun/toolset/api/mcp.py) sync wrappers use asyncio.run(...). Consider aligning with that approach or otherwise handling the running-loop case safely.

Suggested change
return asyncio.get_event_loop().run_until_complete(
self.list_tools_async()
)
try:
# If this succeeds, we're already inside an event loop
asyncio.get_running_loop()
except RuntimeError:
# No running loop: safe to create and manage one with asyncio.run
return asyncio.run(self.list_tools_async())
else:
# Called from async context: must use the async API instead
raise RuntimeError(
"list_tools() cannot be called from an async context. "
"Use list_tools_async() instead."
)

Copilot uses AI. Check for mistakes.
import asyncio
from typing import Any, Dict, List, Optional

from agentrun.tool.model import ToolInfo, ToolSchema
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

ToolSchema is imported but never used in this module. With ruff/pylint enabled in the repo, this will likely fail linting.

Remove the unused import (or use it if intended).

Suggested change
from agentrun.tool.model import ToolInfo, ToolSchema
from agentrun.tool.model import ToolInfo

Copilot uses AI. Check for mistakes.
Sodawyx added 3 commits March 29, 2026 17:00
此提交添加了对SKILL类型工具的支持,包括获取下载URL和异步下载解压的功能。同时更新了相关单元测试。

Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
Signed-off-by: Sodawyx <sodawyx@126.com>
在多个集成模块中添加了 `tool_resource` 函数的支持,允许用户将 ToolResource 封装为不同 AI 框架所需的工具格式,包括 CrewAI、LangChain、PydanticAI、LangGraph 和 AgentScope。同时更新了相关初始化文件以导出新功能。

Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
Signed-off-by: Sodawyx <sodawyx@126.com>
在多个集成框架中添加了 `skill_tools` 函数,用于将 Skill 封装为不同 AI 框架的工具列表,包括 CrewAI、LangChain、PydanticAI、LangGraph、AgentScope 和 Google ADK。同时更新了相关的初始化文件和工具加载器。

Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
Signed-off-by: Sodawyx <sodawyx@126.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants