Tools¶
A tool is a Python function the model can call.
Define a tool¶
from pathlib import Path
from alpineagents import tool
@tool
def read_file(path: str, max_lines: int = 200) -> str:
"""Read a text file
Args:
path: Path relative to the repository root
max_lines: How many lines to return
"""
file = Path(path)
if not file.exists():
return f"No such file: {path}"
return "\n".join(file.read_text().splitlines()[:max_lines])
The model sees the tool built from the function:
| From the function | The model sees |
|---|---|
| Function name | Tool name: read_file |
| First paragraph of the docstring | Tool description |
| Type hints | Input schema (JSON Schema) |
Args: section of the docstring |
Description of each parameter |
| Default values | Optional parameters |
read_file.spec shows exactly what the model sees.
- Every parameter needs a type hint. Supported:
str,int,float,bool,Literal[...],Enum,list[T],dict[str, T],T | None, dataclass,TypedDict, Pydantic model. On Python 3.11, importTypedDictfromtyping_extensions. - Options:
@tool(name="...", description="...", parallel=False). - A mistake in the function raises
TypeErrorwhen@toolruns, before any model request.
Return values¶
| The tool returns | The model gets |
|---|---|
str |
The string |
None |
(done) |
| Anything else | JSON |
A value that cannot become JSON raises TypeError, which stops the run like any exception from a tool.
When a call goes wrong¶
| Situation | What happens | The run |
|---|---|---|
| The model sends invalid arguments or an unknown tool name | The model gets (input error: ...) as the result |
Continues |
| The tool returns an error message as a string | The model gets the string | Continues |
| The tool raises an exception | The exception propagates out of use_tools and run |
Stops |
Return a string for failures the model can fix, such as a missing file or a failing command. Raise for failures that should stop the run.
Tools that use the State¶
A parameter typed State is hidden from the model and receives the current State:
from alpineagents import State, tool
@tool
def submit(summary: str, state: State) -> None:
"""Submit the finished work"""
state.finish(summary)
Tools on an object¶
@tool works on methods. Pass the object to give the Agent every @tool method, or pass one method:
from pathlib import Path
from alpineagents import Agent, tool
class Workspace:
def __init__(self, root: str):
self.root = Path(root)
@tool
def read_file(self, path: str) -> str:
"""Read a file in the workspace"""
return (self.root / path).read_text()
@tool
def list_files(self) -> list[str]:
"""List the files in the workspace"""
return sorted(p.name for p in self.root.iterdir())
workspace = Workspace("my-repo")
agent = Agent(model="claude-sonnet-5", tools=[workspace])
reader = Agent(model="claude-sonnet-5", tools=[workspace.read_file])
Use an object when tools share settings, such as a root folder or a client.
Several calls in one reply¶
A reply can ask for several tool calls. use_tools runs them like this:
- Tools with
parallel=True(the default) run at the same time, on worker threads. - Then tools with
parallel=Falserun one at a time, in the order the model asked. - The results go into the context in the order the model asked.
Use parallel=False for tools that must not overlap, such as two writes to the same file.
MCP servers¶
MCP servers go in tools= too. See MCP servers.