3tears Agent Tools
Tool framework for LLM agents. Provides tool routing, execution, context management, MCP integration, and a set of builtin tools.
Part of the 3tears framework.
ToolServer baseline audit
ToolServer.handle_call stamps every dispatch with a unified AuditEvent envelope (event_type='tool.call') via threetears.agent.audit.publish_audit. The baseline emission fires in a finally block so success, failure (tool returned success=False), and error (tool raised) outcomes all produce a row. Identity axes carry from the active ToolCallScope (actor_user_id, calling_agent_id, owner_agent_id, customer_id, correlation_id); resource_namespace_id / resource_namespace_type stay None at the baseline layer since the tool resolves its target inside execute. Per-tool additive events (e.g. workspace.fs_write) still publish via publish_audit and ride alongside the baseline row under the same correlation_id. The (correlation_id, event_type) partial unique index on platform_audit.audit_events keeps them distinct. Emission is fire-and-forget: NATS publish failures log WARN and never taint the tool's response.
Tool-as-namespace emission
Tool namespace materialization is platform-owned. ToolServer.publish_registration writes the RegistrationManifest (carrying pod_id + tools + the owner_agent_id / customer_id envelope fields), and a platform-side namespace emitter subscribes to {ns}.tools.register and upserts one namespaces row of type tool per tool. This is the sole writer in the platform.
Agent-spun ToolServers stamp agent_id + customer_id on the RegistrationManifest so the emitter lands rows with the right owner scope; platform-built-in pods (admin tool server, datasource tool pod) leave both None and the row lands with NULL owner columns (admitted under the widened namespaces_row_scope_customer_ck carve-out for tool type alongside system / model).
The canonical name shape is tools.<sanitized-mcp>.<sanitized-version> (per build_namespace_name); metadata carries the pre-sanitized natural-identity fields mcp_name / mcp_version / pod_id so downstream pattern matching (platform access materializer agent.yaml access.tools patterns + registry authorizer canonical-name lookup) does not need to reverse the sanitization rules. Deterministic uuid5 derived from (mcp_name, version, owner_agent_id_hex) keeps concurrent emitters race-safe via ON CONFLICT (id) DO UPDATE.
ToolServer holds no NamespaceCollection and has no constructor parameter to take one: register_tool / deregister_tool publish the manifest and nothing else. The pod-side emitter that once wrote and deleted these rows is deleted -- its write could not land (the agent's L3 proxy resolves platform-scoped writes to the per-agent agent_<hex> schema, which has no namespaces table) and its delete raised on every call (it passed a bare UUID to a Collection keyed on the composite (row_scope, namespace_id)). packages/agent/tools/tests/enforcement/test_no_agent_side_namespace_writes.py fails a build that brings any of it back.
Installation
pip install 3tears-agent-tools
# Optional extras for builtin tools
pip install "3tears-agent-tools[calculator]" # simpleeval
pip install "3tears-agent-tools[units]" # pint
pip install "3tears-agent-tools[fetch]" # trafilatura
pip install "3tears-agent-tools[document]" # PyMuPDF, python-docx, openpyxl
pip install "3tears-agent-tools[all]" # everything
Components
ToolRouter
Routes user messages to the appropriate tool using a lightweight LLM call. Includes recall-intent detection to avoid re-invoking tools when users ask about previous results.
from threetears.agent.tools import ToolRouter, is_recall_intent
# Quick check -- no LLM call needed
if is_recall_intent("show me what the calculator said"):
# User wants to recall, not invoke
# Full routing with LLM
router = ToolRouter(chat_model)
decision = await router.route(user_message, tool_descriptions)
# decision.tool_name, decision.reasoning
ToolExecutor
Invokes a tool-LLM: sends the user message to a secondary model configured for a specific task.
from threetears.agent.tools import ToolExecutor
executor = ToolExecutor()
result = await executor.invoke_with_tools(
chat_model=tool_model,
user_message="What is 42 * 17?",
tools=[calculator_tool],
tool_name="calculator",
)
# result.content, result.tool_calls
ToolContextManager
Tracks tool invocations and results across a conversation for recall support.
from threetears.agent.tools import ToolContextManager
ctx = ToolContextManager()
await ctx.record_invocation("calculator", "42 * 17", "714")
await ctx.get_recall_context("calculator") # Returns formatted recall string
McpClient
MCP (Model Context Protocol) integration for connecting to external tool servers.
from threetears.agent.tools import McpClient
async with McpClient(server_config) as client:
tools = await client.list_tools()
result = await client.invoke_tool("tool_name", {"param": "value"})
Builtin Tools
Register all builtin tools at once:
from threetears.agent.tools import register_builtins, ToolRegistry
registry = ToolRegistry()
register_builtins(registry)
# Registers: calculator, unit_converter, dice_roller, date_time,
# random_number, web_fetch, text_transform, parse_document
Todo Tools
Todo list management behind a storage protocol:
from threetears.agent.tools import TodoStorage, load_todo_tools_from_storage
class MyTodoStorage(TodoStorage):
async def add(self, conv_id, user_id, title, list_name, msg_id) -> dict: ...
async def list_all(self, conv_id) -> list[dict]: ...
# ... other methods
tools = load_todo_tools_from_storage(my_storage, snapshot_callback=on_snapshot)
Protocols
For media-related capabilities, implement these protocols:
from threetears.agent.tools import (
ImageGenerationBackend,
MediaStorage,
VisionProvider,
TranscriptionProvider,
)
Document Parsing
Parse PDF, DOCX, XLSX, and plain text with optional OCR:
from threetears.agent.tools import parse_document, OcrConfig
result = await parse_document(
file_bytes=data,
filename="report.pdf",
ocr_config=OcrConfig(enabled=True),
)
# result.sections -- list of DocumentSection with title, content, page numbers
Release files for 3tears-agent-tools 0.51.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| 3tears_agent_tools-0.51.0.tar.gz | 457.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 3tears_agent_tools-0.51.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 752.8 kB
Release files / 3tears_agent_tools-0.51.0.tar.gz
| Download URL | 3tears_agent_tools-0.51.0.tar.gz |
|---|---|
| Size | 457.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
54d370dfa155b1edf8909cb0eab701c106fae23bb6c8cbb19fb815ac2250c201
|
|
BLAKE2b-256 checksum How to use checksums |
fe7ad2a732eca25cdbbc07fe041c2369c49ba6bc5760102d75ac8bc5ac4460ae
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency logRelease files / 3tears_agent_tools-0.51.0-py3-none-any.whl
| Download URL | 3tears_agent_tools-0.51.0-py3-none-any.whl |
|---|---|
| Size | 295.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4086c5c15efece17717d092ed49e9d2fc920d183d049c204ac0747d67973f08f
|
|
BLAKE2b-256 checksum How to use checksums |
16b18addd69ffd53e2e6404ce6170435eb217d406286f5d98e12837f18ae3033
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency log