Bases: Toolkit
Client-side toolkit for agentskills.io-style local skills.
Packs a three-step progressive-disclosure pattern as a single toolkit so any provider can ship local skills without extra wiring:
list_skills() — lightweight catalog (name + description). load_skill(name) — full SKILL.md instructions on demand. run_skill_script(name, script, args) — execute a script from the skill's scripts/ directory.
Default runtime scans ./.agents/skills and ~/.agents/skills::
Custom install directory::
SkillsToolkit(runtime=LocalRuntime("./skills"))
Extra read-only search paths::
SkillsToolkit(runtime=LocalRuntime("./skills", extra_paths=["./shared-skills"]))
Pick individual tools instead of the full toolkit::
skills = SkillsToolkit()
agent = Agent(
"a",
config=config,
tools=[skills.list_skills(), skills.load_skill()],
)
Source code in autogen/beta/tools/skills/local_skills/toolkit.py
| def __init__(
self,
runtime: SkillRuntime | str | os.PathLike[str] | None = None,
*,
middleware: Iterable[ToolMiddleware] = (),
) -> None:
if runtime is not None:
self._runtime: SkillRuntime = LocalRuntime.ensure_runtime(runtime)
else:
self._runtime = LocalRuntime()
super().__init__(
self.list_skills(),
self.load_skill(),
self.run_skill_script(),
name="local_skills_toolkit",
middleware=middleware,
)
|
The underlying SkillRuntime used to discover and load skills.
list_skills(*, name='list_skills', description='List available local skills with name and short description.', middleware=())
Source code in autogen/beta/tools/skills/local_skills/toolkit.py
| def list_skills(
self,
*,
name: str = "list_skills",
description: str = "List available local skills with name and short description.",
middleware: Iterable[ToolMiddleware] = (),
) -> FunctionTool:
runtime = self._runtime
@tool(name=name, description=description, middleware=middleware)
def _list_skills() -> list[dict[str, str]]:
return [{"name": m.name, "description": m.description} for m in runtime.discover()]
return _list_skills
|
load_skill(*, name='load_skill', description='Load the full SKILL.md content for a specific skill.', middleware=())
Source code in autogen/beta/tools/skills/local_skills/toolkit.py
| def load_skill(
self,
*,
name: str = "load_skill",
description: str = "Load the full SKILL.md content for a specific skill.",
middleware: Iterable[ToolMiddleware] = (),
) -> FunctionTool:
runtime = self._runtime
@tool(name=name, description=description, middleware=middleware)
def _load_skill(
name: Annotated[str, Field(description="Skill name returned by list_skills.")],
) -> str:
return runtime.load(name)
return _load_skill
|
run_skill_script(*, name='run_skill_script', description="Run a script from a skill's scripts directory. Only .py and .sh scripts are supported.", middleware=())
Source code in autogen/beta/tools/skills/local_skills/toolkit.py
| def run_skill_script(
self,
*,
name: str = "run_skill_script",
description: str = "Run a script from a skill's scripts directory. Only .py and .sh scripts are supported.",
middleware: Iterable[ToolMiddleware] = (),
) -> FunctionTool:
runtime = self._runtime
@tool(name=name, description=description, middleware=middleware)
def _run_skill_script(
name: Annotated[
str,
Field(description="Skill name returned by list_skills."),
],
script: Annotated[
str,
Field(description="Script filename inside scripts/, for example scaffold.py or build.sh."),
],
args: Annotated[
list[str] | None,
Field(description="Optional script arguments passed as positional parameters."),
] = None,
) -> str:
skill_dir = runtime.get_path(name)
scripts_dir = skill_dir / "scripts"
script_path = Path(script)
if script_path.name != script:
raise ValueError("script must be a filename inside the skill scripts directory")
resolved_script = (scripts_dir / script_path.name).resolve()
if not resolved_script.is_file() or not resolved_script.is_relative_to(scripts_dir.resolve()):
raise FileNotFoundError(f"script {script!r} not found in {scripts_dir}")
first_line = resolved_script.read_text(encoding="utf-8", errors="replace").split("\n", 1)[0]
has_shebang = first_line.startswith("#!")
if has_shebang:
resolved_script.chmod(resolved_script.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
command = [f"./{resolved_script.name}"]
elif resolved_script.suffix.lower() == ".py":
command = ["python3", f"./{resolved_script.name}"]
elif resolved_script.suffix.lower() == ".sh":
command = ["sh", f"./{resolved_script.name}"]
else:
resolved_script.chmod(resolved_script.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
command = [f"./{resolved_script.name}"]
if args:
command.extend(args)
env = runtime.shell(scripts_dir)
return env.run(shlex.join(command))
return _run_skill_script
|
Source code in autogen/beta/tools/final/toolkit.py
| def set_provider(self, provider: Provider) -> None:
for t in self.tools:
t.set_provider(provider)
|
Source code in autogen/beta/tools/final/toolkit.py
| async def schemas(self, context: "Context") -> Iterable[ToolSchema]:
schemas: list[ToolSchema] = []
for t in self.tools:
schemas.extend(await t.schemas(context))
return schemas
|
register(stack, context, *, middleware=())
Source code in autogen/beta/tools/final/toolkit.py
| def register(
self,
stack: "ExitStack | AsyncExitStack",
context: "Context",
*,
middleware: Iterable["BaseMiddleware"] = (),
) -> None:
for t in self.tools:
t.register(stack, context, middleware=middleware)
|
tool(function: Callable[..., Any], *, name: str | None = None, description: str | None = None, schema: FunctionParameters | None = None, sync_to_thread: bool = True, middleware: Iterable[ToolMiddleware] = ()) -> FunctionTool
tool(function: None = None, *, name: str | None = None, description: str | None = None, schema: FunctionParameters | None = None, sync_to_thread: bool = True, middleware: Iterable[ToolMiddleware] = ()) -> Callable[[Callable[..., Any]], FunctionTool]
tool(function=None, *, name=None, description=None, schema=None, sync_to_thread=True, middleware=())
Source code in autogen/beta/tools/final/toolkit.py
| def tool(
self,
function: Callable[..., Any] | None = None,
*,
name: str | None = None,
description: str | None = None,
schema: FunctionParameters | None = None,
sync_to_thread: bool = True,
middleware: Iterable[ToolMiddleware] = (),
) -> FunctionTool | Callable[[Callable[..., Any]], FunctionTool]:
def make_tool(f: Callable[..., Any]) -> FunctionTool:
t = tool(
f,
name=name,
description=description,
schema=schema,
sync_to_thread=sync_to_thread,
middleware=middleware,
)
self._add_tool(t)
return t
if function:
return make_tool(function)
return make_tool
|