RagLeap Packages
Looking for the RagLeap platform? This page documents the open-source pip install ragleap-tools library. For the hosted business platform, see docs.ragleap.com instead.
69 tests, all passing — including real security verification, not just documented as safe

ragleap-tools

Standalone, dependency-light tool implementations for LLM tool-calling. Exposes OpenAI/Gemini-style function-calling schemas — ragleap-tools provides the Tool objects, not the execution loop.

0.1.1
PyPI version
69
Tests passing
12
Stateless tools included
0
Uses of eval()/exec()

Install

No configuration needed for the 12 stateless tools. File operations and document ingestion are opt-in and each need their own config object.

pip install ragleap-tools
# or, with uv
uv add ragleap-tools

# optional, for the ragleap-rag-backed ingestion tool:
pip install ragleap-tools[ingest]

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's job, per the roadmap's own split. Wire these tools into your own tool-calling code, or into ragleap-agents once that ships.

Quick start

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

Full public API

Stateless tools (v0.1.0+) — no configuration needed

CALCULATOR_TOOL
Safe arithmetic via an AST-based whitelist evaluator — never eval()/exec().
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 (v0.1.0+) — 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. Paths are resolved via Path.resolve() (which follows symlinks) before containment is checked with is_relative_to() — so both ../ traversal and symlink-based escapes are rejected, not just naive string-prefix checking. There is no unsandboxed mode.

Document ingestion and search (v0.1.0+) — optional, needs ragleap-rag

from ragleap import RagLeap, ProviderConfig, EmbeddingConfig
from ragleap_tools import IngestConfig, make_ingest_tool

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

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. Same optional-dependency pattern ragleap-graph already uses for its own optional ragleap-rag link.

Version history

VersionWhat shippedReal live test performed
v0.1.0Initial release: 12 stateless tools, sandboxed file ops (FileOpsConfig, make_file_tools), optional ingestion tool (IngestConfig, make_ingest_tool)51 tests incl. real security tests: calculator rejects __import__/attribute access/list comprehensions/multi-statement injection; file ops blocked against a real on-disk symlink pointing outside the sandbox, not just a path-string check
v0.1.1Added search_documents (SearchConfig, make_search_tool) wrapping ragleap-rag's retrieve() for hybrid vector+keyword search, with an optional filename= to scope search to one document. Fixed ingest_document to pass metadata={"filename": filename} to ingest_text() - v0.1.0 passed no metadata at all, silently making every ingested document unfilterable by metadata_filter, which filename= depends on.69 tests (was 51). New: 8 tests for search_documents asserting on the fake's actually-recorded metadata_filter value, not just call-succeeded. 6 tests backfilled for ingest_document - v0.1.0 shipped it with zero direct test coverage, exactly the kind of gap that hid the metadata bug.

Real design decisions & scope boundaries this session

Not fabricated wins — each of these was a deliberate call made before writing code, not an afterthought.

  • ✓ shipped
    No execution-loop ownership. ragleap-tools provides Tool objects only. The roadmap already assigns tool-calling execution + HITL approval gates to ragleap-agents — avoiding two competing execution-loop implementations in the ecosystem.
  • ✓ shipped
    AST-based calculator, never eval()/exec(). Parses the expression, walks the tree, rejects anything outside an explicit allowlist of node types/functions. Verified against real code-injection payloads, not just documented as safe.
  • ✓ shipped
    Symlink-aware file sandboxing. Path.resolve() before containment check, not naive string-prefix matching — closes a real escape class that string-based sandboxing misses. Verified with a real on-disk symlink pointing outside the sandbox, not just a synthetic path string.
  • deliberately deferred
    Code execution, web search, HTTP fetch, and business-system connectors are explicitly out of scope for v0.1.0. Each needs its own security-focused design pass. Not rushed in alongside lower-risk tools.

Known limitations

  • No tool-calling execution loop is provided — the caller (or ragleap-agents, once it ships) must decide when to call a tool and feed results back to the model.
  • File ops require an explicit root_dir — there is no unsandboxed mode, and no default directory is assumed.
  • Code execution, web search, HTTP fetch, and database/business-system connectors are not included in v0.1.0.