7.9 KiB
Ollama Integration
This document describes the current local Ollama integration in the Python claw-code workspace, the features the harness uses today, and the commands to exercise them.
It is intended as a reference for future API cleanup, provider abstraction work, or deeper tool integrations.
Scope
The current Ollama integration lives in the Python workspace:
src/llm_backend.py: low-level/api/chatclientsrc/task.py: one-shot local chat wrappersrc/runtime_tools.py: executable workspace toolssrc/agent_loop.py: multi-turn agent loop with tool usesrc/main.py: CLI entrypoints
Default Configuration
- Host:
http://localhost:11434 - Default model:
qwen2.5-coder:7b - Endpoint:
POST /api/chat - Transport: one non-streaming request per turn
Ollama Features Currently Used
1. Chat messages
The harness sends standard Ollama chat messages:
{
"model": "qwen2.5-coder:7b",
"messages": [
{"role": "system", "content": "..."},
{"role": "user", "content": "..."}
],
"stream": false
}
Used by:
python3 -m src.main chat ...python3 -m src.main agent ...
2. Non-streaming responses
The harness currently uses stream: false.
That means:
- each turn waits for a full Ollama response
- the Python agent loop is simpler
- there is no token-by-token terminal rendering yet
This is fine for early harness integration, but future work could add streaming for better UX and partial tool-call parsing.
3. JSON response mode
The agent path asks Ollama for JSON output:
{
"format": "json"
}
This is only used in agent mode. It makes the model return structured responses like:
{"type":"tool_call","name":"read_file","arguments":{"path":"src/main.py"}}
or:
{"type":"final","content":"..."}
4. Ollama options
The agent path currently sets:
{
"options": {
"temperature": 0
}
}
Reason:
- lower randomness improves protocol adherence
- weaker local models are less likely to drift away from the JSON tool format
5. Multi-turn conversation state
The one-shot chat command sends a single system+user turn.
The agent command maintains a growing message list across turns:
- system instructions
- original user prompt
- assistant JSON tool call
- synthetic user
TOOL_RESULT ...message - final assistant answer
This is the core mechanism that lets Ollama use local harness tools.
Tool Protocol
Agent mode expects exactly one JSON object from the model on each turn.
Valid shapes:
{"type":"tool_call","name":"read_file","arguments":{"path":"src/main.py"}}
{"type":"final","content":"Summary goes here."}
If the model returns invalid JSON or tries to answer directly without using a required tool, the harness will:
- reject the response
- ask the model to follow the protocol again
- for obvious prompt shapes, synthesize a fallback first tool call
Executable Tools Available Today
The current agent exposes these real tools:
read_file
Arguments:
path- optional
start_line - optional
end_line
Behavior:
- reads a file inside the workspace root
- returns numbered lines
- rejects paths outside the workspace
search_files
Arguments:
pattern- optional
path - optional
max_results
Behavior:
- uses
rgwhen available - falls back to a Python file scan otherwise
- returns
path:line:contentmatches
edit_file
Arguments:
pathnew_text- optional
old_text
Behavior:
- creates a new file when the target does not exist and
old_textis omitted - replaces exactly one matching snippet in an existing file
- rejects ambiguous multi-match replacements
run_shell_command
Arguments:
command- optional
timeout_seconds
Behavior:
- runs inside the workspace root
- captures stdout, stderr, and exit code
- marks non-zero exit as failure
CLI Commands
One-shot local chat
Use this when you only want a plain local model response and do not need tool use.
python3 -m src.main chat "write a hello world in python"
Override model or host:
python3 -m src.main chat --model qwen2.5-coder:7b --host http://localhost:11434 "summarize this repo"
Pipe stdin:
printf 'summarize src/main.py' | python3 -m src.main chat
Agent mode with tool use
Use this when the task requires reading files, searching code, editing files, or running commands.
python3 -m src.main agent "read src/main.py lines 1 to 40 and summarize the CLI"
Search the workspace:
python3 -m src.main agent "search the src tree for 'agent_parser' and tell me which file contains it"
Edit a file:
python3 -m src.main agent "create tmp_test.txt containing hello harness"
Run shell commands:
python3 -m src.main agent "run 'pwd' and 'ls src | head' and summarize the results"
Agent trace mode
Use --trace to verify that the model actually called a harness tool.
python3 -m src.main agent --trace "read src/main.py lines 1 to 40 and quote the subcommands you find"
Expected stderr output looks like:
[trace] assistant_raw[1]={"type":"tool_call","name":"read_file","arguments":{"path":"src/main.py","start_line":1,"end_line":40}}
[trace] tool_call[1]=read_file {"path": "src/main.py", "start_line": 1, "end_line": 40}
[trace] tool_result[1]=read_file success=True error=None
[trace] assistant_raw[2]={"type":"final","content":"..."}
Deny tools
You can block specific tools or prefixes in agent mode:
python3 -m src.main agent --deny-tool run_shell_command "inspect this repo"
python3 -m src.main agent --deny-prefix read "inspect src/main.py"
Prompt Shapes That Work Best
Local models follow the protocol more reliably when prompts are concrete.
Good:
read src/main.py lines 1 to 40 and list the subcommandssearch the src tree for 'agent_parser'run 'pwd' and 'ls src | head' and summarize the resultscreate tmp_test.txt containing hello harness
Weaker:
inspect the codebaselook around and tell me what you think
Reason:
- concrete prompts make it easier for the harness to infer the correct first tool call when the model hesitates
Current Limitations
- no streaming responses yet
- no native Ollama function-calling schema; this is prompt+JSON protocol driven
- no patch-based editing tool yet, only exact text replacement or file creation
- shell execution is real but still minimal; there is no deep safety policy beyond workspace scoping and CLI deny lists
- the agent does not yet plan complex multi-step edits as well as a stronger hosted model
Suggested Next API Improvements
If you extend this integration later, these are the next sensible upgrades:
- Add streaming support to
/api/chat - Separate model protocol logic from tool orchestration
- Introduce a stronger typed schema for tool calls and tool results
- Add patch-style file editing instead of exact-text replacement only
- Add richer shell permission policies
- Store traces and tool transcripts in sessions
- Move Ollama into a provider abstraction so local and hosted models share one agent runtime
Quick Verification Checklist
Before building on this integration, verify:
ollama serveis running- the target model is available locally
python3 -m src.main chat "hello"workspython3 -m src.main agent --trace "read src/main.py lines 1 to 20"shows a realtool_call
Example End-to-End Session
Command:
python3 -m src.main agent --trace "search the src tree for 'agent_parser' and tell me which file contains it"
Observed behavior:
- Ollama returns
{"type":"tool_call","name":"search_files",...} - the harness executes
search_files - the harness feeds back
TOOL_RESULT {...} - Ollama returns
{"type":"final","content":"..."}
That is the current definition of "real harness tool use" for the local Ollama path.