@tangle-network/agent-runtime 0.86.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/mcp/index.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  import {
7
7
  mcpToolsForRuntimeMcp,
8
8
  mcpToolsForRuntimeMcpSubset
9
- } from "../chunk-U4TS65XZ.js";
9
+ } from "../chunk-JHULWWQD.js";
10
10
  import {
11
11
  createKbGate
12
12
  } from "../chunk-SGKPNBXE.js";
@@ -14,7 +14,7 @@ import {
14
14
  assertTraceDerivedFindings,
15
15
  runCoderChecks,
16
16
  selectValidWinner
17
- } from "../chunk-3TZOXS7B.js";
17
+ } from "../chunk-22HPUH77.js";
18
18
  import {
19
19
  DELEGATE_DESCRIPTION,
20
20
  DELEGATE_FEEDBACK_DESCRIPTION,
@@ -64,7 +64,7 @@ import {
64
64
  validateDelegateUiAuditArgs,
65
65
  validateDelegationHistoryArgs,
66
66
  validateDelegationStatusArgs
67
- } from "../chunk-F7OO2SKB.js";
67
+ } from "../chunk-LRNRPJAV.js";
68
68
  import "../chunk-UD4BHQMI.js";
69
69
  import {
70
70
  deleteBoxSafe,
@@ -72,7 +72,7 @@ import {
72
72
  throwAbort,
73
73
  throwIfAborted
74
74
  } from "../chunk-BZF3KQ6G.js";
75
- import "../chunk-4J6RBI3K.js";
75
+ import "../chunk-FVJ7M3DA.js";
76
76
  import {
77
77
  runLocalHarness
78
78
  } from "../chunk-7LO5GMAO.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-runtime",
3
- "version": "0.86.0",
3
+ "version": "0.88.0",
4
4
  "description": "Shared task-lifecycle skeleton for agents: a recursive loop kernel for chat turns, one-shot tasks, and multi-attempt loops, with trace capture and eval-gated self-improvement. Domain behavior lives in adapters; scoring and ship-gates in @tangle-network/agent-eval.",
5
5
  "homepage": "https://github.com/tangle-network/agent-runtime#readme",
6
6
  "repository": {
@@ -94,7 +94,7 @@
94
94
  },
95
95
  "devDependencies": {
96
96
  "@biomejs/biome": "^2.4.15",
97
- "@tangle-network/agent-eval": "^0.103.1",
97
+ "@tangle-network/agent-eval": "^0.103.2",
98
98
  "@tangle-network/agent-interface": ">=0.14.0 <1.0.0",
99
99
  "@tangle-network/sandbox": ">=0.8.0 <1.0.0",
100
100
  "@types/node": "^25.9.3",
@@ -64,8 +64,9 @@ agent-runtime's `AgentSpec { profile, harness }`. To sweep it as an eval axis,
64
64
  don't hand-declare a harness list — expand one base profile across
65
65
  `CODING_HARNESSES` with `expandProfileAxes` (agent-eval), run with
66
66
  `runProfileMatrix`, and pivot results by the stamped `AgentProfileCell`
67
- (`groupRunsByAgentProfileCell`); incompatible `(harness, model)` pairs drop via
68
- `harnessSupportsModel`.
67
+ (`groupRunsByAgentProfileCell`); `harnessSupportsModel` filters per harness,
68
+ and a vendor-locked harness that supports none of the requested models SNAPS
69
+ to its native default (`HARNESS_NATIVE_MODEL`) — never silently dropped.
69
70
 
70
71
  | Altitude — I want to… | Use | Source |
71
72
  |---|---|---|
@@ -77,9 +78,15 @@ don't hand-declare a harness list — expand one base profile across
77
78
  | **Produce-then-gate / multi-judge quorum / fixed chain** | `verify` / `panel` / `pipeline` — `/loops` | canonical-api §3.1 |
78
79
  | **Run depth-vs-breadth (or a custom strategy) over a stateful tool domain** | `runAgentic({ surface, task, mode\|strategy, budget })` — `/loops` | canonical-api §3.3 |
79
80
  | **Author a new topology/strategy compactly** | `defineStrategy(name, body)` w/ `ctx.shot()`+`ctx.critique()` — `/loops` | canonical-api §3.3 |
81
+ | **Spawn a coded loop as a first-class atom** (bounded/gated/steerable, spawned + steered like a worker — the 3rd shape beside leaf worker + driver child) | `defineLoop(name, { maxRounds, round | agents, check })` + `loopChild`, wired via `createInMemoryRunContext({ withLoop: true })` — `/loops` — multi-agent = `agents: [proposer, verifier]` (declarative chain, not a bespoke `runTwoAgent…` fn); NOT a hand-driver looping in the model's head; the loop-executor owns maxRounds + conserved budget + gate + steer-between-rounds | canonical-api decision table |
82
+ | **Have an LLM AUTHOR a loop at runtime** (codemode: the supervisor writes a `defineLoop` module for a novel goal) | `authorLoop({ chat, goal, maxRounds, outDir })` → a `LoopDef` for `loopChild` — `/loops` — NOT a per-product loop-code generator or a VM around authored code; the sibling of `authorStrategy`, safety is the conserved pool + gate + `assertStrategyContract` lint | `src/runtime/loop-author.ts` |
80
83
  | **Add a stateful tool-using domain** | implement `AgenticSurface` (5 hooks) — `/loops` | canonical-api §3.3 |
81
84
  | **Drive a team of agents over a graded `AgenticSurface` task** (workers settle on its check, driver self-improves from the failing tests) | `superviseSurface(profile, task, { surface, worker })` — `/loops` | canonical-api §2 |
82
85
  | **Benchmark: compare strategies + significance + Pareto on a domain** | `runBenchmark({ environment, tasks, worker, strategies })` — `/loops` | canonical-api §3.3 |
86
+ | **Author a PRODUCT eval leaderboard** (cases + prompt + grader → ranked board, standard flags, fresh run-dir, export, `toBenchmarkAdapter()`) | `defineLeaderboard({ name, cases, prompt, score, axis?, backends?, flags?, setup?/teardown?, onCellEvents?, resolveModel?, export?, dispatch?, judges?, matrix? })` — `/loops` — NOT a hand-assembled flag-parsing + `runProfileMatrix` frame; `runProfileMatrix` is the escape floor, the level-2 `dispatch` override is how in-process products plug in | `src/runtime/define-leaderboard.ts` (verify vs source) |
87
+ | **Resolve a harness-in-box backend** (box / local cli-bridge / router leaf, one `SandboxClient` shape) | `resolveSandboxClient({ backend: 'sandbox' \| 'bridge' \| 'router' })` — `/loops` — NOT a per-product backend factory or a hand-faked box (`inlineSandboxClient` / the bridge executor already exist) | `src/runtime/resolve-sandbox-client.ts` |
88
+ | **Resolve an in-process chat backend** (the one `--backend` branch for `runChatThroughRuntime` / `runAgentTaskStream`) | `resolveAgentBackend({ kind: 'router' \| 'tcloud' \| 'cli-bridge' \| 'sandbox' })` — root `.` | `src/resolve-agent-backend.ts` |
89
+ | **Run ONE agent turn as one normalized event stream** (box, executor, or chat backend; guaranteed terminal result+usage) | `streamAgentTurn(backend, prompt, { signal, timeoutMs })` + `collectAgentTurn(stream)` — `/loops` | canonical-api §2 |
83
90
  | **Benchmark report: multi-profile × multi-axis leaderboard** (ranked board + score matrix + SVG/HTML charts, any `RunRecord[]`) | `leaderboard(records)` + `renderLeaderboardMarkdown` / `renderLeaderboardSvg` / `renderLeaderboardHtml` — `/loops` | canonical-api §2 |
84
91
  | **Meter one `openSandboxRun` cell's token/cost usage** | `sumSandboxUsage(events)` — `/loops` | canonical-api §2 |
85
92
  | **Sweep harness × model as an eval axis** (turn one base profile into the full harness × model set) | `expandProfileAxes({ base, harnesses, models })` over `CODING_HARNESSES` → `runProfileMatrix(...)`, pivot with `groupRunsByAgentProfileCell` — `agent-eval` root — NOT a hand-declared `HARNESSES` list | agent-eval root (verify vs source) |
@@ -125,10 +132,28 @@ holds the load-bearing invariant the parallel breaks:
125
132
  (seeded, identical run-to-run; never report a point lift without `low/high/pairs`).
126
133
  - a per-product `HARNESSES` / `HarnessBackend` list + a metadata-harness reader
127
134
  **≈** `CODING_HARNESSES` + `expandProfileAxes` (the one canonical harness list;
128
- incompatible `(harness, model)` pairs drop via `harnessSupportsModel`) and the
135
+ vendor-locked harnesses SNAP to their native model via `HARNESS_NATIVE_MODEL`,
136
+ never dropped) and the
129
137
  `AgentProfileCell` stamped by `runProfileMatrix`, pivoted via
130
138
  `groupRunsByAgentProfileCell` — never bake the harness into the model id so the
131
139
  same model can run under multiple harnesses.
140
+ - a per-product leaderboard CLI (flag parsing + run-dir management + axis
141
+ expansion + a `runProfileMatrix` call + export/markdown) **≈**
142
+ `defineLeaderboard` (0.84+; it owns that whole frame — FRESH default run-dir,
143
+ standard `--backend`/`--harnesses`/`--models`/`--cases`/`--shots`/`--reps`
144
+ flags, `toBenchmarkAdapter()`; the product writes ~150-250 domain lines).
145
+ - a backend factory / `if (backend === 'router') ... else ...` branch or a
146
+ hand-faked box around a non-box executor **≈** `resolveSandboxClient`
147
+ (harness-in-box: `'sandbox' | 'bridge' | 'router'`) or `resolveAgentBackend`
148
+ (in-process: `'router' | 'tcloud' | 'cli-bridge' | 'sandbox'`) — grep the
149
+ substrate first; `inlineSandboxClient` and the bridge executor exist.
150
+ - a per-provider stream→event mapper for a single agent turn **≈**
151
+ `streamAgentTurn` + `collectAgentTurn` (0.85+; one `RuntimeStreamEvent`
152
+ contract over box / executor / chat, guaranteed terminal result+usage).
153
+ - a supervisor `act` with a `for (round…)` loop that spawns + checks + continues
154
+ in the model's reasoning **≈** `defineLoop` + `loopChild` (the loop-executor
155
+ enforces the round ceiling, the conserved pool, the completion gate, and
156
+ steer-between-rounds; a hand-driver loop enforces none of them).
132
157
 
133
158
  ## End-to-end recipe
134
159
 
@@ -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.