@tangle-network/agent-runtime 0.87.0 → 0.88.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.js +3 -3
- package/dist/analyst-loop.js +2 -2
- package/dist/{chunk-VKVNDNG4.js → chunk-22HPUH77.js} +272 -142
- package/dist/chunk-22HPUH77.js.map +1 -0
- package/dist/{chunk-QUXZBZCS.js → chunk-FVJ7M3DA.js} +1 -1
- package/dist/chunk-FVJ7M3DA.js.map +1 -0
- package/dist/{chunk-FLVVVBWV.js → chunk-HBE77SWV.js} +4 -4
- package/dist/{chunk-MHYF2LIP.js → chunk-JHULWWQD.js} +2 -2
- package/dist/{chunk-6XCW3M7W.js → chunk-LRNRPJAV.js} +282 -34
- package/dist/chunk-LRNRPJAV.js.map +1 -0
- package/dist/{chunk-LCXXIL3U.js → chunk-ZQZX77MM.js} +2 -2
- package/dist/index.js +6 -6
- package/dist/loop-runner-bin.js +5 -5
- package/dist/loops.d.ts +209 -5
- package/dist/loops.js +15 -3
- package/dist/mcp/bin.js +2 -2
- package/dist/mcp/index.js +4 -4
- package/package.json +2 -2
- package/skills/build-with-agent-runtime/SKILL.md +6 -0
- package/skills/loop-writer/SKILL.md +73 -0
- package/dist/chunk-6XCW3M7W.js.map +0 -1
- package/dist/chunk-QUXZBZCS.js.map +0 -1
- package/dist/chunk-VKVNDNG4.js.map +0 -1
- /package/dist/{chunk-FLVVVBWV.js.map → chunk-HBE77SWV.js.map} +0 -0
- /package/dist/{chunk-MHYF2LIP.js.map → chunk-JHULWWQD.js.map} +0 -0
- /package/dist/{chunk-LCXXIL3U.js.map → chunk-ZQZX77MM.js.map} +0 -0
|
@@ -30,6 +30,7 @@ The driver owns strategy.
|
|
|
30
30
|
| Review from several lenses | `panel` |
|
|
31
31
|
| Simulated user/product eval | `defineConversation` + `runConversation` |
|
|
32
32
|
| Dynamic topology / drivers of drivers | `Scope` or sandbox driver + `createCoordinationTools` |
|
|
33
|
+
| **A coded multi-round loop spawned + steered like a worker** | `defineLoop` + `loopChild` (the loop atom) |
|
|
33
34
|
| Mutate a shared repo | git branch/clone loop with typed merge outcomes |
|
|
34
35
|
|
|
35
36
|
If a fixed combinator solves it, do not use a dynamic driver.
|
|
@@ -114,6 +115,78 @@ When the driver lives in a sandbox, expose the same verbs through
|
|
|
114
115
|
`steer_worker`, `list_questions`, `answer_question`, `ask_parent`, `stop`, and
|
|
115
116
|
optional analyst tools.
|
|
116
117
|
|
|
118
|
+
## The Loop Atom — a coded loop spawned like a worker
|
|
119
|
+
|
|
120
|
+
When the loop itself is the reusable unit (a research loop, a verify loop, an
|
|
121
|
+
evolve loop), make it a spawnable atom instead of a hand-driver. `defineLoop`
|
|
122
|
+
authors the body; the runtime owns the round ceiling, the conserved budget, the
|
|
123
|
+
gate, and steer-between-rounds. A supervisor spawns / observes / steers it with
|
|
124
|
+
the SAME coordination verbs as a worker.
|
|
125
|
+
|
|
126
|
+
Two ways to author the round. **`agents`** — a MULTI-AGENT loop as a declarative
|
|
127
|
+
CHAIN (the common case): an ordered list of named agents piped each round,
|
|
128
|
+
`task -> agents[0] -> agents[1] -> ... -> out`, each agent's return feeding the next
|
|
129
|
+
as `prior`. "Two agents" is self-evident from the list — no bespoke `runTwoAgent...`
|
|
130
|
+
function. **`round`** — freeform code for any other topology (fan-out, dynamic
|
|
131
|
+
routing). Provide exactly one.
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
// A two-agent research loop as a CHAIN: proposer drafts, verifier checks the draft.
|
|
135
|
+
const research = defineLoop('research', {
|
|
136
|
+
maxRounds: 3,
|
|
137
|
+
agents: [
|
|
138
|
+
{ name: 'proposer', run: async ({ scope, steer }, _prior) => {
|
|
139
|
+
const w = scope.spawn(researcher, { steer }, { budget: perRound, label: 'propose' })
|
|
140
|
+
if (!w.ok) throw new Error(w.reason)
|
|
141
|
+
return await scope.next() // the draft
|
|
142
|
+
} },
|
|
143
|
+
{ name: 'verifier', run: async ({ scope }, draft) => {
|
|
144
|
+
const w = scope.spawn(verifier, { draft }, { budget: perRound, label: 'verify' })
|
|
145
|
+
if (!w.ok) throw new Error(w.reason)
|
|
146
|
+
return await scope.next() // the verified result -> round out
|
|
147
|
+
} },
|
|
148
|
+
],
|
|
149
|
+
check: (out) => readinessPasses(out), // the deployable completion oracle
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
// Spawn it exactly like a worker (role:'loop' resolves to the loop-executor).
|
|
153
|
+
const r = scope.spawn(loopChild(research, journal), task, { budget, label: 'research-loop' })
|
|
154
|
+
// Wire once at the top: createInMemoryRunContext({ withDriver: true, withLoop: true }).
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
TOPOLOGY: `agents` is a sequential CHAIN only. It is NOT parallel and NOT a graph —
|
|
158
|
+
the loop's nested `scope.next()` is one shared queue, so parallel agents would steal
|
|
159
|
+
each other's settlements. For fan-out (a panel of critics, best-of-N), dynamic
|
|
160
|
+
routing, or any non-linear shape, use the freeform `round`: spawn every handle first,
|
|
161
|
+
then drain N times, or branch on the data yourself. `fanout`/`panel`/`pipeline` cover
|
|
162
|
+
the reactive-layer parallel case.
|
|
163
|
+
|
|
164
|
+
Rules: the loop is code, not the model's judgment — that is what makes maxRounds,
|
|
165
|
+
the budget, and the gate ENFORCED rather than hoped-for. Give the loop a real
|
|
166
|
+
`check` (an executable oracle, never a self-judged score). Budget nests: the pool
|
|
167
|
+
reserves each spawn's full ceiling until it settles, so pool > loop > per-round.
|
|
168
|
+
|
|
169
|
+
### Codemode — an LLM authors the loop at runtime
|
|
170
|
+
|
|
171
|
+
When the supervisor should WRITE the loop for a novel goal (not pick a hand-built
|
|
172
|
+
one), use `authorLoop` — the codemode seam over the atom, the sibling of
|
|
173
|
+
`authorStrategy`. It shows the model `loopAuthorContract` (the exact `defineLoop`
|
|
174
|
+
module shape, exported so a skill/GEPA pass can evolve it), extracts the fenced
|
|
175
|
+
module, lints it with `assertStrategyContract` (only the loops import; no
|
|
176
|
+
require/eval/fetch/process/node builtins), writes it, dynamic-imports it, and
|
|
177
|
+
validates the default export is a `LoopDef` — ready for `loopChild`.
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
const { loop } = await authorLoop({ chat, goal, maxRounds, outDir, fallbackModel })
|
|
181
|
+
const spawned = scope.spawn(loopChild(loop, journal), task, { budget, label: 'authored-loop' })
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Safety is structural, same as `authorStrategy`: the authored body can be WRONG
|
|
185
|
+
but cannot overspend (conserved pool), cannot skip the check (the runtime gates
|
|
186
|
+
it), and cannot reach outside the loops surface (the lint). Do not build a
|
|
187
|
+
per-product loop-code generator or a VM sandbox around authored loops — `authorLoop`
|
|
188
|
+
is that seam.
|
|
189
|
+
|
|
117
190
|
## Role Boundaries
|
|
118
191
|
|
|
119
192
|
- **Verifier**: executable shippability gate; controls accept/reject.
|