Let a local model delegate `openagents coder --model ollama:<name>` answered from a local model but could not delegate, while the same session on a thread could. The gap was not the model: `qwen3.8:27b` reports the `tools` capability and emits a correct `delegate` call when it is offered one. The gap was that tools were declared on the thread rather than on whatever was answering, and `OllamaReplySource` implemented `reply` only, so a local session had no tool runtime to reach. Tools are the client's, not the transport's, so `ReplySource` now carries an optional `useTools`. A source opts in by running the calls a model asks for and reporting them as chunks; one that cannot leaves it undefined, and the session then declares no tools rather than declaring tools nothing runs. `OllamaReplySource` implements it with the same shape as the thread lane: a turn is a loop, the model answers or asks for tools and then answers once it has seen what they returned, and `MAX_TOOL_STEPS` stops a model that only ever delegates. Two differences are Ollama's, not ours. It hands back parsed arguments where the chat lane sends JSON source, so the chunk carries the source the renderer shows and the tool receives the object. It numbers no calls, so the id is this session's own, stable between a `tool_call` and its `tool_result`. An Ollama session now reads the stored credential it used to skip. It still opens no thread of its own -- the parent answers locally, spends nothing, and sends nothing to the chat API -- but children hold a server grant, so a local session delegates exactly as a thread session does. Without a credential it behaves as before. `--child-model` still runs children on a named model instead. The request now carries a snapshot of the transcript. It was passing the live array, which kept growing while the round streamed. Verified against the running server: a local qwen parent called `delegate`, a granted child answered, and the parent reported it. 276 tests pass.
Let a local model delegate
Deploy story
What this commit did to the running system — joined from the forge receipt chain, the part a commit page elsewhere cannot show.
Not deployed through the forge lane
No push, promotion, build, or deploy receipt references this commit (receipts are scanned over a bounded recent window). Changes shipped by full node replacement carry their proof in the release gate receipt instead.
Changed files
-
modified
docs/assure-repo/false-green-candidates.v1.json -
modified
docs/assure-repo/surface-inventory.v1.json -
modified
packages/openagents-cli/src/cli.ts -
modified
packages/openagents-cli/src/coder-ollama.ts -
modified
packages/openagents-cli/src/coder-session.ts -
added
packages/openagents-cli/test/coder-ollama.test.ts
Diff
6 files changed, +347 -38
docs/assure-repo/false-green-candidates.v1.json modified +1 -1
@@ -4,7 +4,7 @@
| 4 | 4 |
|
| 5 | 5 |
|
| 6 | 6 |
|
| 7 |
|
|
| 7 |
|
|
| 8 | 8 |
|
| 9 | 9 |
|
| 10 | 10 |
|
docs/assure-repo/surface-inventory.v1.json modified +2 -2
@@ -1,7 +1,7 @@
| 1 | 1 |
|
| 2 | 2 |
|
| 3 | 3 |
|
| 4 |
|
|
| 4 |
|
|
| 5 | 5 |
|
| 6 | 6 |
|
| 7 | 7 |
|
packages/openagents-cli/src/cli.ts modified +9 -5
@@ -23,6 +23,7 @@ import { DelegateFleet, describePrompt, OpencodeHarness } from "./coder-delegate
| 23 | 23 |
|
| 24 | 24 |
|
| 25 | 25 |
|
| 26 |
|
|
| 26 | 27 |
|
| 27 | 28 |
|
| 28 | 29 |
|
@@ -1664,8 +1665,11 @@ const coderCommand = Command.make(
| 1664 | 1665 |
|
| 1665 | 1666 |
|
| 1666 | 1667 |
|
| 1668 |
|
|
| 1669 |
|
|
| 1670 |
|
|
| 1667 | 1671 |
|
| 1668 |
|
|
| 1672 |
|
|
| 1669 | 1673 |
|
| 1670 | 1674 |
|
| 1671 | 1675 |
|
@@ -1692,7 +1696,7 @@ const coderCommand = Command.make(
| 1692 | 1696 |
|
| 1693 | 1697 |
|
| 1694 | 1698 |
|
| 1695 |
|
|
| 1699 |
|
|
| 1696 | 1700 |
|
| 1697 | 1701 |
|
| 1698 | 1702 |
|
@@ -1701,7 +1705,7 @@ const coderCommand = Command.make(
| 1701 | 1705 |
|
| 1702 | 1706 |
|
| 1703 | 1707 |
|
| 1704 |
|
|
| 1708 |
|
|
| 1705 | 1709 |
|
| 1706 | 1710 |
|
| 1707 | 1711 |
|
@@ -1736,8 +1740,8 @@ const coderCommand = Command.make(
| 1736 | 1740 |
|
| 1737 | 1741 |
|
| 1738 | 1742 |
|
| 1739 |
|
|
| 1740 |
|
|
| 1743 |
|
|
| 1744 |
|
|
| 1741 | 1745 |
|
| 1742 | 1746 |
|
| 1743 | 1747 |
|
packages/openagents-cli/src/coder-ollama.ts modified +150 -30
@@ -12,11 +12,22 @@
| 12 | 12 |
|
| 13 | 13 |
|
| 14 | 14 |
|
| 15 |
|
|
| 15 | 16 |
|
| 16 | 17 |
|
| 18 |
|
|
| 17 | 19 |
|
| 18 | 20 |
|
| 19 | 21 |
|
| 22 |
|
|
| 23 |
|
|
| 24 |
|
|
| 25 |
|
|
| 26 |
|
|
| 27 |
|
|
| 28 |
|
|
| 29 |
|
|
| 30 |
|
|
| 20 | 31 |
|
| 21 | 32 |
|
| 22 | 33 |
|
@@ -33,15 +44,21 @@ export const parseOllamaModelFlag = (value: string): string | undefined => {
| 33 | 44 |
|
| 34 | 45 |
|
| 35 | 46 |
|
| 36 |
|
|
| 37 |
|
|
| 38 |
|
|
| 39 |
|
|
| 47 |
|
|
| 48 |
|
|
| 49 |
|
|
| 50 |
|
|
| 51 |
|
|
| 52 |
|
|
| 53 |
|
|
| 54 |
|
|
| 40 | 55 |
|
| 41 | 56 |
|
| 42 | 57 |
|
| 43 | 58 |
|
| 44 | 59 |
|
| 60 |
|
|
| 61 |
|
|
| 45 | 62 |
|
| 46 | 63 |
|
| 47 | 64 |
|
@@ -52,41 +69,144 @@ export class OllamaReplySource implements ReplySource {
| 52 | 69 |
|
| 53 | 70 |
|
| 54 | 71 |
|
| 72 |
|
|
| 73 |
|
|
| 74 |
|
|
| 75 |
|
|
| 76 |
|
|
| 77 |
|
|
| 78 |
|
|
| 79 |
|
|
| 80 |
|
|
| 81 |
|
|
| 82 |
|
|
| 55 | 83 |
|
| 56 | 84 |
|
| 57 | 85 |
|
| 58 |
|
|
| 59 |
|
|
| 60 |
|
|
| 61 |
|
|
| 62 |
|
|
| 63 |
|
|
| 64 |
|
|
| 65 |
|
|
| 66 |
|
|
| 86 |
|
|
| 87 |
|
|
| 88 |
|
|
| 89 |
|
|
| 90 |
|
|
| 91 |
|
|
| 92 |
|
|
| 93 |
|
|
| 94 |
|
|
| 95 |
|
|
| 96 |
|
|
| 97 |
|
|
| 98 |
|
|
| 99 |
|
|
| 100 |
|
|
| 101 |
|
|
| 102 |
|
|
| 103 |
|
|
| 104 |
|
|
| 105 |
|
|
| 106 |
|
|
| 107 |
|
|
| 108 |
|
|
| 109 |
|
|
| 110 |
|
|
| 111 |
|
|
| 112 |
|
|
| 113 |
|
|
| 114 |
|
|
| 115 |
|
|
| 116 |
|
|
| 117 |
|
|
| 118 |
|
|
| 119 |
|
|
| 120 |
|
|
| 121 |
|
|
| 122 |
|
|
| 123 |
|
|
| 124 |
|
|
| 125 |
|
|
| 126 |
|
|
| 127 |
|
|
| 128 |
|
|
| 129 |
|
|
| 130 |
|
|
| 131 |
|
|
| 132 |
|
|
| 133 |
|
|
| 134 |
|
|
| 135 |
|
|
| 136 |
|
|
| 137 |
|
|
| 138 |
|
|
| 139 |
|
|
| 140 |
|
|
| 141 |
|
|
| 142 |
|
|
| 143 |
|
|
| 144 |
|
|
| 145 |
|
|
| 67 | 146 |
|
| 68 |
|
|
| 69 |
|
|
| 70 |
|
|
| 147 |
|
|
| 71 | 148 |
|
| 72 |
|
|
| 73 |
|
|
| 74 |
|
|
| 75 |
|
|
| 149 |
|
|
| 150 |
|
|
| 151 |
|
|
| 152 |
|
|
| 153 |
|
|
| 154 |
|
|
| 155 |
|
|
| 76 | 156 |
|
| 77 |
|
|
| 78 |
|
|
| 79 |
|
|
| 80 |
|
|
| 81 |
|
|
| 157 |
|
|
| 82 | 158 |
|
| 83 |
|
|
| 159 |
|
|
| 160 |
|
|
| 161 |
|
|
| 84 | 162 |
|
| 85 |
|
|
| 86 |
|
|
| 87 |
|
|
| 88 |
|
|
| 163 |
|
|
| 164 |
|
|
| 165 |
|
|
| 166 |
|
|
| 167 |
|
|
| 168 |
|
|
| 169 |
|
|
| 170 |
|
|
| 171 |
|
|
| 172 |
|
|
| 173 |
|
|
| 174 |
|
|
| 175 |
|
|
| 176 |
|
|
| 177 |
|
|
| 178 |
|
|
| 179 |
|
|
| 180 |
|
|
| 181 |
|
|
| 182 |
|
|
| 183 |
|
|
| 184 |
|
|
| 185 |
|
|
| 186 |
|
|
| 187 |
|
|
| 188 |
|
|
| 189 |
|
|
| 190 |
|
|
| 191 |
|
|
| 192 |
|
|
| 193 |
|
|
| 194 |
|
|
| 195 |
|
|
| 196 |
|
|
| 197 |
|
|
| 198 |
|
|
| 199 |
|
|
| 200 |
|
|
| 201 |
|
|
| 202 |
|
|
| 203 |
|
|
| 204 |
|
|
| 89 | 205 |
|
| 90 | 206 |
|
| 207 |
|
|
| 208 |
|
|
| 209 |
|
|
| 210 |
|
|
| 91 | 211 |
|
| 92 | 212 |
|
packages/openagents-cli/src/coder-session.ts modified +10
@@ -22,6 +22,7 @@
| 22 | 22 |
|
| 23 | 23 |
|
| 24 | 24 |
|
| 25 |
|
|
| 25 | 26 |
|
| 26 | 27 |
|
| 27 | 28 |
|
@@ -122,6 +123,15 @@ export interface ReplySource {
| 122 | 123 |
|
| 123 | 124 |
|
| 124 | 125 |
|
| 126 |
|
|
| 127 |
|
|
| 128 |
|
|
| 129 |
|
|
| 130 |
|
|
| 131 |
|
|
| 132 |
|
|
| 133 |
|
|
| 134 |
|
|
| 125 | 135 |
|
| 126 | 136 |
|
| 127 | 137 |
|
packages/openagents-cli/test/coder-ollama.test.ts added +175
@@ -0,0 +1,175 @@
| 1 |
|
|
| 2 |
|
|
| 3 |
|
|
| 4 |
|
|
| 5 |
|
|
| 6 |
|
|
| 7 |
|
|
| 8 |
|
|
| 9 |
|
|
| 10 |
|
|
| 11 |
|
|
| 12 |
|
|
| 13 |
|
|
| 14 |
|
|
| 15 |
|
|
| 16 |
|
|
| 17 |
|
|
| 18 |
|
|
| 19 |
|
|
| 20 |
|
|
| 21 |
|
|
| 22 |
|
|
| 23 |
|
|
| 24 |
|
|
| 25 |
|
|
| 26 |
|
|
| 27 |
|
|
| 28 |
|
|
| 29 |
|
|
| 30 |
|
|
| 31 |
|
|
| 32 |
|
|
| 33 |
|
|
| 34 |
|
|
| 35 |
|
|
| 36 |
|
|
| 37 |
|
|
| 38 |
|
|
| 39 |
|
|
| 40 |
|
|
| 41 |
|
|
| 42 |
|
|
| 43 |
|
|
| 44 |
|
|
| 45 |
|
|
| 46 |
|
|
| 47 |
|
|
| 48 |
|
|
| 49 |
|
|
| 50 |
|
|
| 51 |
|
|
| 52 |
|
|
| 53 |
|
|
| 54 |
|
|
| 55 |
|
|
| 56 |
|
|
| 57 |
|
|
| 58 |
|
|
| 59 |
|
|
| 60 |
|
|
| 61 |
|
|
| 62 |
|
|
| 63 |
|
|
| 64 |
|
|
| 65 |
|
|
| 66 |
|
|
| 67 |
|
|
| 68 |
|
|
| 69 |
|
|
| 70 |
|
|
| 71 |
|
|
| 72 |
|
|
| 73 |
|
|
| 74 |
|
|
| 75 |
|
|
| 76 |
|
|
| 77 |
|
|
| 78 |
|
|
| 79 |
|
|
| 80 |
|
|
| 81 |
|
|
| 82 |
|
|
| 83 |
|
|
| 84 |
|
|
| 85 |
|
|
| 86 |
|
|
| 87 |
|
|
| 88 |
|
|
| 89 |
|
|
| 90 |
|
|
| 91 |
|
|
| 92 |
|
|
| 93 |
|
|
| 94 |
|
|
| 95 |
|
|
| 96 |
|
|
| 97 |
|
|
| 98 |
|
|
| 99 |
|
|
| 100 |
|
|
| 101 |
|
|
| 102 |
|
|
| 103 |
|
|
| 104 |
|
|
| 105 |
|
|
| 106 |
|
|
| 107 |
|
|
| 108 |
|
|
| 109 |
|
|
| 110 |
|
|
| 111 |
|
|
| 112 |
|
|
| 113 |
|
|
| 114 |
|
|
| 115 |
|
|
| 116 |
|
|
| 117 |
|
|
| 118 |
|
|
| 119 |
|
|
| 120 |
|
|
| 121 |
|
|
| 122 |
|
|
| 123 |
|
|
| 124 |
|
|
| 125 |
|
|
| 126 |
|
|
| 127 |
|
|
| 128 |
|
|
| 129 |
|
|
| 130 |
|
|
| 131 |
|
|
| 132 |
|
|
| 133 |
|
|
| 134 |
|
|
| 135 |
|
|
| 136 |
|
|
| 137 |
|
|
| 138 |
|
|
| 139 |
|
|
| 140 |
|
|
| 141 |
|
|
| 142 |
|
|
| 143 |
|
|
| 144 |
|
|
| 145 |
|
|
| 146 |
|
|
| 147 |
|
|
| 148 |
|
|
| 149 |
|
|
| 150 |
|
|
| 151 |
|
|
| 152 |
|
|
| 153 |
|
|
| 154 |
|
|
| 155 |
|
|
| 156 |
|
|
| 157 |
|
|
| 158 |
|
|
| 159 |
|
|
| 160 |
|
|
| 161 |
|
|
| 162 |
|
|
| 163 |
|
|
| 164 |
|
|
| 165 |
|
|
| 166 |
|
|
| 167 |
|
|
| 168 |
|
|
| 169 |
|
|
| 170 |
|
|
| 171 |
|
|
| 172 |
|
|
| 173 |
|
|
| 174 |
|
|
| 175 |
|