@tangle-network/agent-knowledge 4.0.0 → 4.1.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/AGENTS.md +32 -18
- package/CHANGELOG.md +32 -0
- package/README.md +31 -19
- package/dist/benchmarks/index.d.ts +51 -3
- package/dist/benchmarks/index.js +1 -1
- package/dist/{chunk-EUAXSBMH.js → chunk-AKYJG2MR.js} +224 -224
- package/dist/chunk-AKYJG2MR.js.map +1 -0
- package/dist/{chunk-DW6APRTX.js → chunk-BBCIB4UL.js} +2486 -2457
- package/dist/chunk-BBCIB4UL.js.map +1 -0
- package/dist/{chunk-UWOTQNBI.js → chunk-CPMLJYA3.js} +1886 -1842
- package/dist/chunk-CPMLJYA3.js.map +1 -0
- package/dist/{chunk-WCYW2GDA.js → chunk-MYFM6LKH.js} +2 -2
- package/dist/chunk-MYFM6LKH.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +48 -52
- package/dist/index.js +2906 -2874
- package/dist/index.js.map +1 -1
- package/dist/memory/index.d.ts +129 -6
- package/dist/memory/index.js +2 -2
- package/dist/sources/index.d.ts +17 -33
- package/dist/sources/index.js +1 -1
- package/dist/{index-Bqg1mBPt.d.ts → types-DP38encz.d.ts} +127 -284
- package/docs/eval/investment-material-facts.md +28 -29
- package/docs/eval/rag-eval-roadmap.md +6 -5
- package/docs/results/adaptive.md +13 -13
- package/docs/results/claim-grounding.md +11 -11
- package/docs/results/cost-quality.md +4 -4
- package/docs/results/investment-thesis.md +56 -56
- package/docs/results/research-driving.md +54 -54
- package/docs/two-agent-research-ab.md +94 -94
- package/package.json +4 -7
- package/dist/chunk-DW6APRTX.js.map +0 -1
- package/dist/chunk-EUAXSBMH.js.map +0 -1
- package/dist/chunk-UWOTQNBI.js.map +0 -1
- package/dist/chunk-WCYW2GDA.js.map +0 -1
|
@@ -10,34 +10,34 @@ fixed. A *worker* agent searches the web and proposes sources for the knowledge
|
|
|
10
10
|
base's open gaps; a *driver* agent vets each proposed source before it commits,
|
|
11
11
|
fills gaps the worker missed, and decides when the base is complete. Over 9
|
|
12
12
|
machine-learning topics at equal compute, the two-agent loop admitted **2.3–2.7
|
|
13
|
-
fewer sources per topic at identical coverage
|
|
13
|
+
fewer sources per topic at identical coverage**, 95% bootstrap intervals
|
|
14
14
|
[1.78, 2.89] and [2.22, 3.00] across two independent runs, both above zero. The
|
|
15
15
|
effect is real and reproduces. But the mechanism is not the one we set out to
|
|
16
|
-
test: reading the rejection logs, most of the gain is **de-duplication
|
|
17
|
-
same paper fetched from arXiv, OpenReview, and the NeurIPS proceedings
|
|
16
|
+
test: reading the rejection logs, most of the gain is **de-duplication**, the
|
|
17
|
+
same paper fetched from arXiv, OpenReview, and the NeurIPS proceedings, not the
|
|
18
18
|
relevance filtering we expected. Pricing the verifier's calls (we added per-arm
|
|
19
19
|
router-usage instrumentation) shows the cleanliness costs roughly **5× the
|
|
20
|
-
dollars, 9× the tokens, and 3× the latency** of the single agent
|
|
20
|
+
dollars, 9× the tokens, and 3× the latency** of the single agent, and that the
|
|
21
21
|
original "equal passes" framing hid this, because it charged the verify step as
|
|
22
22
|
one pass while it is actually one LLM call per proposed source. Since the win is
|
|
23
23
|
de-dup-dominated, a deterministic content hash recovers most of the cleanliness at
|
|
24
|
-
~none of the premium. We then asked the sharper question
|
|
25
|
-
where an LLM verifier *does* earn its dollar
|
|
24
|
+
~none of the premium. We then asked the sharper question, is there an error band
|
|
25
|
+
where an LLM verifier *does* earn its dollar?, and found two, on opposite sides of
|
|
26
26
|
the ledger. **Misattributed citations** (an on-topic, unique, real source whose
|
|
27
27
|
cited claim never appears in the page) are caught by a $0 deterministic
|
|
28
28
|
text-presence check that the LLM relevance judge misses 1 in 5 times, because the
|
|
29
29
|
judge structurally never sees the claim. And we built the deployable shape the
|
|
30
|
-
cost result implied
|
|
30
|
+
cost result implied, an **adaptive driver** that runs free dedup, then free
|
|
31
31
|
heuristic triage, and escalates to the LLM only on the ambiguous tail: it cuts
|
|
32
32
|
LLM verifier calls 76% and dollars 74%, recovering the de-dup half of the
|
|
33
|
-
verifier's cleanliness while
|
|
33
|
+
verifier's cleanliness while giving up the relevance-judgment half on a
|
|
34
34
|
source pool dominated by authoritative hosts. The verifier earns its dollar on
|
|
35
35
|
misattribution, not on de-duplication; the right production loop spends it only
|
|
36
36
|
where the cheap signals can't decide. Finally we ask the harder question this whole
|
|
37
|
-
metric can't reach
|
|
38
|
-
*answer more
|
|
37
|
+
metric can't reach, a filter agent can only make the base *carry less*, never
|
|
38
|
+
*answer more*, by building the opposite agent (a **driving** driver that chases
|
|
39
39
|
depth and corroboration instead of pruning) and the opposite metric (a firewalled
|
|
40
|
-
exam of 20 held-out **deep questions**, $0-graded).
|
|
40
|
+
exam of 20 held-out **deep questions**, $0-graded). The result is null: driving
|
|
41
41
|
does **not** reliably beat plain collection at answering hard questions, and costs
|
|
42
42
|
**12–16×** more; the verdict flips with the compute budget, the signature of web
|
|
43
43
|
variance rather than a real topology effect, and it still ties a blind worker even
|
|
@@ -46,15 +46,15 @@ when forced to run its full multi-round mechanism (§9).
|
|
|
46
46
|
## 1. Setup
|
|
47
47
|
|
|
48
48
|
A research agent building a knowledge base accumulates sources. A single agent both
|
|
49
|
-
finds sources and, implicitly, decides which to keep
|
|
49
|
+
finds sources and, implicitly, decides which to keep, it grades its own work. The
|
|
50
50
|
hypothesis is the usual one for verification: separating the producer (find
|
|
51
51
|
sources) from the checker (keep the good ones) should yield a cleaner result, for
|
|
52
52
|
the same reason a second pair of eyes catches typos the author misses.
|
|
53
53
|
|
|
54
54
|
The trap in any "more agents help" claim is compute. Two agents that simply do more
|
|
55
|
-
work will of course produce more
|
|
56
|
-
comparison must hold total compute fixed and ask whether the *topology
|
|
57
|
-
find from check
|
|
55
|
+
work will of course produce more, that is a bigger budget, not a finding. So the
|
|
56
|
+
comparison must hold total compute fixed and ask whether the *topology*, splitting
|
|
57
|
+
find from check, beats spending the same compute on a single agent that just finds
|
|
58
58
|
more. And once topology shows an effect, the second question is what it costs: a
|
|
59
59
|
cleaner base bought at 5× the inference is a different product decision than one
|
|
60
60
|
bought for free.
|
|
@@ -65,9 +65,9 @@ bought for free.
|
|
|
65
65
|
|
|
66
66
|
The loop has two roles (`src/two-agent-research-loop.ts`, `runTwoAgentResearchLoop`):
|
|
67
67
|
|
|
68
|
-
- **Worker
|
|
68
|
+
- **Worker**: primary research. Each round it reads the open gaps and proposes
|
|
69
69
|
sources to close them (`ResearchWorker: (ctx: { gaps, steer }) => proposals`).
|
|
70
|
-
- **Driver
|
|
70
|
+
- **Driver**: does three things (`ResearchDriver`): `verifySource` vets each
|
|
71
71
|
proposed source before it commits (dedup against the base, then reject sources
|
|
72
72
|
that aren't relevant); `research` runs the driver's own gap-fill pass over gaps
|
|
73
73
|
the worker missed; `foldGaps` turns the still-open gaps into a `steer` string for
|
|
@@ -80,7 +80,7 @@ reports no blocking gaps left.
|
|
|
80
80
|
|
|
81
81
|
Note what the driver→worker hand-off is and isn't: the driver *steers* the worker
|
|
82
82
|
by handing it the remaining readiness gaps (`foldGaps`), which is a deterministic
|
|
83
|
-
formatting of unmet requirements
|
|
83
|
+
formatting of unmet requirements, not an LLM authoring a fresh instruction. The
|
|
84
84
|
driver's LLM work is in `verifySource` (one call per proposed source) and its own
|
|
85
85
|
`research` pass. This matters for §4.2: the verify step is N calls, not one, and
|
|
86
86
|
the cost framing turns on that.
|
|
@@ -90,14 +90,14 @@ The readiness gate is `scoreKnowledgeReadiness` (from `agent-eval`). It scores
|
|
|
90
90
|
'blocking'` requirements gate. Coverage below is the fraction of a topic's blocking
|
|
91
91
|
requirements met.
|
|
92
92
|
|
|
93
|
-
### 2.2
|
|
93
|
+
### 2.2 Implementation note
|
|
94
94
|
|
|
95
95
|
The agents in the live run are **not** `AgentProfile`s on a coding harness. The
|
|
96
96
|
worker is a hand-wired pipeline (`src/web-research-worker.ts`,
|
|
97
97
|
`createWebResearchWorker`): glm-5.2 turns the gaps into search queries → a real web
|
|
98
98
|
search over the Tangle router (`POST /v1/search`) → each hit is fetched with the
|
|
99
99
|
repo's `politeFetch` and reduced to text with `htmlToText` → citing pages are
|
|
100
|
-
proposed. It talks to the router directly through `createTangleRouterClient
|
|
100
|
+
proposed. It talks to the router directly through `createTangleRouterClient`, no
|
|
101
101
|
claude-code / opencode / sandbox harness, and no dynamic harness selection. The
|
|
102
102
|
driver (`createVerifyingResearchDriver`) is one glm-5.2 chat call per source.
|
|
103
103
|
|
|
@@ -109,7 +109,7 @@ Agent profiles and sandbox-backed runners now live in `agent-runtime`; this pack
|
|
|
109
109
|
Compute is counted in agent passes. A two-agent round = 1 worker pass + 1
|
|
110
110
|
verify pass = 2 passes; a single-agent iteration = 1 pass. Both arms gate on the
|
|
111
111
|
*same* readiness criterion and stop as soon as it is met, so neither is starved.
|
|
112
|
-
We budget-match by passes, not rounds
|
|
112
|
+
We budget-match by passes, not rounds, the single-agent loop gets more rounds to
|
|
113
113
|
spend the compute the two-agent loop spends on verification. The harness asserts,
|
|
114
114
|
per topic, that the two-agent loop spent no more passes than the single-agent loop
|
|
115
115
|
and that both stayed under the ceiling; if that ever fails the comparison has
|
|
@@ -137,7 +137,7 @@ results / trade-offs). Seven are "narrow-scope-inside-a-broad-space" (e.g.
|
|
|
137
137
|
broad space to leak in; two are clean controls (*the transformer architecture*,
|
|
138
138
|
*gradient descent*).
|
|
139
139
|
|
|
140
|
-
## 3. Result 1
|
|
140
|
+
## 3. Result 1: cleanliness: the verifier admits fewer sources at equal coverage
|
|
141
141
|
|
|
142
142
|
The cleanliness signal is the **admitted-source count**: on live data there is no
|
|
143
143
|
oracle, so "fewer sources admitted at equal coverage" is the measurable proxy for
|
|
@@ -157,7 +157,7 @@ oracle, so "fewer sources admitted at equal coverage" is the measurable proxy fo
|
|
|
157
157
|
| **mean Δ** | | **2.33** | **2.67** |
|
|
158
158
|
| **95% CI** (paired bootstrap) | | **[1.78, 2.89]** | **[2.22, 3.00]** |
|
|
159
159
|
|
|
160
|
-
Coverage was **1.00 on every topic, both arms, both runs
|
|
160
|
+
Coverage was **1.00 on every topic, both arms, both runs**, the verifier never
|
|
161
161
|
cost completeness. Both bootstrap intervals (`pairedBootstrap`, from `agent-eval`)
|
|
162
162
|
are above zero. The effect reproduces; its exact magnitude varies run-to-run with
|
|
163
163
|
what the web returns (one topic swung Δ = 0→1→3 across separate runs during
|
|
@@ -166,10 +166,10 @@ development).
|
|
|
166
166
|
A third, cost-instrumented run (the one priced in §4.2) was noisier: mean Δ **+1.56,
|
|
167
167
|
95% CI [0.33, 2.67]**, with two topics where the two-agent loop admitted *more* than
|
|
168
168
|
the single agent (KV-cache quantization −1, gradient descent −1). The interval still
|
|
169
|
-
clears zero, but it is the lower-bound run
|
|
169
|
+
clears zero, but it is the lower-bound run, a reminder that the magnitude is
|
|
170
170
|
web-variance-bound, while the sign is stable.
|
|
171
171
|
|
|
172
|
-
## 4. Result 2
|
|
172
|
+
## 4. Result 2: what the verifier does, and what it costs
|
|
173
173
|
|
|
174
174
|
### 4.1 Mostly de-duplication
|
|
175
175
|
|
|
@@ -181,18 +181,18 @@ We classified each rejection by the verifier's own stated reason:
|
|
|
181
181
|
| off-scope (broad space leaked in) | 3 | 2 |
|
|
182
182
|
| junk page (aggregator / marketing / explainer) | 3 | 0 |
|
|
183
183
|
|
|
184
|
-
The dominant mechanism is **de-duplication
|
|
185
|
-
arXiv, OpenReview, and the NeurIPS proceedings
|
|
184
|
+
The dominant mechanism is **de-duplication**, canonical papers mirrored across
|
|
185
|
+
arXiv, OpenReview, and the NeurIPS proceedings, and it fires regardless of band.
|
|
186
186
|
The off-scope rejection we set out to measure is real (on *self-speculative
|
|
187
187
|
decoding* the verifier correctly dropped three general *speculative decoding* papers
|
|
188
188
|
that use a *separate* draft model) but it is the minority, and it does not
|
|
189
189
|
concentrate on the narrow topics as hypothesized: narrow mean Δ = 2.14 vs clean
|
|
190
|
-
3.00. The strong form of our hypothesis
|
|
190
|
+
3.00. The strong form of our hypothesis, narrow-in-broad pays more, is **refuted
|
|
191
191
|
in magnitude, confirmed only in mechanism**.
|
|
192
192
|
|
|
193
193
|
The practical reading: most of the win is "you fetched the same PDF three times,"
|
|
194
194
|
which a content hash catches for free. The LLM's distinctive contribution is the
|
|
195
|
-
page that *looks* on-topic but isn't
|
|
195
|
+
page that *looks* on-topic but isn't, the self-speculative-vs-separate-draft
|
|
196
196
|
distinction a string match would miss.
|
|
197
197
|
|
|
198
198
|
### 4.2 The inference premium (and what "equal passes" hid)
|
|
@@ -207,59 +207,59 @@ distinction a string match would miss.
|
|
|
207
207
|
| tokens (in+out) | ~4,900 | ~530 | ~9× |
|
|
208
208
|
| cost (USD) | ~$0.0072 | ~$0.0013 | ~5.5× |
|
|
209
209
|
| latency (wall) | ~37 s | ~11 s | ~3.4× |
|
|
210
|
-
| cleanliness Δ (single − two admitted) |
|
|
210
|
+
| cleanliness Δ (single − two admitted) | n/a | n/a | +1.56, 95% CI [0.33, 2.67] |
|
|
211
211
|
|
|
212
212
|
The verifier buys ~1.5–2.7 fewer junk sources for roughly **5× the dollars, 9× the
|
|
213
213
|
tokens, and 3× the latency**. Since the cleanliness gain is de-dup-dominated
|
|
214
|
-
(§4.1), the
|
|
214
|
+
(§4.1), the production move is a deterministic content-hash / canonical-URL
|
|
215
215
|
dedup, which captures most of the cleanliness at ~none of this premium, reserving
|
|
216
216
|
an LLM check only for the off-scope tail. This is the cost half the "equal passes"
|
|
217
|
-
framing left out
|
|
217
|
+
framing left out, and the rest of the paper is what we built once we saw it.
|
|
218
218
|
|
|
219
|
-
## 5. Result 3
|
|
219
|
+
## 5. Result 3: the two bands where an LLM verifier does, and doesn't, earn its dollar
|
|
220
220
|
|
|
221
221
|
If de-dup is free and dominates the win, when is the LLM verifier worth its 5×? We
|
|
222
222
|
found two bands, and they cut in opposite directions.
|
|
223
223
|
|
|
224
|
-
### 5.1 Misattributed citations
|
|
224
|
+
### 5.1 Misattributed citations: the cheap check beats the expensive judge
|
|
225
225
|
|
|
226
226
|
`docs/results/claim-grounding.md`. A source can be on-topic, unique, and real, yet
|
|
227
|
-
the cited *claim* never appears in the page
|
|
227
|
+
the cited *claim* never appears in the page, the LLM wrote a plausible sentence and
|
|
228
228
|
hung a real URL off it. De-dup passes it (unique). A relevance judge passes it (the
|
|
229
|
-
page is on-topic). Only checking the claim against the fetched text catches it
|
|
229
|
+
page is on-topic). Only checking the claim against the fetched text catches it, and
|
|
230
230
|
that check is **deterministic text presence, $0 inference**.
|
|
231
231
|
|
|
232
232
|
Each proposed source now carries the claim it is cited for (`withCitedClaim` →
|
|
233
233
|
`metadata.citedClaim`). The claim-grounding verifier (`createClaimGroundingVerifier`,
|
|
234
234
|
`src/claim-grounding.ts`) runs `groundClaimInText(claim, pageText)` over the
|
|
235
|
-
`htmlToText` output of the page the worker actually fetched
|
|
235
|
+
`htmlToText` output of the page the worker actually fetched, verbatim, normalized
|
|
236
236
|
(punctuation/whitespace-insensitive), or a ≥70% content-word overlap close
|
|
237
237
|
paraphrase. A claim that isn't present is rejected as misattributed. The oracle is
|
|
238
238
|
text presence, not a model call, so it composes with the LLM relevance verifier or
|
|
239
239
|
runs alone at zero cost.
|
|
240
240
|
|
|
241
|
-
Live A/B (glm-5.2, real web fetch, one planted misattribution per topic
|
|
242
|
-
fetched page plus a deliberately-wrong claim
|
|
241
|
+
Live A/B (glm-5.2, real web fetch, one planted misattribution per topic, a real
|
|
242
|
+
fetched page plus a deliberately-wrong claim, over three verifier arms on the same
|
|
243
243
|
proposals):
|
|
244
244
|
|
|
245
245
|
| n=5 topics | misattributions caught | marginal $ | per-$ caught |
|
|
246
246
|
|---|---|---|---|
|
|
247
|
-
| no-verifier | 0 / 5 | $0.0000 |
|
|
247
|
+
| no-verifier | 0 / 5 | $0.0000 | n/a |
|
|
248
248
|
| relevance (LLM judge) | 4 / 5 | $0.0157 | 254 |
|
|
249
249
|
| claim-grounding (text) | **5 / 5** | **$0.0000** | ∞ |
|
|
250
250
|
|
|
251
|
-
The relevance judge catches one only by accident
|
|
251
|
+
The relevance judge catches one only by accident, when the fabricated claim also
|
|
252
252
|
makes the page read off-topic (a "12-billion-parameter draft transformer" claim on a
|
|
253
253
|
rotary-embeddings page). When the fabrication stays on-topic (the KV-cache case), the
|
|
254
254
|
judge waves it through, because the relevance verifier only ever sees the page text,
|
|
255
|
-
never the cited claim
|
|
255
|
+
never the cited claim, it is **structurally blind** to misattribution. On this band
|
|
256
256
|
the verifier-per-dollar comparison inverts §4.2: the cheap, deterministic check
|
|
257
257
|
catches strictly more (5/5 vs 4/5) at strictly less ($0 vs $0.0157). The offline
|
|
258
258
|
floor confirms the wiring: on a controlled 4-source pool (2 grounded, 2
|
|
259
259
|
misattributed), claim-grounding admits **0/2** misattributions and keeps **2/2**
|
|
260
260
|
grounded, while relevance and no-verifier both admit **2/2**.
|
|
261
261
|
|
|
262
|
-
### 5.2 Adaptive topology
|
|
262
|
+
### 5.2 Adaptive topology: pay the LLM only on the ambiguous tail
|
|
263
263
|
|
|
264
264
|
`docs/results/adaptive.md`. The deployable shape §4.2 implied: do the free
|
|
265
265
|
deterministic work first, reserve the LLM for what the cheap signals can't decide.
|
|
@@ -275,7 +275,7 @@ decides:
|
|
|
275
275
|
github, …) with a substantial body is **kept**; an obvious spam/listicle title
|
|
276
276
|
or a too-thin body is **dropped**; everything else is **ambiguous**.
|
|
277
277
|
3. **LLM escalation ($).** Only ambiguous survivors reach the shipped LLM relevance
|
|
278
|
-
verifier
|
|
278
|
+
verifier, one call each.
|
|
279
279
|
|
|
280
280
|
Live frontier, n=5 topics, glm-5.2, same fetched proposals gated through all three
|
|
281
281
|
drivers (plus one planted tracking-decorated mirror of the first source, so the
|
|
@@ -291,12 +291,12 @@ dedup stage has a real duplicate to catch). Total spend $0.033:
|
|
|
291
291
|
| **total** | **25** | **25** | **12 / 25 / $0.0261** | **20 / 6 / $0.0068** |
|
|
292
292
|
|
|
293
293
|
Adaptive cuts LLM verifier calls **76%** (25 → 6) and dollars **74%** ($0.0261 →
|
|
294
|
-
$0.0068). On 3 of the 5 topics it spent **zero** LLM calls
|
|
294
|
+
$0.0068). On 3 of the 5 topics it spent **zero** LLM calls, every unique survivor
|
|
295
295
|
was on an authoritative host, so the $0 stages decided everything.
|
|
296
296
|
|
|
297
297
|
It is a frontier point, not a free lunch. Admitted counts (lower = cleaner): single
|
|
298
298
|
25, **adaptive 20**, full-LLM 12. Adaptive removes the 5 real duplicates the $0 dedup
|
|
299
|
-
catches
|
|
299
|
+
catches, exactly the de-dup-dominated win, but keeps the 8 sources full-LLM rejects
|
|
300
300
|
on relevance, because on this authoritative-host-heavy set the heuristic resolved
|
|
301
301
|
every non-duplicate survivor without ever asking the LLM, and the host prior is
|
|
302
302
|
coarser than the relevance judge. So adaptive **recovers the deterministic de-dup
|
|
@@ -304,26 +304,26 @@ half of full-LLM's cleanliness for ~26% of its dollars, and gives up the
|
|
|
304
304
|
relevance-judgment half**. The escalation count is the diagnostic: on the 3 topics
|
|
305
305
|
where it was zero, adaptive *is* a pure host/title/length rule and the LLM
|
|
306
306
|
contributes nothing by construction; on the 2 topics with unknown-host survivors
|
|
307
|
-
(grouped-query attention, LoRA) it escalated 3 calls each
|
|
307
|
+
(grouped-query attention, LoRA) it escalated 3 calls each, the off-scope tail the
|
|
308
308
|
verifier is actually for.
|
|
309
309
|
|
|
310
310
|
## 6. Discussion
|
|
311
311
|
|
|
312
312
|
The three results compose into one rule. The LLM verifier's headline cleanliness win
|
|
313
313
|
is real (§3) but **de-dup-dominated** (§4.1) and **expensive** (§4.2, ~5×/9×/3×), so
|
|
314
|
-
spending an LLM call on every source is the wrong default
|
|
314
|
+
spending an LLM call on every source is the wrong default, a free content hash buys
|
|
315
315
|
most of it. The verifier earns its 5× exactly where the cheap signals are blind: on
|
|
316
316
|
**misattribution** (§5.1), where a $0 text-presence check beats the LLM judge
|
|
317
317
|
outright because the judge never sees the claim; and on the **off-scope tail** (§5.2),
|
|
318
318
|
where a page looks on-topic, is unique, and isn't fabricated, so only a relevance
|
|
319
319
|
judgment can settle it. The deployable loop therefore stratifies by cost: free dedup,
|
|
320
|
-
free claim-grounding, free heuristic triage, then an LLM call only on what survives
|
|
320
|
+
free claim-grounding, free heuristic triage, then an LLM call only on what survives:
|
|
321
321
|
which is what the adaptive driver ships.
|
|
322
322
|
|
|
323
323
|
Two cross-cutting lessons. First, **the accounting unit decides the verdict**:
|
|
324
324
|
charging the verify step as one pass made the topology look near-free; pricing it per
|
|
325
325
|
LLM call (§4.2) is what surfaced the 5× and motivated everything after it. Second,
|
|
326
|
-
**the same verifier inverts in value across bands
|
|
326
|
+
**the same verifier inverts in value across bands**, on de-dup the LLM is expensive
|
|
327
327
|
for what a hash does; on misattribution a deterministic check is free for what the LLM
|
|
328
328
|
can't do; on the off-scope tail the LLM is the only thing that works. "Add a verifier"
|
|
329
329
|
is not a setting; it is a cost-stratified decision per error type.
|
|
@@ -344,7 +344,7 @@ is not a setting; it is a cost-stratified decision per error type.
|
|
|
344
344
|
- **Planted error bands.** The misattributions (§5.1) and the adaptive duplicate
|
|
345
345
|
(§5.2) are injected so the band is measurable. They model the real LLM
|
|
346
346
|
citation-fabrication and mirror-host failures but do not measure their base rate in
|
|
347
|
-
the wild
|
|
347
|
+
the wild, that needs a hand-checked corpus of model-written citations.
|
|
348
348
|
- **Adaptive's quality is host-prior-bound.** On an authoritative-host-heavy source
|
|
349
349
|
pool the heuristic resolves everything and the LLM's relevance judgment contributes
|
|
350
350
|
nothing; a richer worker (good sources on unknown hosts, junk on on-topic-looking
|
|
@@ -356,20 +356,20 @@ is not a setting; it is a cost-stratified decision per error type.
|
|
|
356
356
|
- **High web variance.** One live run per topic per result; numbers move with what
|
|
357
357
|
search returns.
|
|
358
358
|
|
|
359
|
-
## 8. A simpler loop
|
|
359
|
+
## 8. A simpler loop: built, not deferred
|
|
360
360
|
|
|
361
361
|
The original write-up named two simplifications as future work. Both are now built and
|
|
362
362
|
measured; this is what changed.
|
|
363
363
|
|
|
364
|
-
1. **Deterministic dedup before the LLM, LLM only on the tail
|
|
364
|
+
1. **Deterministic dedup before the LLM, LLM only on the tail, shipped.** The
|
|
365
365
|
adaptive driver (`src/adaptive-driver.ts`, §5.2) does exactly this: free
|
|
366
366
|
canonical-URL / content-hash dedup, free host/title/length triage, LLM relevance
|
|
367
367
|
only on the ambiguous survivors. Measured: **76% fewer LLM calls, 74% cheaper**,
|
|
368
368
|
recovering the de-dup half of the verifier's cleanliness. The remaining gap to
|
|
369
|
-
full-LLM is the relevance-judgment half,
|
|
369
|
+
full-LLM is the relevance-judgment half, measured separately in §5.2, adaptive is a
|
|
370
370
|
frontier point you choose by how much a kept-but-marginal source costs you, not a
|
|
371
371
|
strict improvement.
|
|
372
|
-
2. **A free check the LLM judge can't replicate
|
|
372
|
+
2. **A free check the LLM judge can't replicate, shipped.** Claim-grounding
|
|
373
373
|
(`src/claim-grounding.ts`, §5.1) adds the one verification an LLM relevance judge is
|
|
374
374
|
structurally blind to: does the cited claim actually appear in the page? It catches
|
|
375
375
|
5/5 planted misattributions at **$0**, vs the judge's 4/5 at ~$0.003/topic.
|
|
@@ -377,19 +377,19 @@ measured; this is what changed.
|
|
|
377
377
|
What is still **not** built remains the worker: the live worker is a ~500-line
|
|
378
378
|
hand-wired pipeline (query-gen, search, fetch, propose) against the router directly,
|
|
379
379
|
where the runtime integration's pattern is to author an agent profile
|
|
380
|
-
and run it on a harness with a web-search tool
|
|
380
|
+
and run it on a harness with a web-search tool, reusable and harness-agnostic. The
|
|
381
381
|
direct pipeline is cheaper to run today (no harness, no creds beyond the router) but it
|
|
382
382
|
is the loop's main remaining piece of duplication, and the obvious next step if this
|
|
383
383
|
loop graduates from experiment to production.
|
|
384
384
|
|
|
385
|
-
## 9. From hygiene to depth
|
|
385
|
+
## 9. From hygiene to depth: a research-DRIVING loop, measured on held-out deep questions
|
|
386
386
|
|
|
387
|
-
Everything above measures one thing: **source hygiene
|
|
387
|
+
Everything above measures one thing: **source hygiene**, how *few* sources a verifier
|
|
388
388
|
admits at equal coverage. That is the right metric for a verifier whose only job is to
|
|
389
389
|
filter, and it is why the win turned out to be de-duplication (§4.1): the most a
|
|
390
390
|
filter-only verifier can do is reject. By construction it cannot make the knowledge base
|
|
391
391
|
*answer more*; it can only make it *carry less*. So "the verifier mostly deduplicates" is
|
|
392
|
-
not a disappointing finding about *this* verifier
|
|
392
|
+
not a disappointing finding about *this* verifier, it is the ceiling of what *any*
|
|
393
393
|
admit-or-reject step can do. To ask whether a second agent can improve the research
|
|
394
394
|
itself, you have to change both the agent and the metric.
|
|
395
395
|
|
|
@@ -398,17 +398,17 @@ So we built the opposite agent and gave it the opposite metric. The **driving dr
|
|
|
398
398
|
extracts each fetched source's claims, demands a second independent source for every
|
|
399
399
|
claim, generates comparative / mechanism / contradiction sub-questions, and steers the
|
|
400
400
|
worker to chase them in the next round. Its thesis is that *driving the research deeper*
|
|
401
|
-
|
|
402
|
-
not on admitted-count (which would score its whole point as a regression
|
|
401
|
+
- not pruning it, builds a knowledge base that answers harder questions. We measure it
|
|
402
|
+
not on admitted-count (which would score its whole point as a regression, it admits
|
|
403
403
|
*more*) but on a **firewalled exam of 20 deep questions across 5 ML topics**
|
|
404
404
|
(`tests/loops/held-out-exam.ts`), graded with a $0 deterministic substring grader the
|
|
405
|
-
loop never sees. The questions are depth questions by construction
|
|
405
|
+
loop never sees. The questions are depth questions by construction, the grader scores
|
|
406
406
|
**0/20** on a one-line topic definition and **20/20** on a mechanism-rich paragraph, so
|
|
407
407
|
a high score is reachable only by depth, not by grader slack. All three arms run the
|
|
408
408
|
same real web worker and differ only in the driver: (A) plain collection, (B)
|
|
409
409
|
verify/dedup, (C) driving.
|
|
410
410
|
|
|
411
|
-
**
|
|
411
|
+
**Result: driving does NOT reliably beat plain collection, and costs
|
|
412
412
|
~12–16× more.** The tell is that the winner flips with the compute budget, on the same
|
|
413
413
|
exam:
|
|
414
414
|
|
|
@@ -420,55 +420,55 @@ exam:
|
|
|
420
420
|
|
|
421
421
|
Driving "wins" at B=4 (16 > 15 > 13) and "loses" at B=6 (13 < 15), while the
|
|
422
422
|
single-agent arm itself swings 15→13 across the two budgets. At n=5 topics a ±1–3
|
|
423
|
-
question difference is inside the run-to-run web variance
|
|
423
|
+
question difference is inside the run-to-run web variance, the **within-arm swing is as
|
|
424
424
|
large as the between-arm gap**, which is the signature of a null. What is stable and
|
|
425
425
|
large is the cost: an order of magnitude more dollars and ~24× the tokens, for the
|
|
426
426
|
claim-extraction LLM call driving runs on every fetched source.
|
|
427
427
|
|
|
428
428
|
The autopsy explains it: every arm finished in **one effective round**
|
|
429
|
-
(`passes=2` on every topic at every budget). The generic readiness gate
|
|
430
|
-
closes the gap"
|
|
429
|
+
(`passes=2` on every topic at every budget). The generic readiness gate, "one source
|
|
430
|
+
closes the gap", is met by the first fetch, so the loop stops *before* the driving
|
|
431
431
|
driver ever steers a second round, and its entire mechanism is multi-round. So we gave
|
|
432
|
-
it
|
|
433
|
-
actually steers. It **still ties** a blind worker that just re-searches the same gaps
|
|
434
|
-
**8/12 vs 8/12, at ~9× the cost**. Driving was better on RLHF (3 vs 1
|
|
432
|
+
it a controlled test: a probe that *forces* three rounds so the driver
|
|
433
|
+
actually steers. It **still ties** a blind worker that just re-searches the same gaps:
|
|
434
|
+
**8/12 vs 8/12, at ~9× the cost**. Driving was better on RLHF (3 vs 1, chasing
|
|
435
435
|
corroboration reached a page blind search missed) and worse on speculative decoding (2
|
|
436
|
-
vs 4
|
|
436
|
+
vs 4, steering pulled the worker *off* the pages that answered the exam); the two
|
|
437
437
|
cancel. The null survives the fix, so it is not an artifact of a permissive gate.
|
|
438
438
|
|
|
439
|
-
The durable output is the
|
|
439
|
+
The durable output is the evaluation method, not the agent: a firewalled deep-question exam with
|
|
440
440
|
a $0 grader that can tell depth from surface, reusable for any future research-quality
|
|
441
441
|
claim. Full result, per-topic tables, and the probe: [`docs/results/research-driving.md`](results/research-driving.md).
|
|
442
442
|
The two findings compose into one rule for "should I add a second research agent?":
|
|
443
443
|
a **filter** agent measured on hygiene buys de-dup cleanliness you can get cheaper from a
|
|
444
444
|
hash (§3–§4); a **driver** agent measured on depth buys nothing reliable over plain
|
|
445
445
|
collection at this n and worker, for 9–16× the cost (§9). Neither earns a blanket "yes";
|
|
446
|
-
both earn a narrow, cost-stratified one
|
|
446
|
+
both earn a narrow, cost-stratified one, the verifier on misattribution and the
|
|
447
447
|
off-scope tail (§5), the driver only where a richer worker makes "go corroborate this"
|
|
448
448
|
reach a page collection can't.
|
|
449
449
|
|
|
450
|
-
### 9.1 The domain was too easy
|
|
450
|
+
### 9.1 The domain was too easy: re-running the A/B where one search is not enough
|
|
451
451
|
|
|
452
452
|
The §9 null has a structural cause, not a measurement one: **on an ML topic a single
|
|
453
453
|
good search already collects the answer.** Every arm finished in one effective round
|
|
454
|
-
because the first fetch met the readiness gate, so the driving driver
|
|
455
|
-
is steering a *second* round
|
|
454
|
+
because the first fetch met the readiness gate, so the driving driver, whose mechanism
|
|
455
|
+
is steering a *second* round, never acted. When one search suffices, there is no
|
|
456
456
|
investigation for a smarter coordinator to do, and the metric can only reward
|
|
457
457
|
collection. To ask whether topology *can ever* beat blind collection, you have to move
|
|
458
458
|
to a domain where the answer is buried and a single fetch provably cannot surface it.
|
|
459
459
|
|
|
460
|
-
So we did. We ported the
|
|
461
|
-
grader, matched-compute 3-arm A/B
|
|
460
|
+
So we did. We ported the full method, firewalled checklist, `$0` model-free
|
|
461
|
+
grader, matched-compute 3-arm A/B, onto **investment research**: give a loop a company
|
|
462
462
|
+ ticker + an as-of cutoff and grade the thesis on the buried, material 10-K-footnote
|
|
463
463
|
facts a ticker search misses (an HTM mark the size of a bank's equity, a 97%-uninsured
|
|
464
464
|
deposit base, a negative per-unit margin). First we *calibrated* the new metric and
|
|
465
|
-
proved it discriminates depth on this harder domain
|
|
465
|
+
proved it discriminates depth on this harder domain, a shallow ticker summary scores
|
|
466
466
|
**1/27 (4%)**, a deep filings-grounded thesis **27/27 (100%)**, a **+96-point** gap.
|
|
467
467
|
Then the live 3-arm A/B over 5 held-out companies: **driving surfaced the most buried
|
|
468
|
-
facts (16/27, 59%) vs blind collection (11/27, 41%)** for ~1.9× the cost
|
|
468
|
+
facts (16/27, 59%) vs blind collection (11/27, 41%)** for ~1.9× the cost, the lift is
|
|
469
469
|
real and points the right way, but at n=5 the paired-bootstrap CI still crosses zero
|
|
470
470
|
(P(Δ≤0)=0.08), and verify did not beat collection (10/27). So the verdict survives the
|
|
471
|
-
domain change: **no topology *significantly* beats collection
|
|
471
|
+
domain change: **no topology *significantly* beats collection, but on a domain where
|
|
472
472
|
the answer must be investigated for, driving is the only arm that even leans positive,
|
|
473
473
|
and it does so suggestively, not significantly.** Full reframe, calibration, and
|
|
474
474
|
per-company A/B: [`docs/results/investment-thesis.md`](results/investment-thesis.md).
|
|
@@ -484,7 +484,7 @@ multi-topic burn.
|
|
|
484
484
|
git clone https://github.com/tangle-network/agent-knowledge
|
|
485
485
|
cd agent-knowledge && pnpm install
|
|
486
486
|
|
|
487
|
-
# offline A/B
|
|
487
|
+
# offline A/B: deterministic, no credentials (a controlled lower bound that
|
|
488
488
|
# exercises the same harness against a planted source pool)
|
|
489
489
|
pnpm exec vitest run tests/loops/research-loop-equal-compute.test.ts
|
|
490
490
|
|
|
@@ -492,29 +492,29 @@ pnpm exec vitest run tests/loops/research-loop-equal-compute.test.ts
|
|
|
492
492
|
pnpm exec vitest run tests/loops/claim-grounding-ab.test.ts -t "offline"
|
|
493
493
|
pnpm exec vitest run tests/loops/adaptive-ab.test.ts
|
|
494
494
|
|
|
495
|
-
# the live cleanliness sweep
|
|
495
|
+
# the live cleanliness sweep: real web search + a real glm-5.2 verifier, with
|
|
496
496
|
# per-arm cost reported (~$0.20 for 9 topics)
|
|
497
497
|
export TANGLE_API_KEY=<router key with glm-5.2 credits>
|
|
498
498
|
AGENT_KNOWLEDGE_LIVE=1 \
|
|
499
499
|
AGENT_KNOWLEDGE_LIVE_GOALS="self-speculative decoding|grouped-query attention|rotary position embeddings|KV-cache quantization|LoRA|ring attention|constitutional AI|the transformer architecture|gradient descent" \
|
|
500
500
|
pnpm exec vitest run tests/loops/research-loop-equal-compute.test.ts
|
|
501
501
|
|
|
502
|
-
# live misattribution band
|
|
502
|
+
# live misattribution band: three verifier arms over the same proposals
|
|
503
503
|
AGENT_KNOWLEDGE_LIVE=1 TANGLE_API_KEY=<…> \
|
|
504
504
|
CLAIM_GROUNDING_LIVE_GOALS='self-speculative decoding|rotary position embeddings|grouped-query attention|KV-cache quantization|LoRA' \
|
|
505
505
|
pnpm exec vitest run tests/loops/claim-grounding-ab.test.ts -t "three verifier arms"
|
|
506
506
|
|
|
507
|
-
# live adaptive frontier
|
|
507
|
+
# live adaptive frontier: single / full-LLM / adaptive on the same fetched proposals
|
|
508
508
|
AGENT_KNOWLEDGE_LIVE=1 TANGLE_API_KEY=<…> \
|
|
509
509
|
ADAPTIVE_LIVE_GOALS="self-speculative decoding|rotary position embeddings|grouped-query attention|KV-cache quantization|LoRA fine-tuning" \
|
|
510
510
|
pnpm exec vitest run tests/loops/adaptive-ab.test.ts -t "three-topology"
|
|
511
511
|
|
|
512
|
-
# the research-DRIVING 3-arm A/B (§9)
|
|
512
|
+
# the research-DRIVING 3-arm A/B (§9): collect / verify / drive, graded on the
|
|
513
513
|
# held-out deep-question exam; re-run at RQ_LIVE_BUDGET=6 to see the verdict flip
|
|
514
514
|
AGENT_KNOWLEDGE_LIVE=1 RQ_LIVE_BUDGET=4 TANGLE_API_KEY=<…> \
|
|
515
515
|
pnpm exec vitest run tests/loops/research-driving-ab.test.ts -t "3-arm A/B"
|
|
516
516
|
|
|
517
|
-
# the controlled multi-round probe
|
|
517
|
+
# the controlled multi-round probe: forces 3 rounds so the driver actually steers
|
|
518
518
|
AGENT_KNOWLEDGE_LIVE=1 RQ_PROBE=1 RQ_PROBE_ROUNDS=3 TANGLE_API_KEY=<…> \
|
|
519
519
|
pnpm exec vitest run tests/loops/research-driving-ab.test.ts -t "multi-round probe"
|
|
520
520
|
```
|
|
@@ -523,17 +523,17 @@ AGENT_KNOWLEDGE_LIVE=1 RQ_PROBE=1 RQ_PROBE_ROUNDS=3 TANGLE_API_KEY=<…> \
|
|
|
523
523
|
topic list; the live arms run the loops on each at equal compute and report the paired
|
|
524
524
|
bootstrap and per-arm cost.
|
|
525
525
|
|
|
526
|
-
**Source:** the loop
|
|
527
|
-
the live worker + verifier + cost instrumentation
|
|
528
|
-
the misattribution check
|
|
529
|
-
the adaptive driver
|
|
530
|
-
the driving driver
|
|
531
|
-
the held-out exam + $0 grader
|
|
532
|
-
the A/B harnesses
|
|
526
|
+
**Source:** the loop, [`src/two-agent-research-loop.ts`](../src/two-agent-research-loop.ts);
|
|
527
|
+
the live worker + verifier + cost instrumentation, [`src/web-research-worker.ts`](../src/web-research-worker.ts);
|
|
528
|
+
the misattribution check, [`src/claim-grounding.ts`](../src/claim-grounding.ts);
|
|
529
|
+
the adaptive driver, [`src/adaptive-driver.ts`](../src/adaptive-driver.ts);
|
|
530
|
+
the driving driver, [`src/research-driving-driver.ts`](../src/research-driving-driver.ts);
|
|
531
|
+
the held-out exam + $0 grader, [`tests/loops/held-out-exam.ts`](../tests/loops/held-out-exam.ts);
|
|
532
|
+
the A/B harnesses, [`tests/loops/`](../tests/loops/).
|
|
533
533
|
Per-result detail: [`docs/results/cost-quality.md`](results/cost-quality.md),
|
|
534
534
|
[`docs/results/claim-grounding.md`](results/claim-grounding.md),
|
|
535
535
|
[`docs/results/adaptive.md`](results/adaptive.md),
|
|
536
536
|
[`docs/results/research-driving.md`](results/research-driving.md),
|
|
537
|
-
[`docs/results/investment-thesis.md`](results/investment-thesis.md) (§9.1
|
|
537
|
+
[`docs/results/investment-thesis.md`](results/investment-thesis.md) (§9.1, the domain reframe + calibration + 3-arm A/B).
|
|
538
538
|
</content>
|
|
539
539
|
</invoke>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-knowledge",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "Source-grounded, eval-gated knowledge growth primitives for agents.",
|
|
5
5
|
"homepage": "https://github.com/tangle-network/agent-knowledge#readme",
|
|
6
6
|
"repository": {
|
|
@@ -78,21 +78,18 @@
|
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"@biomejs/biome": "^2.5.4",
|
|
80
80
|
"@neo4j-labs/agent-memory": "0.4.0",
|
|
81
|
-
"@
|
|
82
|
-
"@types/node": "^25.6.0",
|
|
81
|
+
"@types/node": "^26.1.1",
|
|
83
82
|
"@types/proper-lockfile": "4.1.4",
|
|
84
83
|
"mem0ai": "3.1.0",
|
|
85
84
|
"tsup": "^8.0.0",
|
|
86
|
-
"tsx": "^4.23.1",
|
|
87
85
|
"typescript": "^5.7.0",
|
|
88
|
-
"vitest": "^
|
|
86
|
+
"vitest": "^4.1.10"
|
|
89
87
|
},
|
|
90
88
|
"pnpm": {
|
|
91
89
|
"minimumReleaseAge": 4320,
|
|
92
90
|
"minimumReleaseAgeExclude": [
|
|
93
91
|
"@tangle-network/agent-eval",
|
|
94
|
-
"@tangle-network/agent-interface"
|
|
95
|
-
"@tangle-network/sandbox"
|
|
92
|
+
"@tangle-network/agent-interface"
|
|
96
93
|
],
|
|
97
94
|
"overrides": {
|
|
98
95
|
"hono": "4.12.30",
|