Skip to content

feat(onboard): warn on Ollama models without tools capability (#2667) - #3097

Merged
cv merged 4 commits into
NVIDIA:mainfrom
TonyLuo-NV:feat/2667-ollama-tools-capability-check
May 6, 2026
Merged

feat(onboard): warn on Ollama models without tools capability (#2667)#3097
cv merged 4 commits into
NVIDIA:mainfrom
TonyLuo-NV:feat/2667-ollama-tools-capability-check

Conversation

@TonyLuo-NV

@TonyLuo-NV TonyLuo-NV commented May 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes #2667 — users who picked an Ollama model without tool-calling support (e.g. `phi4`) hit `HTTP 400 ... does not support tools` the first time the agent invoked a tool, with no early signal during onboarding that the chosen model would not work.

This adds an onboard-time capability check plus a friendlier runtime mapping so users find out as early as possible and get an actionable hint either way.

What changed

Onboard-time check (primary fix)

  • New `probeOllamaModelCapabilities` POSTs `/api/show` against the local Ollama daemon and parses the `capabilities` array. Defensive parsing returns "unknown" on any failure (HTTP error, empty body, malformed JSON, missing field) so we never false-positive-block.
  • New `checkOllamaModelToolSupport` runs inside `prepareOllamaModel` after the pull and before warmup. When the model lacks `tools`, it prints a warning naming the model and tools-capable alternatives, then branches:
    • `--yes` / `NEMOCLAW_YES=1`: continues with a stderr note
    • non-interactive default: blocks with actionable error pointing at the override env var
    • non-interactive + `NEMOCLAW_OLLAMA_REQUIRE_TOOLS=0`: continues with stderr warning
    • interactive: prompts `Use this model anyway? [y/N]` (default N)
  • `NEMOCLAW_OLLAMA_REQUIRE_TOOLS=0` is the documented escape hatch (default `1`: block).

Runtime fallback

  • `validateOllamaModel` now detects `/does not support tools/i` in the `/api/generate` error payload and rewrites the user-facing message to name the model and recommend a replacement — covers the case where capability metadata says tools but generation still fails.

No new CLI flags. One env var: `NEMOCLAW_OLLAMA_REQUIRE_TOOLS` (default `1`).

Architectural notes

  • The host-side onboard probes Ollama on `localhost:11434` directly (network policy preset is irrelevant — onboard runs on host before the sandbox exists).
  • The new check fits the existing `selectAndValidateOllamaModel` loop contract — `prepareOllamaModel` returning `{ok:false}` already loops back to model selection.
  • Backward-compatible: existing onboarded sandboxes are untouched. Only fires during fresh model selection.
  • Custom Ollama registries / older daemons without `/api/show` capabilities → "unknown" → graceful proceed (never blocks on probe failure).

Test plan

  • `npx vitest run test/ollama-tools-capability.test.ts` — 13/13 covering the 13 architect-specified scenarios (tools=true/false/null, malformed JSON, correct curl argv, runtime error rewrite, interactive yes/no, non-interactive default + override, NEMOCLAW_YES, graceful unknown-degradation).
  • Broader Ollama suite (`get-ollama-model-options`, `ollama-pull-timeout`, `ollama-proxy-recovery`, `ollama-gpu-cleanup`, `onboard-selection`, plus new file): 70/70 passing.
  • `npm run typecheck:cli` passes.
  • Security review: 9/9 PASS (no secrets, injection-safe via argv `spawnSync`, JSON parse wrapped, no SSRF — host comes from internal resolver, no TLS skipped).
  • CI green.
  • Manual repro on Ubuntu 22.04 with phi4 (deferred to maintainer review env).

Signed-off-by: Tony Luo xialuo@nvidia.com

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Automatic tool-capability detection for Ollama models before loading.
    • Pre-load gating that checks model tool support and can prompt, warn, or block loading.
    • Non-interactive and auto-approve overrides for different environments.
    • Improved user-facing guidance and error messages suggesting tool-capable alternatives.
  • Tests

    • Added comprehensive tests for capability probing, prompts, override flows, and graceful degradation.

…#2667)

Users who pick an Ollama model that lacks tool-calling capability (e.g.
phi4) hit "HTTP 400 ... does not support tools" the first time the agent
tries to invoke a tool. The TUI surfaces only the raw error and there is
no early signal during onboarding that the chosen model will not work.

Add an onboard-time capability check and a friendlier runtime mapping so
the user finds out as early as possible.

Onboard-time check (primary fix):
- New `probeOllamaModelCapabilities` POSTs `/api/show` against the local
  Ollama daemon and parses the `capabilities` array. Defensive parsing
  returns "unknown" on any failure (HTTP error, empty body, malformed
  JSON, missing field) so we never false-positive-block.
- New `checkOllamaModelToolSupport` runs inside `prepareOllamaModel`
  after the pull and before warmup. When the model lacks `tools`:
  prints a warning naming the model and tools-capable alternatives
  (qwen2.5:7b, llama3.1, mistral-nemo, nemotron-3-nano:30b), then
  branches on auto-yes / non-interactive / interactive prompt.
- `NEMOCLAW_OLLAMA_REQUIRE_TOOLS=0` is the non-interactive override
  (default 1: block).

Runtime fallback:
- `validateOllamaModel` now detects `/does not support tools/i` in the
  /api/generate error payload and rewrites the user-facing message to
  name the model and recommend a replacement, so even users who already
  onboarded against an incompatible model get an actionable hint.

13 unit tests cover the 13 architect-specified scenarios; 70/70 across
the broader Ollama suite still pass.

Signed-off-by: Tony Luo <xialuo@nvidia.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@copy-pr-bot

copy-pr-bot Bot commented May 6, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: ed5101fd-a571-4966-8639-89b9f07ed776

📥 Commits

Reviewing files that changed from the base of the PR and between 353effc and 1d60c8c.

📒 Files selected for processing (3)
  • src/lib/local-inference.ts
  • src/lib/onboard-ollama-proxy.ts
  • test/ollama-tools-capability.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/ollama-tools-capability.test.ts

📝 Walkthrough

Walkthrough

Adds Ollama tool-capability detection and gating: a /api/show probe returning a new OllamaCapabilities shape and exported probeOllamaModelCapabilities(), a probe-driven checkOllamaModelToolSupport() gating flow in the onboard proxy (with interactive/env overrides), and tests for probe and gating behavior.

Changes

Ollama Tool-Capability Detection

Layer / File(s) Summary
Data Shape / Exports
src/lib/local-inference.ts
Adds OllamaCapabilities interface and exports probeOllamaModelCapabilities.
Core Capability Probe
src/lib/local-inference.ts
Implements probeOllamaModelCapabilities() that POSTs to /api/show, parses response into OllamaCapabilities, sets supportsTools (true/false/null), and maps known "does not support tools" errors into a user-facing suggestion message or rawError.
Tool Support Gating & Helpers
src/lib/onboard-ollama-proxy.ts
Adds isProxyNonInteractive(), isProxyAutoYes(), promptProxyYesNo(), printToolsIncompatibleWarning() and checkOllamaModelToolSupport() which calls the probe, respects NEMOCLAW_OLLAMA_REQUIRE_TOOLS and interactive/auto-yes modes, and returns { ok, message }.
Model Loading Integration
src/lib/onboard-ollama-proxy.ts
prepareOllamaModel() now invokes checkOllamaModelToolSupport(model) before pull/load and aborts with the returned message if the check fails. Exports checkOllamaModelToolSupport.
Tests & Verification
test/ollama-tools-capability.test.ts
New test suite validating probeOllamaModelCapabilities() parsing, curl argv construction, error mapping, and checkOllamaModelToolSupport() interactive/non-interactive flows, env overrides, and graceful degradation. Includes shared stubs and a proxy harness for module patching.

Sequence Diagram

sequenceDiagram
    actor User
    participant TUI
    participant OnboardProxy as onboard-ollama-proxy
    participant LocalInf as local-inference
    participant OllamaAPI as Ollama /api/show

    User->>TUI: Request load model
    TUI->>OnboardProxy: prepareOllamaModel(model)
    OnboardProxy->>OnboardProxy: checkOllamaModelToolSupport(model)
    OnboardProxy->>LocalInf: probeOllamaModelCapabilities(model)
    LocalInf->>OllamaAPI: POST /api/show { name: model }
    OllamaAPI-->>LocalInf: { capabilities: [...], ... } or error
    LocalInf-->>OnboardProxy: OllamaCapabilities (supportsTools: true/false/null)

    alt supportsTools is false & interactive
        OnboardProxy->>User: print warning + prompt
        User-->>OnboardProxy: response
        alt User declines
            OnboardProxy-->>TUI: { ok: false, message }
        else User accepts or auto-yes
            OnboardProxy-->>TUI: { ok: true }
        end
    else supportsTools is true OR null
        OnboardProxy-->>TUI: { ok: true }
    end

    OnboardProxy->>OnboardProxy: proceed with pull/load sequence
    OnboardProxy-->>TUI: model ready / streaming responses
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 I sniffed the Ollama paths beneath the dew,
I ask which models know the tools they use,
If one says "no", I tap a gentle clue,
Suggest starter names so streams stay true,
Hooray — the TUI hops along anew!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a warning for Ollama models without tools capability during onboarding.
Linked Issues check ✅ Passed The PR addresses the linked issue #2667 by detecting models without tool support and warning users with actionable guidance, including capability checking and user-friendly error messages.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the stated objectives: capability probing, warning mechanisms, tool-support gating, and comprehensive tests for Ollama tools capability.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/ollama-tools-capability.test.ts`:
- Around line 236-238: The cast on localInference is too direct; update it to go
through unknown first to satisfy TypeScript (i.e., cast localInference to
unknown then to Record<string, unknown>) before assigning
probeOllamaModelCapabilities so the assignment to SHARED.scriptedCaps is
type-safe; locate the expression using localInference and
probeOllamaModelCapabilities and replace the direct cast with the intermediate
unknown cast.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a88c8b90-13dd-4243-9178-3f75cf64b1d3

📥 Commits

Reviewing files that changed from the base of the PR and between 3800964 and ad2615a.

📒 Files selected for processing (3)
  • src/lib/local-inference.ts
  • src/lib/onboard-ollama-proxy.ts
  • test/ollama-tools-capability.test.ts

Comment thread test/ollama-tools-capability.test.ts Outdated
CodeRabbit and CI typecheck flagged the direct
`localInference as Record<string, unknown>` cast as a non-overlapping
type assertion. Use the documented `as unknown as ...` pattern.

Signed-off-by: Tony Luo <xialuo@nvidia.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/ollama-tools-capability.test.ts`:
- Around line 230-266: The proxy module is cached and can be loaded before our
stubs are installed, causing order-dependent tests; in loadProxyWithStubs() call
the installSharedStubs() first (already done) and then clear Node's require
cache for the onboard proxy module (resolve ONBOARD_OLLAMA_PROXY_PATH and delete
its entry from require.cache) before requiring it so the module re-evaluates and
picks up the patched probeOllamaModelCapabilities and credential.prompt stubs;
keep SHARED resets and then require the proxy as before.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: f2d578d6-1436-46e4-8381-31d0630fe91a

📥 Commits

Reviewing files that changed from the base of the PR and between ad2615a and 5b4e9b7.

📒 Files selected for processing (1)
  • test/ollama-tools-capability.test.ts

Comment thread test/ollama-tools-capability.test.ts
CodeRabbit flagged that loadProxyWithStubs reuses the cached
onboard-ollama-proxy module. The proxy destructures
probeOllamaModelCapabilities at module load, so if another test file
loaded it first, the cached copy is bound to the original probe and
our stub never takes effect.

Delete require.cache for the proxy path before re-requiring, so the
fresh module run picks up the stubbed local-inference exports.

Signed-off-by: Tony Luo <xialuo@nvidia.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread src/lib/local-inference.ts Outdated
@cv cv added the v0.0.36 label May 6, 2026
@cv pointed out the curated list of tools-capable Ollama models will
go stale fast (and was already out of date). Remove
TOOLS_CAPABLE_OLLAMA_MODELS and direct users to discover capabilities
themselves via 'ollama show <model>' — the same source of truth
NemoClaw probes during onboarding.

User-facing changes:
- Onboard warning: "Inspect a model's capabilities with `ollama show
  <model>` and pick one whose list includes 'tools'."
- Runtime error rewrite (validateOllamaModel): same guidance, no
  recommended models.

Test assertion updated to check for the `ollama show` guidance instead
of the (now removed) hardcoded list membership.

Signed-off-by: Tony Luo <xialuo@nvidia.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@TonyLuo-NV
TonyLuo-NV requested a review from cv May 6, 2026 07:42
@cv
cv merged commit 7b2cacf into NVIDIA:main May 6, 2026
13 checks passed
@TonyLuo-NV
TonyLuo-NV deleted the feat/2667-ollama-tools-capability-check branch May 6, 2026 08:14
miyoungc added a commit that referenced this pull request May 7, 2026
## Summary
- Bump docs metadata to 0.0.36 and refresh generated NemoClaw user
skills.
- Document Model Router onboarding, validation retries, Ollama tool
checks, Hermes policy behavior, and deployment verification updates.
- Remove suppressed experimental command references from public docs per
`docs/.docs-skip`.

## Source summary
- #2202 -> `docs/get-started/quickstart.md`,
`docs/inference/inference-options.md`, `docs/reference/architecture.md`:
Document Model Router setup and routed inference architecture.
- #3128 -> `docs/get-started/quickstart.md`,
`docs/reference/commands.md`: Document deployment verification and HTTP
401 health handling.
- #3104 -> `docs/inference/inference-options.md`: Document retry
behavior for transient provider validation failures.
- #3121 -> `docs/reference/architecture.md`: Document agent-scoped
model/provider compatibility manifests.
- #3046 -> `docs/reference/architecture.md`: Tie model-specific
compatibility setup to known model/provider behavior.
- #3097 -> `docs/inference/use-local-inference.md`: Document Ollama
tool-calling capability validation.
- #3082 -> `docs/reference/commands.md`: Document
`NEMOCLAW_SANDBOX_NAME` as the interactive sandbox-name default.
- f586cc5, 3442adf -> `docs/get-started/quickstart-hermes.md`,
`docs/reference/network-policies.md`: Document Hermes agent-specific
baseline policy endpoints.

## Test plan
- `python3 scripts/docs-to-skills.py docs/ .agents/skills/ --prefix
nemoclaw-user`
- `make docs`
- `npm run build:cli`
- `rg` skip-term scan for `docs/` and generated user skills

Made with [Cursor](https://cursor.com)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Model Router provider for complexity-based routed inference.
* Ollama/local inference onboarding now validates tool-calling
capability.
  * Added `local-inference` network policy preset.

* **Documentation**
* New integration policy examples (Outlook, Telegram, Slack, Discord,
GitHub, Jira, etc.).
  * Clarified config immutability workflow and sandbox writable paths.
  * Hermes baseline network policy documented.

* **Improvements**
* Health checks treat device-auth responses as live; transient
validation retries.
* Installer performs pre-install reachability checks; CLI onboarding
gained a --fresh option.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@wscurran wscurran added the feature PR adds or expands user-visible functionality label Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature PR adds or expands user-visible functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] HTTP 400 local ollama model dose not support tools

3 participants