Skip to content

Commit 3a50868

Browse files
committed
docs: Ollama tool-call retry adapter documentation for issue #205
1 parent 5d20139 commit 3a50868

2 files changed

Lines changed: 114 additions & 0 deletions

File tree

docs/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
*
77
!.gitignore
88
!golden-principles.md
9+
!ollama_tool_call_adapter.md

docs/ollama_tool_call_adapter.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Ollama Tool-Call Retry Adapter
2+
3+
## Problem
4+
5+
When using Ollama models with OpenKB's `query` and `chat` commands, the
6+
openai-agents SDK tool-calling loop frequently fails because small local
7+
models hallucinate tool names instead of calling the registered tools.
8+
9+
For example, when the only registered tool is `read_file`, a model may
10+
attempt to call `get_topics`, `search_strategy`, or `system` — none of
11+
which exist. The SDK then raises:
12+
13+
```
14+
ModelBehaviorError: Tool search_strategy not found in agent wiki-query
15+
```
16+
17+
and the entire query aborts with no recovery.
18+
19+
This affects all Ollama models tested (issue #205):
20+
| Model | Symptom |
21+
|---|---|
22+
| `llama3.1:8b` | raw tool-call JSON; no final answer |
23+
| `qwen3:14b` | `{}` |
24+
| `qwen3.5:9b` | empty output |
25+
| `gemma4:12b` | timed out |
26+
| `deepseek-r1:14b` | `{}` |
27+
| `qwen2.5-coder:14b` | raw/incomplete response |
28+
| `llama3.2:1b` | raw function-call JSON |
29+
30+
## Solution
31+
32+
OpenKB now includes a **retry adapter** (`openkb/agent/ollama_adapter.py`)
33+
that intercepts `ModelBehaviorError` and retries the query with a
34+
corrective system message:
35+
36+
```
37+
[SYSTEM CORRECTION 1] You tried to call a tool named 'get_topics',
38+
but that tool does not exist. The only available tools are:
39+
read_file, get_page_content, get_image. Please answer the original
40+
question using ONLY these tools. Do not invent tool names.
41+
```
42+
43+
The retry adapter is **Ollama-only** — all other providers (OpenAI,
44+
Anthropic, Gemini, etc.) keep the original bare-Runner behaviour
45+
unchanged.
46+
47+
## How It Works
48+
49+
### Detection
50+
51+
`is_ollama_backend(model)` returns `True` for model strings matching:
52+
- `ollama/llama3.2:1b` (LiteLLM prefix)
53+
- `litellm/ollama/llama3.2:1b` (Agent-layer prefix used by OpenKB)
54+
55+
### Retry Flow
56+
57+
1. The agent runs normally via `Runner.run()` / `Runner.run_streamed()`.
58+
2. If `ModelBehaviorError` is raised, the bad tool name is extracted
59+
from the error message.
60+
3. A corrective user message is appended to the input.
61+
4. The run is retried (up to `max_retries` times, default 3).
62+
5. If all retries are exhausted, the original error is re-raised.
63+
64+
### Streaming
65+
66+
For streamed queries, `_RetryableStreamResult` wraps the `RunResult` and
67+
intercepts `stream_events()`. If a `ModelBehaviorError` occurs mid-stream,
68+
the wrapper re-creates the stream with a corrective message and continues
69+
yielding events seamlessly.
70+
71+
## Configuration
72+
73+
The retry behaviour is automatic for Ollama models. No configuration is
74+
required. The default retry count is 3.
75+
76+
Future config options (not yet implemented):
77+
78+
```yaml
79+
ollama:
80+
tool_call_retries: 3 # max retry attempts (default 3)
81+
correct_tool_names: true # enable tool-name correction (default true)
82+
```
83+
84+
## Files
85+
86+
| File | Description |
87+
|---|---|
88+
| `openkb/agent/ollama_adapter.py` | Retry adapter module |
89+
| `openkb/agent/query.py` | Patched to use adapter for Ollama models |
90+
| `tests/test_ollama_adapter.py` | 26 unit tests |
91+
92+
## Testing
93+
94+
```bash
95+
# Run adapter tests
96+
python -m pytest tests/test_ollama_adapter.py -v
97+
98+
# Run full test suite (non-Ollama path unchanged)
99+
python -m pytest tests/ -q
100+
```
101+
102+
## Limitations
103+
104+
- Very small models (e.g. `llama3.2:1b`, 1B params) may fail even after
105+
retries — they are simply too small to follow tool-use instructions
106+
reliably. The adapter recovers the crash but cannot fix the model's
107+
fundamental inability.
108+
- The adapter does not modify the model's output format. If a model
109+
returns tool-call JSON in the `content` field instead of `tool_calls`,
110+
the SDK will still not execute the tool. A future enhancement could
111+
add content-to-tool-call extraction.
112+
- Timeout handling is not modified. Models that time out will still
113+
time out; the retry adapter only handles `ModelBehaviorError`.

0 commit comments

Comments
 (0)