feat(agent): add native Ollama backend with tool-use loop#1095
Open
sanjay3290 wants to merge 1 commit intomultica-ai:mainfrom
Open
feat(agent): add native Ollama backend with tool-use loop#1095sanjay3290 wants to merge 1 commit intomultica-ai:mainfrom
sanjay3290 wants to merge 1 commit intomultica-ai:mainfrom
Conversation
Closes multica-ai#769. Ships a first-class `ollama` agent provider alongside claude/codex/opencode/openclaw/hermes/gemini. Models with `tools` capability (gemma3+, qwen2.5+, llama3.1+) drive the Multica CLI via a single shell tool; chat-only models still work for conversational tasks. End-to-end verified: gemma4:latest ran a 6-tool-call sequence on a Multica issue (read context, wrote a file, updated status, posted a comment, finished in 29s), and separately wrote a file to $HOME/Desktop via absolute-path shell command in 4 calls / 20s. Configuration: MULTICA_OLLAMA_HOST (default http://localhost:11434) MULTICA_OLLAMA_MODEL (required; empty = provider skipped) MULTICA_OLLAMA_SHELL_TIMEOUT (default 5m; per-command cap) MULTICA_OLLAMA_MAX_OUTPUT_BYTES (default 16384; tool-result cap) Daemon probes /api/tags for reachability, /api/version for version, /api/show for tool-capability (prints stderr WARNING if missing). All three calls are best-effort and do not block daemon startup. Architecture: - stream:false when tools are active (tool_calls arrive on final chunk anyway; single-shot is simpler and equally responsive at task level) - Single `shell` tool, executed via `bash -c` (NOT `-lc` — login shell would re-source /etc/profile and wipe the PATH injection the daemon makes for the multica CLI) - tool_call_id threaded on tool-role messages so strict models (qwen2.5, llama3.1) can correlate results to calls - MaxTurns cap (default 25) prevents runaway tool loops - Context status (DeadlineExceeded/Canceled) takes precedence over side-effect errors when determining final Result.Status — same pattern claude.go and gemini.go use post-PR multica-ai#920 v1 non-goals (documented): - Streaming during tool turns (loses token-by-token UX for tool-using tasks; chat-only non-tool tasks still get the final text as one MessageText event) - Per-task model selection (single configured model wins) - Session resume (Ollama is stateless; ResumeSessionID ignored) - Dynamic /api/tags discovery (operator picks model via env) - Granular tools (file_read, file_write, etc. — single shell covers the same ground via standard Unix utilities; matches Claude's bypassPermissions and Gemini's --yolo) Tests (22 total, all pass in 10s): - Single-turn chat, tool-loop 2-turn, tool_call_id wire propagation - Malformed response guards (both {done:true} empty, and OOM-case {role:assistant, content:"", tool_calls:[]}) - Shell exit codes forwarded to model; unknown tool returns error string without crashing; MaxTurns cap; timeout; cancel - Env helpers honor valid values and fall back on malformed/negative - /api/show capability probe (true, false, unreachable, 404) - /api/version probe; system-prompt forwarding; missing-model guard
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a first-class
ollamaagent provider alongside claude/codex/opencode/openclaw/hermes/gemini. Models withtoolscapability (gemma3+, qwen2.5+, llama3.1+) drive the Multica CLI via a single shell tool; chat-only models still work for conversational tasks.Closes #769.
Why
Issue #769 closed with the env-var workaround (#846) — pointing
ANTHROPIC_BASE_URLat Ollama. That works for users who've installed Claude Code, but Ollama-only users still need a supported CLI on their machine before anything works. This ships the real native path.End-to-end verified
gemma4:latestran a 6-tool-call sequence on a Multica issue — read context, wrote a file, updated status toin_review, posted a summary comment. 29s.$HOME/Desktop/multica-ollama-test.txtvia absolute-pathprintf, verified withls -l, posted output as comment. 4 calls / 20s.Configuration
Daemon probes
/api/tagsfor reachability,/api/versionfor version,/api/showfor tool capability (prints stderr WARNING if the configured model doesn't declare"tools"). All probes are best-effort and do not block daemon startup.Architecture
stream:falsewhen tools active — tool_calls arrive on the final chunk anyway; single-shot is simpler and equally responsive at task granularity.shelltool, executed viabash -c(NOT-lc; login shells re-source/etc/profileand wipe the PATH injection the daemon makes for themulticaCLI). Matches Claude'sbypassPermissionsand Gemini's--yolo.tool_call_idthreaded on tool-role messages so strict models (qwen2.5, llama3.1) can correlate results to calls.DeadlineExceeded/Canceled) takes precedence over side-effect errors when determiningResult.Status— matches the patternclaude.goandgemini.gouse after PR fix(daemon): correct Gemini backend status on timeout and cancellation #920.v1 non-goals (deliberate, documented)
ResumeSessionIDignored with debug log)/api/tagsmodel discoveryThese match the limitations Gemini #755 shipped with.
Test plan
go test ./pkg/agent/... ./internal/daemon/...— 22 new tests, all pass in 10sgo vet ./...cleangofmt -wappliedpnpm --filter @multica/views --filter @multica/core typecheckcleanollamaruntime, reports online, appears in/api/runtimes{role:assistant, content:"", tool_calls:[]}), MaxTurns cap, shell exit code forwarding, unknown tool,tool_call_idwire propagation, env-var fallback on malformed values,/api/showcapability probe (true/false/404/unreachable)Files changed
server/pkg/agent/ollama.go— new (609 LOC)server/pkg/agent/ollama_test.go— new (712 LOC)server/pkg/agent/agent.go— registercase "ollama";DetectVersionnow takes provider name to dispatch HTTP probe for HTTP-based backendsserver/internal/daemon/config.go— HTTP probe ofMULTICA_OLLAMA_HOST; capability check with WARNING; referencesagent.DefaultOllamaHostserver/internal/daemon/execenv/runtime_config.go—ollamaadded to the AGENTS.md caseserver/internal/daemon/daemon.go— one-line change to pass provider name intoDetectVersionpackages/views/runtimes/components/provider-logo.tsx—OllamaLogoSVG + switch case