@tangle-network/agent-runtime 0.88.0 → 0.90.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/README.md +51 -18
- package/dist/agent.d.ts +53 -2
- package/dist/agent.js +166 -4
- package/dist/agent.js.map +1 -1
- package/dist/analyst-loop.d.ts +1 -1
- package/dist/{chunk-22HPUH77.js → chunk-4IBAMGBE.js} +170 -269
- package/dist/chunk-4IBAMGBE.js.map +1 -0
- package/dist/chunk-5QOB7H74.js +387 -0
- package/dist/chunk-5QOB7H74.js.map +1 -0
- package/dist/chunk-74SBMDTO.js +214 -0
- package/dist/chunk-74SBMDTO.js.map +1 -0
- package/dist/{chunk-HBE77SWV.js → chunk-MHK62APK.js} +5 -5
- package/dist/{chunk-LRNRPJAV.js → chunk-QSNSMJSZ.js} +2622 -2842
- package/dist/chunk-QSNSMJSZ.js.map +1 -0
- package/dist/{chunk-VNOOH22O.js → chunk-XMOU4WEY.js} +74 -3
- package/dist/chunk-XMOU4WEY.js.map +1 -0
- package/dist/{chunk-JHULWWQD.js → chunk-XQEISTK2.js} +2 -2
- package/dist/{worktree-harness-CX_McRLp.d.ts → completion-gate-BDaBP8dd.d.ts} +44 -44
- package/dist/{coordination-CuDLO8wj.d.ts → coordination-DxHduZg7.d.ts} +414 -226
- package/dist/environment-provider.d.ts +3 -3
- package/dist/index.d.ts +156 -13
- package/dist/index.js +316 -70
- package/dist/index.js.map +1 -1
- package/dist/intelligence.d.ts +2 -2
- package/dist/knowledge.d.ts +120 -0
- package/dist/knowledge.js +28 -0
- package/dist/knowledge.js.map +1 -0
- package/dist/lifecycle.js +1 -1
- package/dist/{loop-runner-bin-hQDUL8Ld.d.ts → loop-runner-bin-D3GmB2Ru.d.ts} +2 -2
- package/dist/loop-runner-bin.d.ts +5 -5
- package/dist/loop-runner-bin.js +5 -5
- package/dist/loops.d.ts +46 -324
- package/dist/loops.js +3 -15
- package/dist/mcp/bin.js +2 -2
- package/dist/mcp/index.d.ts +8 -9
- package/dist/mcp/index.js +7 -7
- package/dist/{openai-tools-BnrOmGjN.d.ts → openai-tools-D0xmzo0y.d.ts} +1 -1
- package/dist/profiles.d.ts +196 -5
- package/dist/profiles.js +8 -0
- package/dist/profiles.js.map +1 -1
- package/dist/{router-client-r8y_VFVM.d.ts → router-client-DJImUDlm.d.ts} +1 -1
- package/dist/supervise-BpCdssu0.d.ts +131 -0
- package/dist/{types-Driepl87.d.ts → types-DAJQRIUD.d.ts} +2 -2
- package/dist/{types-ESeMOj94.d.ts → types-Dnk189QA.d.ts} +1 -1
- package/dist/{worktree-fanout-D6xR2CIA.d.ts → worktree-fanout-CfRXYmgV.d.ts} +3 -3
- package/package.json +12 -4
- package/skills/agent-runtime-adoption/SKILL.md +74 -24
- package/skills/build-with-agent-runtime/SKILL.md +3 -9
- package/skills/loop-writer/SKILL.md +6 -78
- package/skills/supervise/SKILL.md +2 -2
- package/dist/chunk-22HPUH77.js.map +0 -1
- package/dist/chunk-LRNRPJAV.js.map +0 -1
- package/dist/chunk-VNOOH22O.js.map +0 -1
- package/dist/otel-export-BKmNwiCb.d.ts +0 -180
- /package/dist/{chunk-HBE77SWV.js.map → chunk-MHK62APK.js.map} +0 -0
- /package/dist/{chunk-JHULWWQD.js.map → chunk-XQEISTK2.js.map} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.90.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": {
|
|
@@ -49,6 +49,11 @@
|
|
|
49
49
|
"import": "./dist/lifecycle.js",
|
|
50
50
|
"default": "./dist/lifecycle.js"
|
|
51
51
|
},
|
|
52
|
+
"./knowledge": {
|
|
53
|
+
"types": "./dist/knowledge.d.ts",
|
|
54
|
+
"import": "./dist/knowledge.js",
|
|
55
|
+
"default": "./dist/knowledge.js"
|
|
56
|
+
},
|
|
52
57
|
"./profiles": {
|
|
53
58
|
"types": "./dist/profiles.d.ts",
|
|
54
59
|
"import": "./dist/profiles.js",
|
|
@@ -94,9 +99,9 @@
|
|
|
94
99
|
},
|
|
95
100
|
"devDependencies": {
|
|
96
101
|
"@biomejs/biome": "^2.4.15",
|
|
97
|
-
"@tangle-network/agent-eval": "^0.
|
|
98
|
-
"@tangle-network/agent-interface": "
|
|
99
|
-
"@tangle-network/sandbox": "
|
|
102
|
+
"@tangle-network/agent-eval": "^0.108.1",
|
|
103
|
+
"@tangle-network/agent-interface": "^0.19.0",
|
|
104
|
+
"@tangle-network/sandbox": "^0.9.7",
|
|
100
105
|
"@types/node": "^25.9.3",
|
|
101
106
|
"playwright": "^1.61.0",
|
|
102
107
|
"tsup": "^8.0.0",
|
|
@@ -138,5 +143,8 @@
|
|
|
138
143
|
"playwright": {
|
|
139
144
|
"optional": true
|
|
140
145
|
}
|
|
146
|
+
},
|
|
147
|
+
"dependencies": {
|
|
148
|
+
"@tangle-network/agent-knowledge": "^1.11.1"
|
|
141
149
|
}
|
|
142
150
|
}
|
|
@@ -54,10 +54,12 @@ Topology is the **one recursive agent tree**: each round an agent decides to ref
|
|
|
54
54
|
construction; the body is harness-re-verified, so an authored strategy can't
|
|
55
55
|
fabricate a win. Use when the right shape is task-dependent (scout-then-fanout,
|
|
56
56
|
refine-then-branch, decompose).
|
|
57
|
-
- **`createCoordinationTools`**
|
|
58
|
-
spawns / steers / awaits child agents
|
|
59
|
-
live `Scope`, recursively. Use when a
|
|
60
|
-
its workers in natural language.
|
|
57
|
+
- **`createCoordinationTools`** (from `@tangle-network/agent-runtime/mcp`) — the
|
|
58
|
+
agent-driving-agent loop: a driver agent spawns / steers / awaits child agents
|
|
59
|
+
(and sub-drivers) through MCP verbs over a live `Scope`, recursively. Use when a
|
|
60
|
+
driver should reason about and orchestrate its workers in natural language. From
|
|
61
|
+
`/loops` the equivalent surfaces are `serveCoordinationMcp` (the verbs as an HTTP
|
|
62
|
+
MCP over a live `Scope`) and the offline `driverAgent`.
|
|
61
63
|
|
|
62
64
|
Topology is **orthogonal to harness** — a strategy decides the shape; the executor
|
|
63
65
|
decides which harness (claude-code / codex / opencode / pi / router) runs each
|
|
@@ -100,6 +102,12 @@ agent-driving-agent loop), expose `createCoordinationTools` over a live `Scope`
|
|
|
100
102
|
|
|
101
103
|
- `runLoop` validates `ctx.sandboxClient.create` exists or throws
|
|
102
104
|
`ValidationError`. Never stub a `null` client.
|
|
105
|
+
- Build that client with `resolveSandboxClient({ backend })` (from
|
|
106
|
+
`@tangle-network/agent-runtime/loops`) — the one call that selects the sandbox /
|
|
107
|
+
bridge (cli-bridge) / router transport `runLoop` drives; do not hand-construct it.
|
|
108
|
+
Its sibling `resolveAgentBackend` is a DIFFERENT resolver — it resolves the CHAT
|
|
109
|
+
leg (`runChatThroughRuntime` / `runAgentTaskStream`) and returns an
|
|
110
|
+
`AgentExecutionBackend`, not a feeder for `resolveSandboxClient`.
|
|
103
111
|
- The kernel emits `loop.started / iteration.dispatch / iteration.ended /
|
|
104
112
|
decision / ended` via `ctx.traceEmitter`. Wire it to the same OTLP sink as the
|
|
105
113
|
chat path so loop telemetry is queryable.
|
|
@@ -108,17 +116,19 @@ agent-driving-agent loop), expose `createCoordinationTools` over a live `Scope`
|
|
|
108
116
|
- Dynamic driver: set the kernel's `runLoop` `maxIterations >=` the driver's so
|
|
109
117
|
the driver's cap governs and the loop closes on a clean `'done'`.
|
|
110
118
|
|
|
111
|
-
## Campaign bridge — `loopDispatch`
|
|
119
|
+
## Campaign bridge — `loopCampaignDispatch` / `loopDispatch`
|
|
112
120
|
|
|
113
121
|
To run `runLoop` as an agent-eval campaign cell, do NOT hand-build the ExecCtx +
|
|
114
122
|
forward trace + report usage every time (the third is silent — forgetting it
|
|
115
|
-
yields a `{0,0}` cell `assertRealBackend` reads as a stub). Use the
|
|
116
|
-
|
|
117
|
-
|
|
123
|
+
yields a `{0,0}` cell `assertRealBackend` reads as a stub). Use the bridge. Both
|
|
124
|
+
are exported from `src/runtime/index.ts` and are distinct sibling adapters, NOT a
|
|
125
|
+
rename: `loopCampaignDispatch` returns a `DispatchFn` for plain `runCampaign` /
|
|
126
|
+
`runEvalCampaign`; `loopDispatch` returns a `ProfileDispatchFn` and is the
|
|
127
|
+
`runProfileMatrix` variant (it adds the profile axis).
|
|
118
128
|
|
|
119
129
|
```ts
|
|
120
|
-
import {
|
|
121
|
-
const dispatch =
|
|
130
|
+
import { loopCampaignDispatch } from '@tangle-network/agent-runtime/loops'
|
|
131
|
+
const dispatch = loopCampaignDispatch({
|
|
122
132
|
sandboxClient,
|
|
123
133
|
toLoopOptions: (scenario, profile) => ({ driver, agentRun, output, validator, task: toTask(scenario) }),
|
|
124
134
|
// toArtifact? — defaults to result.winner?.output
|
|
@@ -126,19 +136,59 @@ const dispatch = loopDispatch({
|
|
|
126
136
|
// pass `dispatch` to runCampaign / runEvalCampaign; usage + trace are auto-forwarded
|
|
127
137
|
```
|
|
128
138
|
|
|
129
|
-
|
|
139
|
+
For the common shape — a fixed set of `cases` + a `prompt` builder + a `score`
|
|
140
|
+
fn, swept across profiles — prefer the declarative facade
|
|
141
|
+
`defineLeaderboard({ cases, prompt, score })` (from
|
|
142
|
+
`@tangle-network/agent-runtime/loops`). It composes
|
|
143
|
+
`expandProfileAxes × loopDispatch × naiveDriver` into one call, exposes
|
|
144
|
+
`.run(argv?)` (CLI-flag parsing + matrix) and `.toBenchmarkAdapter()`, and yields
|
|
145
|
+
a ranked leaderboard. Reach for raw `loopDispatch` only when a cell needs a custom
|
|
146
|
+
driver/validator.
|
|
130
147
|
|
|
131
|
-
## Identity-gated optimization — agent-eval's `selfImprove`
|
|
148
|
+
## Identity-gated optimization — agent-runtime's `improve()` (facade over agent-eval's `selfImprove`)
|
|
132
149
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
150
|
+
**Start with `improve()`** — the one pluggable RSI verb, exported at the
|
|
151
|
+
`@tangle-network/agent-runtime` package ROOT (its own header: "the ONE public,
|
|
152
|
+
surface-pluggable RSI verb. A thin facade over agent-eval's `selfImprove`"). Real
|
|
153
|
+
signature is 3-arg, NOT a single options object:
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
improve<TScenario, TArtifact>(
|
|
157
|
+
profile: AgentProfile,
|
|
158
|
+
findings: unknown[],
|
|
159
|
+
opts: ImproveOptions,
|
|
160
|
+
): Promise<ImproveResult>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`opts`: `surface?: 'prompt'|'skills'|'tools'|'mcp'|'hooks'|'code'` (default
|
|
164
|
+
`'prompt'`), `scenarios`, `judge`, `agent`, `gate?: 'holdout'|'none'` (default
|
|
165
|
+
`'holdout'`; `'none'` forces `generations = 0`), plus `budget?` / `llm?` /
|
|
166
|
+
`generator?` / `code?` / `skills?` / `runDir?`. It picks the default proposer for
|
|
167
|
+
the surface (`gepaProposer` for `'prompt'`, `skillOptProposer` for `'skills'`;
|
|
168
|
+
`'code'`/`'tools'`/`'mcp'`/`'hooks'` throw `ConfigError` unless you pass
|
|
169
|
+
`opts.generator` or `opts.code`), extracts the baseline from the profile, runs
|
|
170
|
+
`selfImprove` with the held-out gate, and on a ship verdict writes the winner back
|
|
171
|
+
into the profile field. Returns `ImproveResult { profile, shipped, lift,
|
|
172
|
+
gateDecision, raw }` — deploy with `if (out.shipped) deploy(out.profile)`:
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
import { improve } from '@tangle-network/agent-runtime'
|
|
176
|
+
const out = await improve(profile, findings, {
|
|
177
|
+
surface: 'prompt', scenarios, judge, agent, gate: 'holdout', llm,
|
|
178
|
+
})
|
|
179
|
+
if (out.shipped) deploy(out.profile)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Drop to `selfImprove`** (`@tangle-network/agent-eval/contract`) only when you
|
|
183
|
+
need finer control — a custom proposer/gate, or the code-surface git-worktree path
|
|
184
|
+
via agent-runtime's `improvementDriver` (`/improvement`), which you pass to it as
|
|
185
|
+
`proposer` to optimize CODE instead of a string. `selfImprove` optimizes any
|
|
186
|
+
text/config surface (system / planner / judge rubric) and is **identity-gated by
|
|
187
|
+
construction**: it runs evals, proposes candidates (default proposer
|
|
188
|
+
`gepaProposer`), and a held-out gate ships a winner only if it beats the baseline.
|
|
189
|
+
`result.winner.surface` is the **baseline unless `result.gateDecision === 'ship'`**
|
|
190
|
+
— so registering a surface for optimization can never regress it; it only improves
|
|
191
|
+
when held-out data earns it.
|
|
142
192
|
|
|
143
193
|
```ts
|
|
144
194
|
import { selfImprove } from '@tangle-network/agent-eval/contract'
|
|
@@ -148,8 +198,8 @@ const result = await selfImprove({
|
|
|
148
198
|
scenarios,
|
|
149
199
|
judge,
|
|
150
200
|
budget: { holdoutScenarios, generations: 3, populationSize: 2 },
|
|
151
|
-
llm: { baseUrl, apiKey, model: REFLECTION_MODEL }, // drives the default
|
|
152
|
-
//
|
|
201
|
+
llm: { baseUrl, apiKey, model: REFLECTION_MODEL }, // drives the default gepaProposer
|
|
202
|
+
// proposer? — pass agent-runtime's improvementDriver to optimize CODE (worktree) instead of a string
|
|
153
203
|
// gate? — defaults to a held-out gate; pass defaultProductionGate for red-team hardening
|
|
154
204
|
})
|
|
155
205
|
// use result.winner.surface unconditionally: it's the baseline until a candidate genuinely wins
|
|
@@ -157,7 +207,7 @@ const result = await selfImprove({
|
|
|
157
207
|
|
|
158
208
|
### selfImprove gotchas — read before wiring
|
|
159
209
|
|
|
160
|
-
- **`
|
|
210
|
+
- **`gepaProposer` mutates TEXT only**, and its only structural guard is `##` H2
|
|
161
211
|
headings (`preserveSections`) + `maxSentenceEdits`. Make load-bearing sections
|
|
162
212
|
of your prompt real `##` headings, and treat the output schema as fixed code —
|
|
163
213
|
GEPA optimizes the prose, never the envelope/contract.
|
|
@@ -78,8 +78,6 @@ to its native default (`HARNESS_NATIVE_MODEL`) — never silently dropped.
|
|
|
78
78
|
| **Produce-then-gate / multi-judge quorum / fixed chain** | `verify` / `panel` / `pipeline` — `/loops` | canonical-api §3.1 |
|
|
79
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 |
|
|
80
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` |
|
|
83
81
|
| **Add a stateful tool-using domain** | implement `AgenticSurface` (5 hooks) — `/loops` | canonical-api §3.3 |
|
|
84
82
|
| **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 |
|
|
85
83
|
| **Benchmark: compare strategies + significance + Pareto on a domain** | `runBenchmark({ environment, tasks, worker, strategies })` — `/loops` | canonical-api §3.3 |
|
|
@@ -94,8 +92,8 @@ to its native default (`HARNESS_NATIVE_MODEL`) — never silently dropped.
|
|
|
94
92
|
| **Spawn N coding agents on isolated git worktrees, keep the one whose patch passes checks** | `worktreeFanout` + `createWorktreeCliExecutor` + `gateOnDeliverable(DeliverableSpec)` over a raw `WorktreePatchArtifact`, winner via `selectValidWinner` — `/loops` — NOT a hand-rolled spawn-loop / "coder" role | canonical-api §3.1 / §5 |
|
|
95
93
|
| **Sandbox coding rollout** (fresh box/round, or persistent+resume) | `runLoop(options)` / `openSandboxRun(client, opts, deliverable)` — `/loops` | canonical-api §3.1 |
|
|
96
94
|
| **Optimize a CODE surface** in a gated loop | `improvementDriver({ worktree, generator })` — root `.` | canonical-api §3.4 |
|
|
97
|
-
| **Optimize a PROMPT/config surface** (one call) | `selfImprove({ agent, scenarios, judge, baselineSurface })`
|
|
98
|
-
| **Gate: ship/hold a candidate** (campaign ctx) | `defaultProductionGate` / `heldOutGate` / `composeGate` — `agent-eval/contract` | canonical-api §3.4 |
|
|
95
|
+
| **Optimize a PROMPT/config surface** (one call) — START HERE | `improve(profile, findings, { surface, gate })` — root `.` (the one pluggable RSI verb; picks the default proposer from `surface` — `gepaProposer` for prompt, `skillOptProposer` for skills — and wraps `selfImprove`; drop to `selfImprove({ agent, scenarios, judge, baselineSurface })` from `agent-eval/contract` only for the lower-level loop) | canonical-api §3.4 |
|
|
96
|
+
| **Gate: ship/hold a candidate** (campaign ctx) | `defaultProductionGate` / `heldOutGate` / `composeGate` — `agent-eval/contract`; `neutralizationGate` (footprint-matched PLACEBO gate — proves a held-out lift is CONTENT, not added prompt/mount footprint) — `agent-eval/campaign` | canonical-api §3.4 |
|
|
99
97
|
| **Gate: ship/hold from a `BenchmarkReport`** (per-task cells) | `promotionGate({ report, incumbent, candidate })` — `/loops` | canonical-api §3.4 |
|
|
100
98
|
| **Run the full multi-generation flywheel + certify** | `runStrategyEvolution(config)` — `/loops` | canonical-api §3.4 |
|
|
101
99
|
| **Observe a run** (cost/time waterfall, OTLP) | `createWaterfallCollector()` — `/loops`; `createOtelExporter` attached via `composeRuntimeHooks(...)` — root `.` | canonical-api §2 |
|
|
@@ -112,7 +110,7 @@ holds the load-bearing invariant the parallel breaks:
|
|
|
112
110
|
`loopUntil` + `runPersonified` (threads executor seams; equal-k; selector≠judge
|
|
113
111
|
firewall; journal/replay — a parallel runner silently fails to wire the seams).
|
|
114
112
|
- "skill optimizer" / "topology mutator" that opens branches + applies patches
|
|
115
|
-
**≈** `improvementDriver` (code surface) or `selfImprove`/`
|
|
113
|
+
**≈** `improvementDriver` (code surface) or `selfImprove`/`gepaProposer` (prompt
|
|
116
114
|
surface) — both gated on a frozen holdout.
|
|
117
115
|
- "profile-seam" / agent-config wrapper carrying model+prompt+tools+role **≈**
|
|
118
116
|
`AgentProfile` (it IS that bundle) + `definePersona` (the run record);
|
|
@@ -150,10 +148,6 @@ holds the load-bearing invariant the parallel breaks:
|
|
|
150
148
|
- a per-provider stream→event mapper for a single agent turn **≈**
|
|
151
149
|
`streamAgentTurn` + `collectAgentTurn` (0.85+; one `RuntimeStreamEvent`
|
|
152
150
|
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).
|
|
157
151
|
|
|
158
152
|
## End-to-end recipe
|
|
159
153
|
|
|
@@ -30,8 +30,8 @@ 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
|
-
|
|
|
34
|
-
| Mutate a shared repo | git branch/clone loop with typed merge outcomes |
|
|
33
|
+
| Run N coding workers on isolated worktrees, gate each, pick best patch | `worktreeFanout` |
|
|
34
|
+
| Mutate a shared repo | git branch/clone loop with typed merge outcomes (`gitWorkspace` seam) |
|
|
35
35
|
|
|
36
36
|
If a fixed combinator solves it, do not use a dynamic driver.
|
|
37
37
|
|
|
@@ -111,81 +111,9 @@ const result = await createSupervisor<Task, Output>().run(driver, task, supervis
|
|
|
111
111
|
```
|
|
112
112
|
|
|
113
113
|
When the driver lives in a sandbox, expose the same verbs through
|
|
114
|
-
`createCoordinationTools`: `
|
|
115
|
-
`
|
|
116
|
-
optional analyst tools.
|
|
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.
|
|
114
|
+
`createCoordinationTools`: `spawn_agent`, `await_event`, `observe_agent`,
|
|
115
|
+
`steer_agent`, `list_questions`, `answer_question`, `ask_parent`, `stop`, and
|
|
116
|
+
optional analyst tools (`list_analysts`, `run_analyst`).
|
|
189
117
|
|
|
190
118
|
## Role Boundaries
|
|
191
119
|
|
|
@@ -206,7 +134,7 @@ with unresolved `blocks-run` questions.
|
|
|
206
134
|
Steer sparingly: only when an analyst finds a concrete mistake, a loop is
|
|
207
135
|
duplicating work, a parent/Pi answers a blocker, or a verifier reveals a specific
|
|
208
136
|
fix a running worker can still use. Delivery is through `Scope.send` or
|
|
209
|
-
`
|
|
137
|
+
`steer_agent`; failed delivery means spawn a fresh corrected attempt.
|
|
210
138
|
|
|
211
139
|
## Workspace Loops
|
|
212
140
|
|
|
@@ -10,7 +10,7 @@ You are a supervisor. You do NOT do the work yourself — you design and drive s
|
|
|
10
10
|
## Loop
|
|
11
11
|
|
|
12
12
|
1. **Decompose** the task into the smallest set of sub-tasks a single focused worker can each deliver.
|
|
13
|
-
2. **Author** a worker per sub-task by calling `
|
|
13
|
+
2. **Author** a worker per sub-task by calling `spawn_agent` with a complete `profile`:
|
|
14
14
|
- `name` — a short id.
|
|
15
15
|
- `skills` — the skill files the worker should carry (by name), OR `systemPrompt` — rich, specific instructions for this sub-task.
|
|
16
16
|
- `model` — the model best suited to this sub-task (optional).
|
|
@@ -21,4 +21,4 @@ You are a supervisor. You do NOT do the work yourself — you design and drive s
|
|
|
21
21
|
|
|
22
22
|
## Authoring sub-supervisors
|
|
23
23
|
|
|
24
|
-
If a sub-task is itself too large for one worker, author it as a **sub-supervisor**: give its profile a `skills` list that includes `supervise`. It will decompose and drive its own workers one level deeper. This is not a special call — it is the same `
|
|
24
|
+
If a sub-task is itself too large for one worker, author it as a **sub-supervisor**: give its profile a `skills` list that includes `supervise`. It will decompose and drive its own workers one level deeper. This is not a special call — it is the same `spawn_agent`, just a profile that carries this skill.
|