Skip to main content

ToolScope: per-prompt automatic tool selection for LLM tool calling.

Project description

ToolScope

ToolScope is a lightweight, production-ready Tool RAG library for agentic systems.

It solves a core scalability problem in tool-using agents:

As the number of tools grows, LLMs become worse at selecting the right one.

ToolScope fixes this by filtering tools per turn using semantic retrieval — without changing how the model interacts with tools.

No meta-tools.
No retrievers exposed to the model.
No framework lock-in.


Why ToolScope?

When agents see hundreds of tools:

  • tool selection accuracy drops
  • context windows overflow
  • latency increases
  • small models break first

ToolScope:

  • indexes tool descriptions in a vector database
  • retrieves only the most relevant tools per prompt
  • hands those tools to the model exactly as before

The model doesn’t know ToolScope exists — it just performs better.

Use ToolScope when:

  • you have dozens to hundreds of tools
  • tools come from MCP servers or registries
  • you want to keep using standard agent frameworks
  • you want predictable, debuggable behavior

Quickstart

1. Install

pip install toolscope

(or from source)

pip install -e .

2. Minimal filtering

import toolscope

class TinyEmbedder:
    def embed_texts(self, texts):
        return [[len(t) % 97, t.count("jira"), sum(map(ord, t)) % 101] for t in texts]

tools = [
    {"name": "jira_create_issue", "description": "Create a Jira issue", "inputSchema": {}},
    {"name": "confluence_search", "description": "Search Confluence pages", "inputSchema": {}},
]

filtered = toolscope.filter(
    messages=[{"role": "user", "content": "Create a Jira ticket"}],
    tools=tools,
    embedder=TinyEmbedder(),
    k=1,
)

print(filtered)  # same tools, fewer of them

or, with an embedding configuration (requires sentence-transformers):

import toolscope

embedding_config = toolscope.EmbeddingConfig(
    provider="sentence-transformers",
    model="sentence-transformers/all-MiniLM-L6-v2",
    allow_download=False,
)

tools = [
    {"name": "jira_create_issue", "description": "Create a Jira issue", "inputSchema": {}},
    {"name": "confluence_search", "description": "Search Confluence pages", "inputSchema": {}},
]

filtered = toolscope.filter(
    messages=[{"role": "user", "content": "Create a Jira ticket"}],
    tools=tools,
    embedding=embedding_config,
    k=1,
)

print(filtered)  # same tools, fewer of them

3. Indexed (stateful) usage

idx = toolscope.index(
    tools,
    embedder=TinyEmbedder(),
)

filtered = idx.filter(
    messages="Create a Jira ticket",
    k=1,
)

Core Concepts and Features

Canonical tools

ToolScope normalizes tools from many schemas into a canonical form:

  • name
  • description
  • input schema
  • tags
  • fingerprint

Original tool objects are preserved and returned unchanged.


Embeddings

ToolScope supports pluggable embedding backends.

Option A: Provide your own embedder (recommended default)

class MyEmbedder:
    def embed_texts(self, texts): ...

Option B: Use EmbeddingConfig (HTTP, OpenAI-style, etc.)

toolscope.EmbeddingConfig(
    provider="http",
    endpoint="http://localhost:8000/embed",
    model="my-embedding-model",
)

ToolScope never downloads models behind your back.


Tool text control

You control what text is embedded:

toolscope.ToolTextConfig(
    use_name=True,
    use_description=True,
    use_schema=False,
    truncate=256,
)

Defaults (battle-tested):

  • name + description only
  • truncate to 256 chars
  • no preprocessing

Advanced Features

✅ Allow / deny filters

idx.filter(
    messages,
    allow_tags=["jira"],
    deny_tags=["dangerous"],
)

🔁 Sticky toolsets (multi-turn sessions)

Reuse tools across turns when the query stays similar:

toolscope.StickySessionConfig(
    enabled=True,
    similarity_threshold_reuse=0.95,
    similarity_threshold_refresh=0.8,
    sticky_keep=2,
)

This reduces latency and improves consistency.


🧠 Reranking

Boost retrieval quality using a cross-encoder:

toolscope.RerankingConfig(
    model="cross-encoder/ms-marco-MiniLM-L-6-v2",
    pool_size=20,
)

Not enabled by default — you opt in explicitly.


📊 Observability

Inspect what ToolScope is doing:

tools, trace = idx.filter_with_trace(messages)
print(trace)

Includes:

  • candidate counts
  • timings
  • allow/deny decisions
  • reranking effects

Backends

In-memory (default)

Fast, simple, zero dependencies.

toolscope.MemoryBackend()

Milvus Lite

Persistent, scalable local vector DB:

toolscope.MilvusLiteBackend(path="./toolscope.db")

ToolScope is backend-agnostic; more vector DBs can be added.


Adapters (Plug & Play)

ToolScope integrates cleanly with popular agent stacks.

LangChain / LangGraph

  • full agent loops
  • per-turn tool filtering
  • middleware-based integration
from toolscope.adapters.langchain import (
    ToolSelector,
    make_toolscope_tool_selection_middleware,
)

See:

examples/langchain/

FastMCP

  • drop-in MCP client wrapper
  • supports multi-server clients
  • reacts to tools/list_changed notifications
from toolscope.adapters.fastmcp import ToolScopeFastMCPClient

See:

examples/fastmcp/

License

This project is licensed under the Apache License 2.0.

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

toolscope-0.1.0.tar.gz (38.7 kB view details)

Uploaded Source

Built Distribution

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

toolscope-0.1.0-py3-none-any.whl (39.6 kB view details)

Uploaded Python 3

File details

Details for the file toolscope-0.1.0.tar.gz.

File metadata

  • Download URL: toolscope-0.1.0.tar.gz
  • Upload date:
  • Size: 38.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.13

File hashes

Hashes for toolscope-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ac6a1cdde96e4c44f66279f3cd57d668a9e57fe56152b58a4acc11fb21841eca
MD5 3afb87ca9308c8718f4cd341568b5b90
BLAKE2b-256 4465f80af33a475cc9446ea0a5650906ca2748714c6d739e29c45064525f6031

See more details on using hashes here.

File details

Details for the file toolscope-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: toolscope-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 39.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.13

File hashes

Hashes for toolscope-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 da580077a6d4cd656446620a6a8dad30a1ba9a493f1135331fc37b60bdf34908
MD5 ac9d205e92eedadbc49982316cca98d7
BLAKE2b-256 05c16c9b5d4f9d161634dae7bccc9c6ffdce0ce970914a63ad278d17998d5533

See more details on using hashes here.

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