Tools¶
AgentScope Runtime embraces a componentized philosophy, instead of dropping you straight into API details we start with the motivation. Tools give us a uniform, type-safe capsule for those accessories so they can plug into any orchestration framework without rewrites.
Adding a tool is the recommended path whenever you need to expose a capability to multiple agents or execution engines. A tool carries its own IO schema, throttling policy, tracing hooks, and retry defaults, so you can register it as a tool for ReAct agents, feed it into LangGraph/MCP stacks, or publish it as an MCP server function. Teams typically introduce tools to solve recurring compliance constraints, encapsulate vendor APIs, or ship the same operation across on-call bots, copilots, and workflows.
Once a capability is wrapped as a tool, you gain predictable behavior in a few common scenarios: orchestrators can reason about arguments up front, audit pipelines can log the same typed payloads, and platform teams can patch or swap implementations without touching agent prompts. In short, tools hide infrastructure churn while giving LLM-facing teams a clean interface.
Why Tools (Key Features)¶
Modular architecture: enterprise-grade functions stay decoupled, making it easy to compose or swap tools without touching the agent core.
Framework integration: the same tool instances feed AgentScope Runtime, LangGraph, AutoGen, MCP, or bespoke frameworks thanks to uniform schemas.
ModelStudio alignment: tools wrap DashScope/ModelStudio services (Search, RAG, AIGC, Payments) with production-ready defaults, retries, and tracing.
Type safety and observability: Pydantic models, async execution, and centralized validation mirror the production focus described in the original README.
Clear benefits: consistent tool contracts, centralized governance, and faster onboarding for new agent teams because they reuse curated capabilities instead of reinventing integrations.
To shorten the “first tool” journey we pre-bundle several ModelStudio tools—Search, RAG, AIGC, and Payments—so you can start experimenting immediately before authoring custom ones.
Tool Design Principles¶
Single responsibility: each tool focuses on one enterprise capability (e.g., ModelStudio Search, Alipay refund) so it can be composed with other tools without hidden side effects.
Typed boundaries: tools declare Pydantic
*Inputand*Outputmodels so arguments/results are validated before any network call and so function schemas can be generated automatically.Adapter friendly: the shared
Toolbase emits OpenAI-compatiblefunction_schema, allowing adapters (AgentScope, LangGraph, AutoGen, MCP, etc.) to expose tools with zero additional glue.Async-first, sync-friendly:
_arunis always async for throughput, whilerun()bridges into sync contexts, just like the examples demonstrate for components.Observability-ready: because every invocation funnels through the base class, runtime tracing, retries, and logging can be added centrally without touching individual tools.
These principles mirror the design motifs in the example README (modular bricks, framework adapters, production-grade behaviors) but use the current Tool naming and runtime packages.
Tool Class Essentials¶
Core capabilities¶
Input/output enforcement:
Toolcaptures the genericToolArgsT/ToolReturnTtypes, validates runtime arguments, and ensures the return payload matches the declared schema.Automatic function schema: the base class inspects the Pydantic model and publishes a
FunctionToolschema so LLM tool-calling stacks know exactly how to call the tool.Async + sync execution: call
await tool.arun(...)inside async workflows ortool.run(...)when you only have a synchronous context; both paths share the same validation.Argument helpers:
Tool.verify_args()/verify_list_args()parse JSON strings or dicts into typed inputs, making it easy to deserialize persisted tool calls.Stringified outputs:
return_value_as_string()provides deterministic serialization for audit logs and adapters that require string outputs.
Custom Tool Development Example¶
import asyncio
from pydantic import BaseModel, Field
from agentscope_runtime.tools import Tool
class WeatherInput(BaseModel):
city: str = Field(..., description="City to check")
unit: str = Field(default="celsius", description="Temperature unit")
class WeatherOutput(BaseModel):
summary: str
temperature: float
class WeatherTool(Tool[WeatherInput, WeatherOutput]):
name = "weather_lookup"
description = "Fetches the current weather for a city"
async def _arun(self, args: WeatherInput, **kwargs) -> WeatherOutput:
# Replace with real API logic
return WeatherOutput(summary=f"Sunny in {args.city}", temperature=26.5)
async def main():
tool = WeatherTool()
result = await tool.arun(WeatherInput(city="Hangzhou"))
print(result.summary)
print(tool.function_schema) # ready for tool registration
asyncio.run(main())
Use this pattern for every custom tool: define Pydantic models, extend Tool, implement _arun, instantiate once, and pass the instance into whichever agent framework you use.
AgentScope Integration Example¶
We use agentscope_tool_adapter to add tools to AgentScope’s Toolkit:
import asyncio
import os
from agentscope.agent import ReActAgent
from agentscope.model import DashScopeChatModel
from agentscope.formatter import DashScopeChatFormatter
from agentscope.tool import Toolkit
from agentscope.message import Msg
from agentscope_runtime.tools.searches import (
ModelstudioSearchLite,
SearchInput,
SearchOptions,
)
from agentscope_runtime.adapters.agentscope.tool import agentscope_tool_adapter
search_tool = ModelstudioSearchLite()
search_tool = agentscope_tool_adapter(search_tool)
toolkit = Toolkit()
toolkit.tools[search_tool.name] = search_tool
agent = ReActAgent(
name="Friday",
model=DashScopeChatModel(
"qwen-turbo",
api_key=os.getenv("DASHSCOPE_API_KEY"),
stream=True,
),
sys_prompt="You're a helpful assistant named Friday.",
toolkit=toolkit,
formatter=DashScopeChatFormatter(),
)
if __name__ == "__main__":
asyncio.run(
agent(
Msg(
role="user",
name="user",
content="What is the weather like in Shenzhen?",
),
),
)
LangGraph Integration Example¶
To reproduce the “Apply to existing LangGraph project” flow, wrap the tool as a LangChain StructuredTool, bind it to a model, and wire it into a LangGraph workflow. The tool schema comes directly from the tool’s input model, so tool calls remain type-safe.
import os
from langchain_core.messages import HumanMessage
from langchain_core.tools import StructuredTool
from langchain_openai import ChatOpenAI
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import START, END, MessagesState, StateGraph
from langgraph.prebuilt import ToolNode
from agentscope_runtime.tools.searches import (
ModelstudioSearchLite,
SearchInput,
SearchOptions,
)
search_tool = ModelstudioSearchLite()
def search_tool_func(
messages: list[dict],
search_options: dict | None = None,
search_timeout: int | None = None,
type: str | None = None,
):
kwargs = {
"messages": messages,
"search_options": SearchOptions(**(search_options or {})),
}
if search_timeout is not None:
kwargs["search_timeout"] = search_timeout
if type is not None:
kwargs["type"] = type
result = search_tool.run(
SearchInput(**kwargs),
user_id=os.environ["MODELSTUDIO_USER_ID"],
)
return ModelstudioSearchLite.return_value_as_string(result)
search_tool = StructuredTool.from_function(
func=search_tool_func,
name=search_tool.name,
description=search_tool.description,
)
llm = ChatOpenAI(
model="qwen-turbo",
openai_api_key=os.environ["DASHSCOPE_API_KEY"],
openai_api_base="https://dashscope.aliyuncs.com/compatible-mode/v1",
).bind_tools([search_tool])
def should_continue(state: MessagesState):
last = state["messages"][-1]
return "tools" if last.tool_calls else END
def call_model(state: MessagesState):
response = llm.invoke(state["messages"])
return {"messages": [response]}
workflow = StateGraph(MessagesState)
workflow.add_node("agent", call_model)
workflow.add_node("tools", ToolNode([search_tool]))
workflow.add_edge(START, "agent")
workflow.add_conditional_edges("agent", should_continue)
workflow.add_edge("tools", "agent")
app = workflow.compile(checkpointer=MemorySaver())
final_state = app.invoke(
{"messages": [HumanMessage(content="Give me the latest Hangzhou news.")]}
)
print(final_state["messages"][-1].content)
AutoGen Integration Example¶
We use AutogenToolAdapter to convert our tool to AutogenTool:
import asyncio
from agentscope_runtime.tools.searches import ModelstudioSearchLite
from agentscope_runtime.adapters.autogen.tool import AutogenToolAdapter
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.messages import TextMessage
from autogen_core import CancellationToken
async def main():
# Create the search tool
search_tool = ModelstudioSearchLite()
# Create the autogen tool adapter
search_tool = AutogenToolAdapter(search_tool)
# Create an agents with the search tool
model = OpenAIChatCompletionClient(model="gpt-4")
agents = AssistantAgent(
"assistant",
tools=[search_tool],
model_client=model,
)
# Use the agents
response = await agents.on_messages(
[TextMessage(content="What's the weather in Beijing?",
source="user")],
CancellationToken(),
)
print(response.chat_message)
asyncio.run(main())
Using Tools inside Agents¶
Configure credentials: declare environment variables (DashScope keys, Alipay secrets, etc.) before running the agent process so tools can authenticate.
Instantiate once: create tool objects during agent initialization; reuse them instead of re-instantiating per call to keep connections warm.
Prepare payloads: build dictionaries or Pydantic instances that match the documented
*Inputmodel. When calling from LLM tool invocations, rely on the generated schema to keep arguments consistent.Call asynchronously: prefer
await tool.arun(input_model); only userun()in synchronous contexts.Consume structured outputs: each result is a typed model (e.g.,
SearchOutput,RagOutput,PaymentOutput)—store them directly or convert withreturn_value_as_string()for persistence.Integrate via adapters: the runtime already provides adapters for AgentScope, LangGraph, MCP, etc. Simply hand over
tool.function_schema(or the tool instance itself, depending on the adapter) to wire the capability into your workflow.
Built-in Tool Families¶
Each family bundles a set of related ModelStudio or partner services. Refer to the detailed cookbook pages for exhaustive parameter tables, examples, and operational notes.
ModelStudio Search Tools¶
Key tools:
ModelstudioSearch,ModelstudioSearchLite(agentscope_runtime.tools.searches).When to use: semantic/metasearch across web, news, academic, product, multimedia sources, with advanced routing, filtering, and caching. Lite version trades configurability for latency and resource savings.
Usage highlights: supply
messagesplussearch_optionsdict (strategy,max_results,time_range, etc.), optionally addsearch_output_rulesfor citations/summaries, and read backsearch_result+search_info.Learn more: see
cookbook/en/tools/modelstudio_search.mdfor strategy lists, architecture diagrams, and code samples derived fromdocs/zh/searches.md.
For details, please see Search Components
ModelStudio RAG Tools¶
Key tools:
ModelstudioRag,ModelstudioRagLite(agentscope_runtime.common.tools.RAGs).When to use: ground answers in DashScope knowledge bases with dense/sparse/hybrid retrieval, multi-turn context fusion, multimodal inputs, and citation-friendly generation.
Usage highlights: pass the dialogue
messages,rag_options(knowledge_base_id,top_k,score_threshold,enable_citation), plus authentication tokens; consumerag_result.answer,references, andconfidence.Learn more: consult
cookbook/en/tools/modelstudio_rag.md, which summarizes the detailed behavior fromdocs/en/RAGs.md, including optimization tips (vector indexes, chunking strategies, streaming generation).
For details, please see Retrieval-Augmented Generation Components (RAGs)
ModelStudio AIGC (Generations) Tools¶
Key tools:
ImageGeneration,ImageEdit,ImageStyleRepaintand the WAN/Qwen variants underagentscope_runtime.tools.generations.When to use: text-to-image creation, image editing (in/out-painting, replacements), and portrait style transfer with DashScope WanXiang or Qwen media models.
Usage highlights: supply prompts plus optional
size/n, or providebase_image_url+mask_image_urlfor edits; outputs are signed asset URLs—download or proxy them promptly.Learn more:
cookbook/en/tools/modelstudio_generations.mdmirrorsdocs/en/generations.mdwith environment variables, dependencies, and example event loops.
For details, please see Image Generation Components
Alipay Payment & Subscription Tools¶
Key tools (from
agentscope_runtime.tools.alipay):MobileAlipayPayment,WebPageAlipayPayment,AlipayPaymentQuery,AlipayPaymentRefund,AlipayRefundQuery,AlipaySubscribeStatusCheck,AlipaySubscribePackageInitialize,AlipaySubscribeTimesSave,AlipaySubscribeCheckOrInitialize.When to use: orchestrate full payment lifecycles (link creation, status checks, refunds) and manage subscription entitlements or pay-per-use deductions inside enterprise agents.
Usage highlights: payment tools accept
out_trade_no,order_title,total_amount; query/refund tools operate on order IDs plus optionalout_request_no; subscription tools pivot on useruuidand return flags, packages, or subscription URLs.Learn more:
cookbook/en/tools/alipay.md(and the sourcedocs/en/alipay.md) detail prerequisites, environment variables (ALIPAY_APP_ID,ALIPAY_PRIVATE_KEY, etc.), and example async flows.
For details, please see Alipay Components
Where to Go Next¶
Deep dives: open the per-family cookbook pages under
cookbook/en/tools/whenever you need exhaustive parameter tables or troubleshooting guides.Examples: re-run the scripts in
examples/to see how the same tools integrate with AgentScope Runtime, LangGraph, AutoGen, or other frameworks.New tools: follow the Quickstart template to wrap additional enterprise APIs; keep naming consistent (
Toolsuffix optional but recommended) and document them alongside the existing cookbook entries.
📖 FAQ¶
Q: Why can’t or shouldn’t these out‑of‑the‑box Tools run inside a sandbox? A: Prebuilt Tools (like Search, RAG, AIGC, Payments) are purely API wrappers. Their logic executes on cloud services or third‑party platforms, and the local process only handles network requests. They do not alter system configurations, access local files, or spawn processes. Sandboxing is meant to isolate potentially risky operations (e.g., running untrusted scripts, executing system commands). Since these Tools conform to production safety requirements, we don’t recommend or support running them within a sandbox. If your use‑case needs to execute code that could impact the host environment, please follow sandbox integration patterns and create custom Tools designed for sandbox‑enabled engines.