Tools Overview¶
This page gives you the full picture of what tools exist, how to build them, and how to wire them into an agent. For the full operation-by- operation behavior of each tool, follow the link in the table.
The five tools¶
| Tool | LangChain tool name | Purpose | Factory function | Doc page |
|---|---|---|---|---|
| File Tool | file_tool |
Read, write, edit, copy, move, delete individual files | make_file_tool(ctx=None) |
File Tool |
| Directory Tool | directory_tool |
List (tree view), create, copy, move, delete directories | make_directory_tool(ctx=None) |
Directory Tool |
| Search Tool | file_search_tool |
Find files by name, or search file contents | make_search_tool(ctx=None) |
Search Tool |
| Process Tool | process_tool |
Run a shell command | make_process_tool(ctx=None, shell=True) |
Process Tool |
| Rsync Tool | rsync_tool |
Sync a source directory to a destination | make_rsync_tool(ctx=None) |
Rsync Tool |
Every factory function takes an optional SecurityContext and returns a
langchain_core.tools.StructuredTool — a normal LangChain tool you can
call directly, pass to an agent, or bind to a model.
Building tools one at a time¶
from langchain_mero_tools import (
make_file_tool,
make_directory_tool,
make_search_tool,
make_process_tool,
make_rsync_tool,
SecurityContext,
PathEntry,
Permission,
)
ctx = SecurityContext(
paths=[
PathEntry(
path="./workspace",
slug="root",
allowed_permission=Permission.READ | Permission.WRITE,
),
],
)
file_tool = make_file_tool(ctx)
directory_tool = make_directory_tool(ctx)
search_tool = make_search_tool(ctx)
process_tool = make_process_tool(ctx, shell=False) # see process_tool docs on shell modes
rsync_tool = make_rsync_tool(ctx)
Building all of them at once with get_tools()¶
For the common case — build the whole toolkit against one shared context —
use the get_tools() convenience factory instead:
from langchain_mero_tools import get_tools, SecurityContext, PathEntry, Permission
ctx = SecurityContext(
paths=[PathEntry(path="./workspace", slug="root", allowed_permission=Permission.READ)],
)
tools = get_tools(ctx)
# [file_tool, directory_tool, file_search_tool, process_tool, rsync_tool]
get_tools() signature:
def get_tools(
ctx: SecurityContext | None = None,
*,
include: list[str] | None = None,
process_shell: bool = True,
) -> list[StructuredTool]:
...
ctx— sharedSecurityContextfor all tools.Nonemeans unrestricted.include— subset of{"file", "directory", "search", "process", "rsync"}to build. Defaults to all five. Use this to keep an agent's toolset minimal — e.g. a read-only research agent might only needinclude=["file", "search"].process_shell— forwarded tomake_process_tool(ctx, shell=process_shell). Defaults toTruefor backward compatibility; passFalsefor the safer no-shell execution mode. See Process Tool.
# Only file + search, process tool in the safer no-shell mode
tools = get_tools(ctx, include=["file", "search", "process"], process_shell=False)
Invoking a tool directly¶
All tools follow LangChain's standard StructuredTool interface — call
.invoke(...) with a dict matching the tool's args_schema:
Every tool returns a plain string, always — never raises for expected
failure modes (bad paths, denied permissions, missing files). This is
intentional: an LLM agent can read a string like "Denied: Path 'x' is
outside the allowed scope [...]" and react (e.g. try a different path,
ask the user, or give up gracefully) instead of the whole run crashing on
an unhandled exception. See Error Handling.
Wiring into an agent¶
Because every tool is a standard StructuredTool, it plugs into anything
that accepts a list of LangChain tools:
from langchain.chat_models import init_chat_model
from langgraph.prebuilt import create_react_agent
from langchain_mero_tools import get_tools, SecurityContext, PathEntry, Permission
ctx = SecurityContext(
paths=[
PathEntry(
path="./workspace",
slug="root",
allowed_permission=Permission.READ | Permission.WRITE,
),
],
)
tools = get_tools(ctx)
model = init_chat_model("anthropic:claude-sonnet-4-5")
agent = create_react_agent(model, tools)
Or bind directly to a chat model without the prebuilt agent wrapper:
Extra features across the whole toolkit¶
These aren't tied to one specific tool — they're properties of the package as a whole:
- Zero required system dependencies.
file_search_toolandrsync_tooleach have a pure-Python fallback and use a faster external binary automatically if present — no setup required either way. - Real global result caps.
file_search_tool'smax_resultsis enforced by streaming subprocess output and killing the process the moment the cap is hit — not just slicing a list after an external tool has already scanned/emitted far more than needed. See Search Tool. - Symlink/traversal-safe path resolution. Every path is resolved
(
Path.resolve()) before being checked against thePathEntrymount table, so../../etc/passwd-style escapes can't slip through, and an unmatched absolute path is rejected outright rather than silently remapped inside the sandbox. - Explicit command-pattern matching.
allowed_commands/denied_commandsentries are never "guessed" as regex vs. glob — see Security & Sandboxing. - Output truncation.
process_toolcaps stdout/stderr at 20,000 chars each so a chatty command can't blow up the agent's context window. - Composable, pluggable approval. Four backends ship out of the box,
chainable with
ChainedApproval, and writing a custom one is a single method. See Approval Workflows. - Manager/worker delegation. A manager agent can auto-approve worker requests that fall within scope it already holds, without escalating every action to a human. See Manager/Worker Delegation.
- A stable extension point (
guard()). Adding your own tool on top of the same security model takes a handful of lines. See Building Custom Tools.
Next steps¶
Pick a tool for the full operation reference: File,
Directory, Search,
Process, Rsync — or read
Security & Sandboxing for the complete
SecurityContext reference.