Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.agentscope.io/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Tools are how an agent acts on the world — running shell commands, reading files, calling APIs. Each tool exposes itself to the LLM as a JSON Schema, and the agent invokes it through a unified streaming interface. AgentScope organizes tool-related building blocks under three concepts:
  • Tool — any class that satisfies the ToolBase interface, including the built-ins shipped with AgentScope and the FunctionTool / MCPTool adapters that wrap plain functions or MCP-server tools.
  • Toolkit — the container that registers tools, MCP clients, and skills, exposes their JSON schemas to the model, and dispatches each tool call to the right tool object.
  • Tool Group — a named bundle of tools, MCP clients, and skills that can be activated or deactivated as a unit. The agent toggles groups at runtime via the built-in meta tool to keep its context focused.
from agentscope.tool import Toolkit, Bash, Read, Write, Edit

toolkit = Toolkit(
    tools=[Bash(), Read(), Write(), Edit()],
)
A Toolkit created with tools alone exposes those tools in the special "basic" group, which is always active. Adding mcps, skills_or_loaders, or extra tool_groups extends what the agent can reach — see the sections below.

Python Tool

A Python tool is any object satisfying the ToolBase interface. AgentScope ships built-in tools for common operations and exposes the same interface for developers to build custom tools.

ToolBase Interface

ToolBase is the abstract base class every tool satisfies. The tables below list its attributes and methods. Attributes that describe the tool to the agent and the runtime:
AttributeTypeDescription
namestrThe tool name presented to the agent
descriptionstrAgent-oriented description of what the tool does
input_schemadictJSON Schema defining the tool’s parameters
is_concurrency_safeboolWhether the tool is safe to call in parallel
is_read_onlyboolWhether the tool only reads data without side effects
is_external_toolboolIf True, execution is delegated externally (see Define External Execution Tool)
is_state_injectedboolIf True, the agent state is injected via the _agent_state argument
is_mcpboolWhether the tool comes from an MCP server
mcp_namestr | NoneThe MCP server name when is_mcp is True
Methods that hook into execution and the permission system:
MethodRequiredDescription
check_permissions(tool_input, context)YesRuntime permission check before execution; returns PermissionDecision
match_rule(rule_content, tool_input)OptionalCustom rule-matching logic for the permission system; returns bool
generate_suggestions(tool_input)OptionalGenerate suggested permission rules from a tool call; returns list[PermissionRule]
__call__(**kwargs)OptionalThe tool’s execution logic; returns ToolChunk or AsyncGenerator[ToolChunk, None]. Not required for external execution tools.

Use Built-in Tools

AgentScope ships a set of ready-to-use tools covering common agent operations. Instantiate them and pass into Toolkit(tools=[...]):
ToolDescriptionRead-only
BashExecute shell commandsNo
ReadRead file contents with line numbersYes
WriteCreate or overwrite filesNo
EditPerform exact string replacements in filesNo
GlobFind files by glob patternYes
GrepSearch file contents using ripgrepYes
TaskCreateCreate a structured task for progress trackingNo
TaskGetRetrieve task details by IDYes
TaskListList all tasks and their statusYes
TaskUpdateUpdate task status or metadataNo
Two more tools — the reset_tools meta tool and the Skill viewer — are auto-registered by Toolkit whenever extra tool groups or skills exist. Developers do not instantiate them directly. See Manage Tools Agentically and Skill.

Bash

The Bash tool executes shell commands and returns stdout/stderr. It implements every optional interface method to provide fine-grained permission control. check_permissions() runs a layered safety analysis on the command string:
  1. Injection risk detection — flags dynamic shell structures ($(...), backticks, process substitution) that cannot be statically analyzed → ASK
  2. Read-only command detection — auto-allows safe commands (git status, ls, cat, grep, docker ps, etc.), including compound commands where every subcommand is read-only → ALLOW
  3. Dangerous command patterns — detects destructive operations (e.g. chmod 777, mkfs) → ASK
  4. Sed constraint check — blocks in-place sed -i against dangerous files → ASK
  5. Dangerous path protection — checks if the command operates on sensitive config files (.bashrc, .ssh/, .env) → ASK
  6. Dangerous removal detection — catches rm / rmdir targeting critical system paths (/, ~, /usr) → ASK
  7. ACCEPT_EDITS mode — auto-allows filesystem commands (mkdir, touch, rm, mv, cp, sed) when this mode is active → ALLOW
match_rule() uses prefix-based wildcard matching against the command string:
PatternMatchesDoes not match
npm run:*npm run build, npm run testnpm install
git commit:*git commit -m "fix"git push
rm:*rm file.txt, rm -rf /tmp/xls
generate_suggestions() extracts the command prefix (first two tokens) and proposes a prefix rule. For example, git commit -m "fix bug" produces the suggestion git commit:*. The constructor accepts optional extra entries for the dangerous-path lists:
from agentscope.tool import Bash

bash = Bash(
    additional_dangerous_files=[".secrets"],
    additional_dangerous_directories=[".credentials"],
)

File Tools (Read, Write, Edit)

The file tools enforce a read-before-write rule: Write and Edit require the target file to have been read via Read first. This prevents blind overwrites and ensures the agent always operates on current content.
ToolOperationKey behavior
ReadRead file contentsReturns content with line numbers; supports offset/limit for large files; results cached in agent state
WriteCreate or overwrite a fileFails if the file exists but has not been read first
EditReplace exact strings in a fileFails if old_string is not found or is not unique (unless replace_all=True); requires prior read
check_permissions()Write and Edit share the same permission logic:
  1. Dangerous path protection (bypass-immune) — operations on sensitive files (.bashrc, .env, .ssh/) always trigger ASK, even in BYPASS mode
  2. ACCEPT_EDITS mode — auto-allows operations on files within configured working directories
  3. PASSTHROUGH — falls through to the permission engine for rule matching
Read is read-only and always returns PASSTHROUGH (the engine handles EXPLORE-mode auto-allow). match_rule() — all three tools use fnmatch glob matching against the file_path argument:
PatternMatches
src/**Any file under src/
src/**/*.pyPython files under src/
config.jsonExact file match
generate_suggestions() proposes a glob covering the parent directory. For example, editing /project/src/main.py produces the suggestion src/**.

Create Custom Tool

To create a custom tool, subclass ToolBase, declare its schema, and implement check_permissions and __call__:
from agentscope.tool import ToolBase, ToolChunk
from agentscope.permission import (
    PermissionContext, PermissionDecision, PermissionBehavior,
)
from agentscope.message import TextBlock

class WebSearch(ToolBase):
    name = "WebSearch"
    description = "Search the web for information on a given query."
    input_schema = {
        "type": "object",
        "properties": {
            "query": {
                "type": "string",
                "description": "The search query.",
            },
        },
        "required": ["query"],
    }
    is_concurrency_safe = True
    is_read_only = True

    async def check_permissions(
        self, tool_input: dict, context: PermissionContext,
    ) -> PermissionDecision:
        return PermissionDecision(
            behavior=PermissionBehavior.ALLOW,
            message="Web search is read-only.",
        )

    async def __call__(self, query: str) -> ToolChunk:
        results = await do_search(query)
        return ToolChunk(content=[TextBlock(text=results)])

Wrap Function as Tool

For lightweight cases that don’t justify a full subclass, wrap a plain Python function with the FunctionTool adapter. It auto-extracts the tool name from func.__name__, the description from the function docstring, and the input schema from type hints.
from agentscope.tool import FunctionTool, Toolkit

def get_weather(city: str, unit: str = "celsius") -> str:
    """Get the current weather for a city.

    Args:
        city: The city name to look up.
        unit: Temperature unit, either "celsius" or "fahrenheit".
    """
    return f"The weather in {city} is 22°{unit[0].upper()}"

toolkit = Toolkit(tools=[FunctionTool(get_weather)])
FunctionTool accepts overrides when the auto-extracted defaults are not what you want:
ArgumentTypeDescription
funcCallableThe Python function to wrap
namestr | NoneOverride the tool name (defaults to func.__name__)
descriptionstr | NoneOverride the description (defaults to the docstring)
is_concurrency_safeboolWhether parallel calls are safe (default True)
is_read_onlyboolWhether the function has side effects (default False)
is_state_injectedboolWhether the agent state is injected as _agent_state (default False)
Wrapped functions default to ASK permission behavior — the user must explicitly allow each call. Subclass ToolBase directly when you need custom permission logic.

Define External Execution Tool

An external execution tool delegates its actual execution outside the agent runtime — typically to a human operator or an external system. When the agent calls one, it emits a RequireExternalExecutionEvent and pauses until the result is delivered via ExternalExecutionResultEvent. This pattern underlies the human-in-the-loop workflow, where certain actions require human approval or manual execution. To create an external execution tool, set is_external_tool = True. There is no need to implement __call__:
from agentscope.tool import ToolBase
from agentscope.permission import (
    PermissionContext, PermissionDecision, PermissionBehavior,
)

class HumanApproval(ToolBase):
    name = "HumanApproval"
    description = "Request human approval for a sensitive operation."
    input_schema = {
        "type": "object",
        "properties": {
            "action": {"type": "string", "description": "The action requiring approval."},
            "reason": {"type": "string", "description": "Why this action needs approval."},
        },
        "required": ["action", "reason"],
    }
    is_concurrency_safe = True
    is_read_only = False
    is_external_tool = True

    async def check_permissions(
        self, tool_input: dict, context: PermissionContext,
    ) -> PermissionDecision:
        return PermissionDecision(
            behavior=PermissionBehavior.ALLOW,
            message="External tool dispatch is always allowed.",
        )

MCP

AgentScope integrates with Model Context Protocol (MCP) servers, letting an agent reach any MCP-compatible tool provider. The framework handles protocol negotiation, tool discovery, and result conversion automatically. Two connection modes are supported:
  • Stateful (STDIO or HTTP) — persistent session with explicit connect() / close() lifecycle
  • Stateless (HTTP only) — ephemeral session created per tool call, no lifecycle management needed
MCP tools are namespaced as mcp__{server_name}__{tool_name} to avoid name collisions, and tools annotated with readOnlyHint are auto-allowed by the permission system.

Register MCP Tool

Build one or more MCPClient instances and pass them to Toolkit(mcps=[...]). Stateful clients must be connected before the toolkit is constructed.
from agentscope.mcp import MCPClient, StdioMCPConfig
from agentscope.tool import Toolkit

client = MCPClient(
    name="filesystem",
    is_stateful=True,
    mcp_config=StdioMCPConfig(
        command="mcp-server-filesystem",
        args=["--root", "/my/project"],
    ),
)

await client.connect()

toolkit = Toolkit(mcps=[client])
To expose only a subset of an MCP server’s tools, set enable_tools or disable_tools on the client itself:
client = MCPClient(
    name="search",
    is_stateful=False,
    mcp_config=HttpMCPConfig(url="https://api.search.com/mcp"),
    enable_tools=["web_search", "image_search"],
)
If you need to invoke MCP tools outside a Toolkit, call await client.list_tools() to retrieve a list of MCPTool adapters and use them like any other ToolBase instance.

Skill

Skills are markdown-based instruction sets that extend agent capabilities without writing new tool code. Each skill is a directory containing a SKILL.md file with frontmatter metadata and detailed instructions. Unlike tools, skills are not callable directly. The agent uses the auto-registered Skill viewer tool to read a skill’s instructions, then follows those instructions using its existing tools.

Register Skill

Pass skill sources to the Toolkit constructor through skills_or_loaders. Each entry can be a directory path string, a Skill object, or a SkillLoaderBase subclass:
from agentscope.tool import Toolkit

toolkit = Toolkit(
    skills_or_loaders=["/path/to/skills"],
)

How Skill Works

When a Toolkit is constructed with skills, the registration and lookup flow runs in two phases. At initialization:
  • The toolkit scans every registered skill source and collects each skill’s name, description, and directory.
  • It auto-registers the built-in Skill viewer tool.
  • It composes a system-prompt fragment listing the available skills (name and description only) and instructing the agent to invoke the Skill viewer to read the full content.
At runtime:
  • The agent picks a skill by name and calls the Skill viewer.
  • The viewer reads the corresponding SKILL.md and returns its full markdown.
  • The agent follows those instructions using its already-equipped tools.
Skills are not tools — the agent cannot call a skill directly. It must first use the Skill viewer to read the instructions, then execute the steps described within using its other tools.

Manage Tools Agentically

The built-in meta tool (reset_tools) lets the agent self-manage which tool groups are active at runtime. This keeps its context focused — only tools relevant to the current task are exposed.

Define Tool Group

A ToolGroup is a named bundle of tools, MCP clients, and skills. Pass groups to Toolkit(tool_groups=[...]). The reserved "basic" group is created automatically from the constructor’s top-level tools, mcps, and skills_or_loaders arguments and is always active.
from agentscope.tool import Toolkit, ToolGroup, Bash, Read, Write, Edit

toolkit = Toolkit(
    tools=[Bash(), Read(), Write(), Edit()],
    tool_groups=[
        ToolGroup(
            name="database",
            description="Tools for database operations.",
            instructions="Always wrap mutations in a transaction.",
            tools=[db_query_tool, db_migrate_tool],
        ),
        ToolGroup(
            name="deployment",
            description="Tools for deploying services.",
            instructions="Confirm the target environment before deploying.",
            tools=[deploy_tool, rollback_tool],
        ),
    ],
)
ToolGroup accepts the same tools, mcps, and skills_or_loaders arguments as the toolkit, plus a description shown to the agent in the meta tool schema and an optional instructions string returned when the group is activated.

Use Meta Tool

When at least one non-basic tool group exists, Toolkit auto-registers reset_tools and exposes its schema to the agent. Each non-basic group becomes a boolean field on that schema, and the agent calls the meta tool with the desired final state. The behavior at runtime:
  • Tools in the "basic" group are always exposed; they are never affected by the meta tool.
  • Each call to reset_tools overwrites the activated set — any non-basic group not explicitly set to True becomes inactive, regardless of its previous state.
  • For each group transitioning to active, its instructions (when provided) are concatenated and returned in the meta tool’s response, telling the agent how to use that group properly.
  • Tools from inactive groups are hidden from the agent’s tool schema, freeing context space for the active set.
The meta tool input represents the final state of all groups, not incremental changes. Any group not explicitly set to True will be deactivated, regardless of its previous state.

Further Reading

Agent

How agents orchestrate tool calls in the ReAct loop

Permission System

Fine-grained control over which tools can execute and when

Middleware

Intercept and transform tool calls with onion-style middleware

Human-in-the-Loop

External execution tools and human approval workflows