Skip to main content

ragleap-tools

Standalone, dependency-light tool implementations for LLM tool-calling. Exposes OpenAI/Gemini-style function-calling schemas.

pip install ragleap-tools

What this is (and isn't)

ragleap-tools provides Tool objects - a name, a description, a JSON Schema for parameters, and a safe handler function. It does not own a tool-calling execution loop (deciding when to call a tool, running it, feeding the result back to the model) - that's ragleap-agents' job, per the project roadmap's own split. Wire these tools into your own tool-calling code, or into ragleap-agents once that ships.

Quickstart

from ragleap_tools import STATELESS_TOOLS, CALCULATOR_TOOL

# Give these to your LLM provider's tools= parameter:
openai_tools = [t.to_openai_schema() for t in STATELESS_TOOLS]
gemini_tools = [t.to_gemini_schema() for t in STATELESS_TOOLS]

# When the model calls one, invoke the handler yourself:
result = CALCULATOR_TOOL.call(expression="2 + 2 * sqrt(16)")
print(result.success, result.result)  # True 10.0

The 12 stateless tools

No configuration needed - import and use directly.

  • CALCULATOR_TOOL - safe arithmetic (AST-based whitelist, never eval())
  • CURRENT_DATETIME_TOOL, ADD_TO_DATE_TOOL, DATE_DIFFERENCE_TOOL - date/time math
  • CONVERT_LENGTH_TOOL, CONVERT_WEIGHT_TOOL, CONVERT_TEMPERATURE_TOOL - unit conversion
  • PARSE_JSON_TOOL, PARSE_CSV_TOOL - structured data parsing
  • REGEX_EXTRACT_TOOL, WORD_COUNT_TOOL, TEXT_CASE_TRANSFORM_TOOL - text utilities

File operations (sandboxed, needs configuration)

from ragleap_tools import FileOpsConfig, make_file_tools

config = FileOpsConfig(root_dir="/path/to/a/safe/directory")
read_tool, write_tool, list_tool = make_file_tools(config)

Every operation is confined to root_dir - both ../ path traversal and symlink-based escapes are rejected (verified via real security tests, not just documented), not just naive string-prefix checking. There is no unsandboxed mode.

Document ingestion and search (optional, needs ragleap-rag)

pip install ragleap-tools[ingest]
from ragleap import RagLeap, ProviderConfig, EmbeddingConfig
from ragleap_tools import IngestConfig, make_ingest_tool, SearchConfig, make_search_tool

rag = RagLeap(database_url="...", primary=ProviderConfig(...), embedder=EmbeddingConfig(...))
ingest_tool = make_ingest_tool(IngestConfig(rag=rag))
search_tool = make_search_tool(SearchConfig(rag=rag))

ingest_document wraps ragleap-rag's already-tested ingest_text() - no new ingestion logic, just a tool schema on top of the real 28-format-capable pipeline. As of v0.1.1, it stores the filename as metadata ({"filename": filename}), enabling the per-document search below - v0.1.0 did not pass any metadata, which silently made per-document filtering impossible.

search_documents wraps ragleap-rag's already-tested retrieve() for hybrid vector+keyword search over previously ingested documents. Chunk dicts are returned unmodified - this tool doesn't assume ragleap-rag's exact field set. Pass an optional filename= to scope the search to a single document previously ingested via ingest_document:

result = search_tool.call(query="what was the Q3 revenue?", filename="q3-report.pdf")

ragleap-rag owns the actual ingestion and retrieval logic; these are thin adapters, same pattern ragleap-graph uses for its own optional ragleap-rag dependency.

Web search (BYOK, no extra dependencies)

from ragleap_tools import WebSearchConfig, TavilySearchProvider, make_web_search_tool

provider = TavilySearchProvider(api_key="...")  # or SerperSearchProvider(api_key="...")
search_tool = make_web_search_tool(WebSearchConfig(provider=provider))

result = search_tool.call(query="latest pgvector release", num_results=5)
# result.result == {"results": [{"title": ..., "url": ..., "snippet": ...}, ...], "count": 5}

Bring your own key: you construct the provider you want with your own api_key. There is no default provider and no environment-variable fallback. Uses only the standard library (urllib.request), so ragleap-tools still has zero required dependencies. SearchProvider is a small abstract class - implement search(query, num_results) to plug in any other search engine.

num_results is chosen by the model and costs your API quota, so it is clamped to 1-20.

Honest limitations: request shapes for both reference providers were checked against their current public docs, but neither has been called against a live account - treat them as best-effort until confirmed by someone with a real key. Results are text from arbitrary third-party pages, so treat them as untrusted input: this tool does not screen them for prompt injection. There is no caching, rate limiting or deduplication.

GitHub repository search (BYOK-optional, no extra dependencies)

from ragleap_tools import GitHubSearchConfig, make_github_search_tool

tool = make_github_search_tool(GitHubSearchConfig())  # token optional
# or: GitHubSearchConfig(token="...") for a higher rate limit

result = tool.call(query="language:python topic:llm", num_results=5, sort="stars")
# result.result == {"results": [{"full_name": ..., "url": ..., "description": ..., "stars": ..., "language": ...}, ...], "count": 5}

Works without a token, at GitHub's lower unauthenticated limit for the search resource (a live /rate_limit check on 2026-10-01 showed 10 for search, versus 60 for GitHub's core API; check /rate_limit for your own) - pass token= for a higher limit. No environment-variable fallback: if you want a token used, you pass it. Supports GitHub's real search qualifiers in the query string (language:, stars:, topic:, etc.), same as GitHub's own search UI. Scoped to repository search only, not code or issue search. Standard library only (urllib.request) - no new dependency.

Image description (BYOK, no extra dependencies)

from ragleap_tools import (
    FileOpsConfig, GeminiVisionProvider, VisionConfig, make_vision_tool,
)

provider = GeminiVisionProvider(api_key="...", model="...")  # you choose the model
tool = make_vision_tool(VisionConfig(
    provider=provider,
    sandbox=FileOpsConfig(root_dir="/path/to/images"),
))
result = tool.call(path="chart.png", prompt="What does this chart show?")
# result.result == {"description": "..."}

api_key and model are both required - no environment-variable fallback, no default provider, no default model. AnthropicVisionProvider works the same way (and also takes max_tokens, default 1024, which caps the description's length and cost). The tool only reads images inside the sandbox directory, using the same path-escape protection as the file tools (../ traversal, absolute paths and symlink escapes are rejected). The image type is detected from the file's bytes, not its extension. Defaults: 5,000,000 bytes per image (max_image_bytes) and 2,000 characters for the model-supplied prompt (max_prompt_chars). Gemini accepts JPEG, PNG and WebP here; Anthropic also accepts GIF. Standard library only (urllib.request) - no new dependency.

URLs are deliberately not accepted: letting a model name a URL to fetch carries the same SSRF risk as the HTTP-fetch tool listed below as out of scope. The returned description is text derived from an image that may be attacker-controlled - treat it as untrusted input (it is not screened for prompt injection).

GeminiVisionProvider was live-checked once on 2026-10-03 (one call on a small PNG, model gemini-3.6-flash): the request shape and response parsing worked. JPEG and WebP input and Gemini's error responses were not live-checked. AnthropicVisionProvider has not been called against a live account - its request shape was checked against current public documentation only, so treat it as best-effort until confirmed live.

Network limits (all HTTP providers)

Every provider that makes an HTTP request (Tavily, Serper, GitHub search, Gemini and Anthropic vision) enforces a response-size cap and a hard total deadline. Both are configurable on the provider (or on GitHubSearchConfig):

from ragleap_tools import TavilySearchProvider

provider = TavilySearchProvider(
    api_key="...",
    max_response_bytes=2_000_000,  # default 1,048,576
    total_timeout=30,              # seconds; default 20 (90 for vision)
)

An oversize response or an exceeded deadline returns a failed ToolResult instead of hanging your tool-calling loop. The per-operation socket timeout is unchanged (15 seconds; 60 for vision). Python cannot kill a thread, so after the deadline an abandoned request is stopped on a best-effort basis (its socket is shut down; failing that it ends within one per-operation timeout), and DNS resolution is not covered by the per-operation timeout. See docs/design/http-limits.md.

Deliberately out of scope

Each of these needs its own security-focused design pass, not a rushed inclusion here:

  • Code execution - a real sandboxing/resource-limit design decision, not something to bolt on alongside a calculator.
  • HTTP fetch - letting an LLM request arbitrary URLs carries real SSRF risk, same care level as code execution.
  • Database/business-system connectors (SQL, CRM, payment processors, etc.) - some of what this ecosystem already has elsewhere (e.g. a live payment processor) would be a materially different risk if exposed to LLM tool-calling without deliberate guardrails (dry-run modes, confirmation steps, scoped permissions).

Status

v0.4.1. 200 tests, all passing, including real security verification for the two risk-sensitive tools (calculator's code-injection rejection, file ops' path-traversal and symlink-escape rejection) - not just documented as safe, actually tested against real attack vectors.

Not live-verified: the web search providers (Tavily, Serper), the Anthropic vision provider, and authenticated GitHub requests - request shapes were checked against current public documentation only. The Gemini vision provider was live-checked once (see above). The v0.4.1 bounded transport was live-checked for Gemini vision (2026-10-09) and for unauthenticated GitHub search.

License

MIT

Metadata

Release files for ragleap-tools 0.4.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ragleap-tools 0.4.1
File Size Uploaded
ragleap_tools-0.4.1.tar.gz 47.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ragleap-tools 0.4.1
File Interpreter ABI Platform
ragleap_tools-0.4.1-py3-none-any.whl Python 3 none any Details

Total release size: 81.6 kB

Release files / ragleap_tools-0.4.1.tar.gz

Download URL ragleap_tools-0.4.1.tar.gz
Size 47.8 kB
Tags Source
SHA-256 checksum
How to use checksums
885b1b9eb466b122000e01283d8e656684f527c1198cfd6b94e368ef4e8379aa
BLAKE2b-256 checksum
How to use checksums
1f9d08efb1a669b94e93d56373a0f374eb89bbb32dd2e779633ced5bdd4dddf4
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 Oct 10, 2026.

Transparency log

Release files / ragleap_tools-0.4.1-py3-none-any.whl

Download URL ragleap_tools-0.4.1-py3-none-any.whl
Size 33.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5157875487e1fe2033d6f1880f03c45b366b209bc0623b8539d12ab48a9ce74c
BLAKE2b-256 checksum
How to use checksums
cb7dbbff1127ab4699f0ce67ca474d1c237544bcecd6e8e9772c9eb202c65dd6
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 Oct 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.4.1 This release

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page