Skip to main content

Tool framework for LLM agents -- routing, execution, and builtin tools

Project description

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 platform.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.

The ToolServer.register_tool / deregister_tool helpers still emit through an injected namespace_collection for callers that wire one explicitly, but in production deployments the platform-side emitter is the source of truth and the in-process emission is redundant.

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

3tears_agent_tools-0.19.4.tar.gz (310.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

3tears_agent_tools-0.19.4-py3-none-any.whl (223.1 kB view details)

Uploaded Python 3

File details

Details for the file 3tears_agent_tools-0.19.4.tar.gz.

File metadata

  • Download URL: 3tears_agent_tools-0.19.4.tar.gz
  • Upload date:
  • Size: 310.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for 3tears_agent_tools-0.19.4.tar.gz
Algorithm Hash digest
SHA256 58e57d2ec93cc06b994da357c81b7a914e5a3313abb2fc57af2084deabf1f876
MD5 b148dec7c5b6061a95ed8e8f2a0e88aa
BLAKE2b-256 738d67b7231f94ea2d8bf40099b7d1028c9dd722cd2e6c49bd2c4389bfdb8be3

See more details on using hashes here.

Provenance

The following attestation bundles were made for 3tears_agent_tools-0.19.4.tar.gz:

Publisher: release.yml on pacepace/3tears

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file 3tears_agent_tools-0.19.4-py3-none-any.whl.

File metadata

File hashes

Hashes for 3tears_agent_tools-0.19.4-py3-none-any.whl
Algorithm Hash digest
SHA256 4946266e1fdd2e11ee2ba4025702c71ef9b3b5486783e6bb0c0303584673f877
MD5 edfa1c0cbac6332c02dff4bddd3df947
BLAKE2b-256 5a89dc1a2b96173857967a409c51ef5ccdc8d1434d7ae7ca8469cb57f60e5848

See more details on using hashes here.

Provenance

The following attestation bundles were made for 3tears_agent_tools-0.19.4-py3-none-any.whl:

Publisher: release.yml on pacepace/3tears

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page