Add tool-call capability validation to model selection pipeline
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 35/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Tranquilla
- Stack tecnologico
- go, kubernetes
- Ambito
- api, backend, infrastructure
Direzione di ricerca
Inizia tracciando la configurazione del modello e l'individuazione dei modelli in internal/model/model.go, in particolare ValidateCustomEndpoint() e queryLiteLLMModels(). Poi segui rankModels() in internal/openclaw/openclaw.go e i tipi ServiceOffer e gateway nei file indicati. Il lavoro è completo quando la capacità di tool-call viene registrata, considerata durante la selezione del modello ed esposta oppure segnalata nei flussi di configurazione e vendita proposti.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Problem
OpenClaw relies heavily on tool/function calling to execute skills — 12+ embedded skills ship with executable scripts (kube.py, rpc.sh, signer.py, buy.py, discovery.py, monetize.py, etc.) that the agent invokes via shell execution tools. If the assigned model doesn't support tool calling, every executable skill silently becomes dead weight. The user gets no warning — the agent appears to work but never invokes any skill.
Root causes
-
Zero capability metadata.
ProviderInfo,ProviderStatus,ModelEntry— none carry asupports_tools,supports_vision, or any capability field. The codebase has no concept of model capabilities. -
ValidateCustomEndpoint()is a ping test only. It sends{role:"user", content:"ping"}withmax_tokens:1. It never tests whether the model can produce atool_callsresponse. A model that passes validation may be completely incapable of using tools. -
drop_params: trueis the silent killer. Set globally in the LiteLLM ConfigMap (litellm_settings.drop_params: true). When a model doesn't support thetools[]parameter, LiteLLM silently strips it instead of erroring. OpenClaw sends tool definitions → LiteLLM drops them → the model never sees them → skills never fire → no error is raised. -
rankModels()uses string heuristics, not capabilities.isCloudModel()checks if the name contains"claude"or starts with"gpt","o1","o3". That's it. A tiny Ollama model with no tool support can become the primary agent model with no warning. -
Selling side has zero capability exposure. The
ServiceOfferCRD only carriesmodel.nameandmodel.runtime. Buyers paying via x402 have no way to know if the model supports tools, vision, structured output, etc.
Impact
| Scenario | What happens today |
|---|---|
| User sets up Ollama model without tool support | Model is accepted, assigned to OpenClaw. All 12+ executable skills silently fail. |
| User adds a custom endpoint | ValidateCustomEndpoint passes with any model that can chat. No tool-call check. |
| Buyer purchases inference via x402 | No capability metadata in ServiceOffer. Buyer discovers limitations only after paying. |
rankModels() picks primary model |
Ranking is cloud-vs-local by name pattern. A cloud model without tool support beats a local model with it. |
Inspiration
ToolCall-15 is a focused benchmark that tests 5 categories of LLM tool-calling failures:
- Tool Selection — pick the right tool among 12
- Parameter Precision — pass correct arguments, handle types/units
- Multi-Step Chains — thread data across 4-step dependent calls
- Restraint/Refusal — know when NOT to call a tool
- Error Recovery — handle empty results and failures gracefully
We don't need to implement the full benchmark, but we can borrow its simplest probe pattern: send a tool definition + a message that requires it, and check whether the model produces a valid tool_calls response.
Proposed solution
Phase 1: Tool-call probe during model setup
During obol model setup, after the existing reachability/inference ping, add a tool-call probe:
{
"model": "<model>",
"messages": [{"role": "user", "content": "What is the weather in Berlin?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get weather for a location",
"parameters": {
"type": "object",
"properties": {"location": {"type": "string"}},
"required": ["location"]
}
}
}],
"max_tokens": 100
}
Pass criteria: Response contains choices[0].message.tool_calls with at least one entry where function.name == "get_weather".
If the model fails:
- Display a clear warning:
⚠ Model "<name>" does not support tool calling. OpenClaw skills will not work. - Still allow setup (the model may be useful for non-agent workloads) but flag it in model metadata.
Phase 2: Add capability fields to model types
Extend ModelEntry or introduce a new ModelCapabilities struct:
type ModelCapabilities struct {
SupportsTools bool `json:"supports_tools" yaml:"supports_tools"`
SupportsVision bool `json:"supports_vision" yaml:"supports_vision"`
SupportsReasoning bool `json:"supports_reasoning" yaml:"supports_reasoning"`
SupportsParallelTools bool `json:"supports_parallel_tools" yaml:"supports_parallel_tools"`
SupportsStructuredOutput bool `json:"supports_structured_output" yaml:"supports_structured_output"`
}
Populate from:
- The Phase 1 probe result (definitive for
SupportsTools) - LiteLLM's
GET /model/infoendpoint (returnssupports_function_calling,supports_tool_choice,supports_vision,supports_reasoning, etc. for 2500+ models from its built-in model cost map) - User override via CLI flags
Phase 3: Capability-aware model selection for OpenClaw
rankModels()should filter to tool-call-capable models first, then apply the cloud-vs-local ranking within that set.- If no tool-capable model is available, warn loudly at startup and during
obol openclawoperations. - Consider gating OpenClaw deployment: if zero models pass the tool-call probe, block deployment with a clear error rather than deploying a broken agent.
Phase 4: Expose capabilities on the selling side
- Add capability fields to the
ServiceOfferCRD spec (alongsidemodel.nameandmodel.runtime). - Populate them from the probe/LiteLLM metadata when
obol monetizeregisters the service. - Surface capabilities in the inference gateway response headers or a discovery endpoint.
- Wire into ERC-8004 registration metadata (the
services[].SkillsOASF taxonomy andregistration.metadatamap already support this — they're just unused for capability info today).
LiteLLM /model/info reference
LiteLLM already tracks per-model capabilities in its model cost database (2594 models, 1353 with supports_function_calling). The proxy exposes this via GET /model/info:
{
"data": [{
"model_name": "claude-sonnet-4-20250514",
"model_info": {
"supports_function_calling": true,
"supports_tool_choice": true,
"supports_parallel_function_calling": true,
"supports_vision": true,
"supports_reasoning": true,
"supports_response_schema": true,
"max_input_tokens": 200000,
"max_output_tokens": 64000
}
}]
}
Today obol-stack only queries /v1/models (bare model IDs). Switching to /model/info would give us capability metadata for free on cloud models.
Files to change
| File | Change |
|---|---|
internal/model/model.go |
Add tool-call probe to ValidateCustomEndpoint(), add ModelCapabilities struct, query /model/info in queryLiteLLMModels() |
internal/openclaw/openclaw.go |
Update rankModels() to use capabilities, add warnings in SyncOverlayModels() |
internal/inference/gateway.go |
Expose capability metadata in response headers or discovery endpoint |
internal/schemas/serviceoffer.go |
Add capability fields to ServiceOffer spec |
internal/embed/infrastructure/base/templates/llm.yaml |
Consider documenting/commenting the drop_params: true risk |
- Lingua principale
- Go
- Stelle
- 11
- Fork
- 1
- Merge medio
- 1h 20m
- PR unite (30g)
- 39
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di ObolNetwork/obol-stack
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
ObolNetwork/obol-stack#612 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 30/100
ObolNetwork/obol-stack#829 ·
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 3/5 1-2 giorni Idoneità per principianti 72/100
ObolNetwork/obol-stack#828 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
ObolNetwork/obol-stack#821 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
ObolNetwork/obol-stack#807 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di ObolNetwork/obol-stack
Issue simili
-
📖 docs: Docker Compose quick start doesn't mention editing the project values in src/hive.yamlApertadocumentation help wanted needs-triage
Difficoltà 1/5 1-3 ore Idoneità per principianti 75/100
hivecommons/hive#11606 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
[docs] `/docs/identity-security/usage/alerts/`: docs reference a date that has already passedApertadocumentation
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 85/100
gravitational/teleport#69869 ·
-
category:agent
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
LanternOps/breeze#8493 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
I maintainer di solito rispondono entro 1 giorno
-
docs
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
shaiknoorullah/hg-mono#815 ·
I maintainer di solito rispondono entro 1 giorno