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 *Input and *Output models so arguments/results are validated before any network call and so function schemas can be generated automatically.

  • Adapter friendly: the shared Tool base emits OpenAI-compatible function_schema, allowing adapters (AgentScope, LangGraph, AutoGen, MCP, etc.) to expose tools with zero additional glue.

  • Async-first, sync-friendly: _arun is always async for throughput, while run() 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: Tool captures the generic ToolArgsT/ToolReturnT types, 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 FunctionTool schema so LLM tool-calling stacks know exactly how to call the tool.

  • Async + sync execution: call await tool.arun(...) inside async workflows or tool.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

  1. Configure credentials: declare environment variables (DashScope keys, Alipay secrets, etc.) before running the agent process so tools can authenticate.

  2. Instantiate once: create tool objects during agent initialization; reuse them instead of re-instantiating per call to keep connections warm.

  3. Prepare payloads: build dictionaries or Pydantic instances that match the documented *Input model. When calling from LLM tool invocations, rely on the generated schema to keep arguments consistent.

  4. Call asynchronously: prefer await tool.arun(input_model); only use run() in synchronous contexts.

  5. Consume structured outputs: each result is a typed model (e.g., SearchOutput, RagOutput, PaymentOutput)—store them directly or convert with return_value_as_string() for persistence.

  6. 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 messages plus search_options dict (strategy, max_results, time_range, etc.), optionally add search_output_rules for citations/summaries, and read back search_result + search_info.

  • Learn more: see cookbook/en/tools/modelstudio_search.md for strategy lists, architecture diagrams, and code samples derived from docs/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; consume rag_result.answer, references, and confidence.

  • Learn more: consult cookbook/en/tools/modelstudio_rag.md, which summarizes the detailed behavior from docs/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, ImageStyleRepaint and the WAN/Qwen variants under agentscope_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 provide base_image_url + mask_image_url for edits; outputs are signed asset URLs—download or proxy them promptly.

  • Learn more: cookbook/en/tools/modelstudio_generations.md mirrors docs/en/generations.md with 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 optional out_request_no; subscription tools pivot on user uuid and return flags, packages, or subscription URLs.

  • Learn more: cookbook/en/tools/alipay.md (and the source docs/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 (Tool suffix 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.