aimu.tools¶
In-process @tool decorator and cross-process MCPClient.
Decorator¶
aimu.tools.tool ¶
Mark a Python function as an AIMU tool.
Inspects the signature and docstring at decoration time and attaches an OpenAI-format
tool spec to func.__tool_spec__. The function itself is unchanged and remains
directly callable.
Each parameter must either have a type hint or a default value. Variadic parameters
(*args / **kwargs) are not supported; declare each argument explicitly.
Supported parameter types: str, int, float, bool, list, dict,
plus Optional[T] and T | None (which unwrap to the inner type).
A tool may be plain (def fn() -> T), async (async def fn() -> T), a generator
(def fn(): yield ...; return T), or an async generator (async def fn(): yield ...).
Generator and async-generator tools stream :class:~aimu.models.StreamChunk objects
during execution; the agent forwards each yielded chunk through its own stream and
treats the final yielded TOOL_CALLING chunk's content["response"] as the
canonical tool result. The decorator sets discriminator attributes:
func.__tool_is_async__: True forasync deforasync def+yield.func.__tool_is_streaming__: True for generator functions (sync or async).
Usage::
import aimu
@aimu.tool
def letter_counter(word: str, letter: str) -> int:
"""Count occurrences of a letter in a word."""
return word.lower().count(letter.lower())
agent = Agent(client, tools=[letter_counter])
aimu.tools.ToolSignatureError ¶
Bases: TypeError
Raised by @tool when a function signature can't be converted to a tool spec.
Argument validation¶
aimu.tools.coerce_tool_arguments ¶
Validate and lax-coerce model-supplied tool arguments against fn's type hints.
Returns a new dict of model-facing arguments coerced to their declared types
("5" -> 5, "true" -> True). Raises :class:ToolArgumentError with a
single self-contained message when arguments are unknown, a required one is missing,
or a value can't be coerced.
Callables not built by @tool (e.g. MCP as_tools() wrappers) carry no
__tool_param_adapters__; their arguments pass through unchanged (the MCP server
validates them).
aimu.tools.ToolArgumentError ¶
Bases: ValueError
Raised when model-supplied tool-call arguments fail validation/coercion.
Caught at dispatch and surfaced to the model as a tool result so it can self-correct.
MCP client¶
aimu.tools.MCPClient ¶
MCPClient(config: Optional[dict] = None, server: Optional[FastMCP] = None, file: Optional[str] = None)
Synchronous wrapper around an async FastMCP Client.
Uses anyio's start_blocking_portal() to run the FastMCP Client in a background
thread with a properly initialized anyio event loop.
Pass exactly one of config, server, or file. Connection errors are
re-raised as :class:MCPConnectionError with the original exception chained.
ping ¶
Verify the connection is alive by listing tools. Returns the tool list.
Raises :class:MCPConnectionError if the connection has been closed or the
server is unreachable.
as_tools ¶
Return this server's tools as @tool-style callables.
Each callable closes over this client, invokes :meth:call_tool cross-process,
and returns the result's text content as a string. The callables carry
__tool_spec__ (OpenAI format), __tool_is_async__ = False, and
__tool_is_streaming__ = False, so they drop straight into client.tools or
Agent(tools=...) and dispatch through the same path as @tool functions,
no model_client.mcp_client reference needed::
mcp = MCPClient(server=my_server)
client.tools = builtin.web + mcp.as_tools()
The tool list is a snapshot taken now (one list_tools() round-trip); call
as_tools() again to pick up server-side changes. Keep a reference to this
MCPClient (or to the returned callables, which hold one) for the lifetime of
the connection.
aimu.tools.MCPConnectionError ¶
Bases: RuntimeError
Raised when an :class:MCPClient fails to establish or use a connection.
Built-in tools¶
The aimu.tools.builtin module ships ready-made @tool functions grouped by domain:
| Group | Tools |
|---|---|
builtin.web |
get_weather, get_webpage, web_search, wikipedia |
builtin.fs |
list_directory, read_file |
builtin.compute |
calculate |
builtin.misc |
echo, get_current_date_and_time |
builtin.ALL_TOOLS |
All of the above |
aimu.tools.builtin.get_current_date_and_time ¶
Returns the current date and time.
aimu.tools.builtin.get_weather ¶
Returns the current weather for a given location.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
location
|
str
|
City name or coordinates (e.g. "London", "48.8566,2.3522"). |
required |
aimu.tools.builtin.calculate ¶
Evaluates a simple arithmetic expression and returns the result.
aimu.tools.builtin.get_webpage ¶
Fetches a web page and returns its visible text content with HTML stripped.
When the page exposes a publication timestamp (in tags, JSON-LD, or a
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The URL of the page to retrieve. |
required |
aimu.tools.builtin.web_search ¶
Search the web using a SearXNG instance and return the top results.
Each result includes its publication date when the search engine reports one (shown as a "Published:" line), useful for judging how recent an article is.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query
|
str
|
The search query string. |
required |
num_results
|
int
|
Number of results to return (default 5). |
5
|
time_range
|
str
|
Optional recency filter, one of "day", "week", "month", or "year". Use "day" to restrict results to roughly the last 24 hours (best for fresh news). |
''
|
categories
|
str
|
Optional SearXNG category filter, e.g. "news" to restrict to news engines (which report publication dates far more reliably than general web engines). Comma-separated for multiple, e.g. "news,science". |
''
|
Set SEARXNG_BASE_URL env var to point to your SearXNG instance (or a .env file) (default: http://localhost:8080).
aimu.tools.builtin.wikipedia ¶
Fetches a Wikipedia article summary for the given query.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query
|
str
|
Article title or search phrase (e.g. "Albert Einstein", "general relativity"). |
required |
aimu.tools.builtin.list_directory ¶
Lists files and subdirectories at the given path.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Directory path to list. |
required |
aimu.tools.builtin.read_file ¶
Reads a local file and returns its contents, capped at max_lines lines.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Path to the file to read. |
required |
max_lines
|
int
|
Maximum number of lines to return (default 200). |
200
|
Tool factories¶
Bind a tool to a specific resource (a memory store, a knowledge base) instead of a process-wide singleton.
aimu.tools.builtin.make_memory_tools ¶
Build store_memory, search_memories, and list_memories tools bound to store.
store may be any :class:aimu.memory.MemoryStore implementation:
:class:~aimu.memory.SemanticMemoryStore (ChromaDB vector search),
:class:~aimu.memory.DocumentStore (path-keyed), or a custom subclass.
Unlike the image/audio/speech tools, there is no env-var singleton for memory because the choice of store (ephemeral vs. persistent, which persist_path) is meaningful and should be explicit. Construct the store, pass it here, and add the returned list to the agent::
store = SemanticMemoryStore(persist_path="./.memory")
agent = Agent(client, tools=make_memory_tools(store) + builtin.web)
For cross-process or multi-agent memory, use the FastMCP servers in
aimu.memory.mcp / aimu.memory.document_mcp instead.
aimu.tools.builtin.make_retrieval_tool ¶
Build a retrieve_context tool bound to store for retrieval-augmented agents.
store may be any :class:aimu.memory.MemoryStore (typically a
:class:~aimu.memory.SemanticMemoryStore populated via :func:aimu.rag.ingest).
The tool runs :func:aimu.rag.retrieve and returns the joined context, letting an
agent fetch relevant background on demand::
from aimu.rag import ingest
store = SemanticMemoryStore()
ingest(store, my_documents)
agent = Agent(client, tools=[make_retrieval_tool(store)])
Like :func:make_memory_tools, there is no env-var singleton; the store (and what was
ingested into it) is a meaningful, explicit choice.