graph-tool-call
graph-tool-call
LLM-Agenten können nicht tausende Tool-Definitionen in den Kontext laden. Vektorsuche findet ähnliche Tools, übersieht aber den Workflow, zu dem sie gehören. graph-tool-call erstellt einen Tool-Graphen und ruft die richtige Kette ab – nicht nur einen Treffer.
Ohne Abfrage | graph-tool-call | |
248 Tools (K8s API) | 12 % Genauigkeit | 82 % Genauigkeit |
1068 Tools (GitHub Full API) | Kontext-Überlauf | 78 % Recall@5 |
Token-Verbrauch | 8.192 Tok | 1.699 Tok (79 % ↓) |
Gemessen mit qwen3:4b (4-Bit) — vollständiger Benchmark
Warum
LLM-Agenten benötigen Tools. Aber mit wachsender Tool-Anzahl treten zwei Probleme auf:
Kontext-Überlauf — 248 Kubernetes-API-Endpunkte = 8.192 Token an Tool-Definitionen. Das LLM ist überlastet und die Genauigkeit sinkt auf 12 %.
Vektorsuche übersieht Workflows — Die Suche nach "cancel my order" findet
cancelOrder, aber der tatsächliche Ablauf istlistOrders → getOrder → cancelOrder → processRefund. Die Vektorsuche liefert nur ein Tool; Sie benötigen die Kette.
graph-tool-call löst beides. Es modelliert Tool-Beziehungen als Graph, ruft mehrstufige Workflows mittels hybrider Suche ab (BM25 + Graph-Traversierung + Embedding + MCP-Annotationen) und reduziert den Token-Verbrauch um 64–91 %, während die Genauigkeit beibehalten oder verbessert wird.
Szenario | Nur Vektor | graph-tool-call |
"cancel my order" | Gibt |
|
"read and save file" | Gibt |
|
"delete old records" | Gibt irgendein Tool mit "delete" zurück | Destruktive Tools werden durch MCP-Annotationen zuerst gerankt |
"now cancel it" (nach Auflistung der Bestellungen) | Kein Kontext aus der Historie | Verwendete Tools werden abgewertet, Folgeschritt-Tools bevorzugt |
Mehrere Swagger-Specs mit überschneidenden Tools | Doppelte Tools in den Ergebnissen | Automatische Deduplizierung über Quellen hinweg |
1.200 API-Endpunkte | Langsame, verrauschte Ergebnisse | Kategorisiert + Graph-Traversierung für präzise Abfrage |
Funktionsweise
OpenAPI / MCP / Python functions → Ingest → Build tool graph → Hybrid retrieve → AgentBeispiel — Der Benutzer sagt "cancel my order and process a refund"
Vektorsuche findet cancelOrder. Aber der tatsächliche Workflow ist:
┌──────────┐
PRECEDES │listOrders│ PRECEDES
┌─────────┤ ├──────────┐
▼ └──────────┘ ▼
┌──────────┐ ┌───────────┐
│ getOrder │ │cancelOrder│
└──────────┘ └─────┬─────┘
│ COMPLEMENTARY
▼
┌──────────────┐
│processRefund │
└──────────────┘graph-tool-call gibt die gesamte Kette zurück, nicht nur ein Tool. Die Abfrage kombiniert vier Signale mittels gewichteter Reciprocal Rank Fusion (wRRF):
BM25 — Keyword-Matching
Graph-Traversierung — beziehungsbasierte Erweiterung (PRECEDES, REQUIRES, COMPLEMENTARY)
Embedding-Ähnlichkeit — semantische Suche (optional, jeder Anbieter)
MCP-Annotationen — Hinweise auf schreibgeschützte / destruktive / idempotente Aktionen
Installation
Das Kernpaket hat null Abhängigkeiten — nur die Python-Standardbibliothek. Installieren Sie nur, was Sie benötigen:
pip install graph-tool-call # core (BM25 + graph) — no dependencies
pip install graph-tool-call[embedding] # + embedding, cross-encoder reranker
pip install graph-tool-call[openapi] # + YAML support for OpenAPI specs
pip install graph-tool-call[mcp] # + MCP server / proxy mode
pip install graph-tool-call[all] # everythingExtra | Installiert | Verwendung |
| pyyaml | YAML OpenAPI-Spezifikationen |
| numpy | Semantische Suche (Verbindung zu Ollama/OpenAI/vLLM) |
| numpy, sentence-transformers | Lokale sentence-transformers-Modelle |
| rapidfuzz | Duplikaterkennung |
| langchain-core | LangChain-Integration |
| pyvis, networkx | HTML-Graph-Export, GraphML |
| dash, dash-cytoscape | Interaktives Dashboard |
| ai-api-lint | Automatische Korrektur fehlerhafter API-Specs |
| mcp | MCP-Server / Proxy-Modus |
Schnellstart
In 30 Sekunden ausprobieren (keine Installation)
uvx graph-tool-call search "user authentication" \
--source https://petstore.swagger.io/v2/swagger.jsonQuery: "user authentication"
Source: https://petstore.swagger.io/v2/swagger.json (19 tools)
Results (5):
1. getUserByName — Get user by user name
2. deleteUser — Delete user
3. createUser — Create user
4. loginUser — Logs user into the system
5. updateUser — Updated userPython-API
from graph_tool_call import ToolGraph
# Build a tool graph from the official Petstore API
tg = ToolGraph.from_url(
"https://petstore3.swagger.io/api/v3/openapi.json",
cache="petstore.json",
)
print(tg)
# → ToolGraph(tools=19, nodes=22, edges=100)
# Search for tools
tools = tg.retrieve("create a new pet", top_k=5)
for t in tools:
print(f"{t.name}: {t.description}")
# Search with workflow guidance
results = tg.retrieve_with_scores("process an order", top_k=5)
for r in results:
print(f"{r.tool.name} [{r.confidence}]")
for rel in r.relations:
print(f" → {rel.hint}")
# Execute an OpenAPI tool directly
result = tg.execute(
"addPet", {"name": "Buddy", "status": "available"},
base_url="https://petstore3.swagger.io/api/v3",
)Workflow-Planung
plan_workflow() gibt geordnete Ausführungsketten mit Voraussetzungen zurück — dies reduziert Agenten-Roundtrips von 3-4 auf 1.
plan = tg.plan_workflow("process a refund")
for step in plan.steps:
print(f"{step.order}. {step.tool.name} — {step.reason}")
# 1. getOrder — prerequisite for requestRefund
# 2. requestRefund — primary action
plan.save("refund_workflow.json")Bearbeiten, parametrisieren und visualisieren Sie Workflows — siehe Direct API guide.
Andere Tool-Quellen
# From an MCP server (HTTP JSON-RPC tools/list)
tg.ingest_mcp_server("https://mcp.example.com/mcp")
# From an MCP tool list (annotations preserved)
tg.ingest_mcp_tools(mcp_tools, server_name="filesystem")
# From Python callables (type hints + docstrings)
tg.ingest_functions([read_file, write_file])MCP-Annotationen (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) werden als Abfragesignale verwendet — die Abfrageabsicht wird automatisch klassifiziert, und Leseabfragen priorisieren schreibgeschützte Tools, während Löschabfragen destruktive Tools priorisieren.
Wählen Sie Ihre Integration
graph-tool-call bietet verschiedene Integrationsmuster. Wählen Sie dasjenige, das zu Ihrem Stack passt:
Sie verwenden... | Muster | Token-Gewinn | Anleitung |
Claude Code / Cursor / Windsurf | MCP Proxy (N MCP-Server aggregieren → 3 Meta-Tools) | ~1.200 Tok/Turn | |
Jeder MCP-kompatible Client | MCP Server (einzelne Quelle als MCP) | variiert | |
LangChain / LangGraph (50+ Tools) | Gateway-Tools (N Tools → 2 Meta-Tools) | 92 % | |
OpenAI / Anthropic SDK (bestehender Code) | Middleware (1-Zeilen-Monkey-Patch) | 76–91 % | |
Direkte Kontrolle über die Abfrage | Python-API ( | variiert |
MCP Proxy (am häufigsten)
Wenn Sie viele MCP-Server haben, häufen sich deren Tool-Namen in jedem LLM-Turn an. Bündeln Sie diese hinter einem Server: 172 Tools → 3 Meta-Tools.
# 1. Create ~/backends.json listing your MCP servers
# 2. Register the proxy with Claude Code
claude mcp add -s user tool-proxy -- \
uvx "graph-tool-call[mcp]" proxy --config ~/backends.jsonVollständiges Setup, Passthrough-Modus, Remote-Transport → MCP Proxy guide.
LangChain Gateway
from graph_tool_call.langchain import create_gateway_tools
# 62 tools from Slack, GitHub, Jira, MS365...
gateway = create_gateway_tools(all_tools, top_k=10)
# → [search_tools, call_tool] — only 2 tools in context
agent = create_react_agent(model=llm, tools=gateway)92 % Token-Reduktion gegenüber der Einbindung aller 62 Tools. Siehe LangChain guide für automatische Filter- und manuelle Muster.
SDK-Middleware
from graph_tool_call.middleware import patch_openai
patch_openai(client, graph=tg, top_k=5) # ← add this one line
# Existing code unchanged — 248 tools go in, only 5 relevant ones are sent
response = client.chat.completions.create(
model="gpt-4o",
tools=all_248_tools,
messages=messages,
)Funktioniert auch mit Anthropic via patch_anthropic. Siehe Middleware guide.
Benchmark
Zwei Fragen: (1) Wählt das LLM immer noch das richtige Tool, wenn es nur die abgerufene Teilmenge erhält? (2) Rankt der Retriever selbst die korrekten Tools in den Top K?
Datensatz | Tools | Baseline-Genauigkeit | graph-tool-call | Token-Reduktion |
Petstore | 19 | 100 % | 95 % (k=5) | 64 % |
GitHub | 50 | 100 % | 88 % (k=5) | 88 % |
Gemischtes MCP | 38 | 97 % | 90 % (k=5) | 83 % |
Kubernetes core/v1 | 248 | 12 % | 82 % (k=5 + Ontologie) | 79 % |
Wichtigste Erkenntnis — bei 248 Tools bricht die Baseline (Kontext-Überlauf) auf 12 % ein, während graph-tool-call sich auf 82 % erholt. In kleinerem Maßstab ist die Baseline bereits stark, daher liegt der Wert von graph-tool-call in der Token-Einsparung ohne Genauigkeitsverlust.
→ Vollständige Ergebnisse (Pipeline / nur Abfrage / Wettbewerb / 1068-Skala / 200-Tool LangChain-Agent über GPT und Claude): docs/benchmarks.md
# Reproduce
python -m benchmarks.run_benchmark # retrieval only
python -m benchmarks.run_benchmark --mode pipeline -m qwen3:4b # full pipelineErweiterte Funktionen
Embedding-basierte hybride Suche
Fügen Sie semantische Suche zusätzlich zu BM25 + Graph hinzu. Keine schweren Abhängigkeiten erforderlich — verbinden Sie sich mit jedem externen Embedding-Server.
tg.enable_embedding("ollama/qwen3-embedding:0.6b") # Ollama (recommended)
tg.enable_embedding("openai/text-embedding-3-large") # OpenAI
tg.enable_embedding("vllm/Qwen/Qwen3-Embedding-0.6B") # vLLM
tg.enable_embedding("sentence-transformers/all-MiniLM-L6-v2") # local
tg.enable_embedding(lambda texts: my_embed_fn(texts)) # custom callableGewichtungen werden automatisch neu ausbalanciert. Siehe API reference für alle Anbieter-Formate.
Abfrage-Tuning
tg.enable_reranker() # cross-encoder rerank
tg.enable_diversity(lambda_=0.7) # MMR diversity
tg.set_weights(keyword=0.2, graph=0.5, embedding=0.3, annotation=0.2)Historienbewusste Abfrage
Übergeben Sie zuvor aufgerufene Tools, um diese abzuwerten und Kandidaten für den nächsten Schritt zu fördern.
tools = tg.retrieve("now cancel it", history=["listOrders", "getOrder"])
# → [cancelOrder, processRefund, ...]Speichern / Laden (erhält Embeddings + Gewichtungen)
tg.save("my_graph.json")
tg = ToolGraph.load("my_graph.json")
# Or use cache= in from_url() for automatic save/load
tg = ToolGraph.from_url(url, cache="my_graph.json")LLM-erweiterte Ontologie
tg.auto_organize(llm="ollama/qwen2.5:7b")
tg.auto_organize(llm="litellm/claude-sonnet-4-20250514")
tg.auto_organize(llm=openai.OpenAI())Erstellt reichhaltigere Kategorien, Beziehungen und Suchbegriffe. Unterstützt Ollama, OpenAI-Clients, litellm und jedes aufrufbare Objekt. Siehe API reference.
Weitere Funktionen
Funktion | API | Doku |
Duplikaterkennung über Specs hinweg |
| |
Konflikterkennung |
| |
Operative Analyse |
| |
Interaktives Dashboard |
| |
HTML / GraphML / Cypher Export |
| |
Automatische Korrektur fehlerhafter OpenAPI-Specs |
|
Dokumentation
Doku | Beschreibung |
Alle | |
| |
MCP-Server / Proxy, LangChain, Middleware, direkte API | |
Vollständige Pipeline / Abfrage / Wettbewerb / Skalierungstabellen | |
Systemübersicht, Pipeline-Schichten, Datenmodell | |
Algorithmus-Design — Normalisierung, Abhängigkeitserkennung, Ontologie | |
Wettbewerbsanalyse, API-Skalierungsdaten | |
Release-Prozess, Changelog-Ablauf |
Mitwirken
Beiträge sind willkommen.
git clone https://github.com/SonAIengine/graph-tool-call.git
cd graph-tool-call
pip install poetry pre-commit
poetry install --with dev --all-extras
pre-commit install # auto-runs ruff on every commit
# Test, lint, benchmark
poetry run pytest -v
poetry run ruff check . && poetry run ruff format --check .
python -m benchmarks.run_benchmark -vLizenz
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/SonAIengine/graph-tool-call'
If you have feedback or need assistance with the MCP directory API, please join our Discord server