Chapter 30

A Tool's Efficiency Is Measured in Calls

Chapter 29 settled what a measurement has to carry before it means anything. This chapter spends that discipline on the first question Part 4 asks of the design: does the way memory leaves the system, described in Chapter 20, actually cost an Agent less than the alternative?

The easiest thing to measure about a tool is how many milliseconds one call takes. It is also close to the least useful.

1. The cost an Agent pays is the number of calls, not the speed of one

An Agent does not experience a tool one call at a time. It experiences a question and whatever sequence of calls the tool forces before the question is answered. One path searches, opens a Node, checks its relations, opens a Record, looks again and then answers. The other receives the Node with its evidence and relations at once and answers.

If every individual call in both paths runs at the same speed, the second path is still far cheaper, and no latency number will say so. So the metric Vinc measures its own tools on is calls to resolution, and that metric explicitly excludes latency. Two runs have been taken against it and neither timed a call.

2. Counting calls alone rewards a tool for finding nothing

One call that returns nothing has an excellent call count. So call count is read beside the rest:

AxisWhat it asks
Task successwas the question actually answered
Calls to resolutionhow many round trips it took
Wasted call ratehow many of those contributed nothing
Payloadhow much material the model had to read
Attributioncan the answer say what it rests on
Recoverywhat happened after an empty or wrong result

3. What was actually run

Seven tasks, twice. A baseline on 28 August 2026 before the composite tool existed, and the same seven tasks again on 30 August with it deployed, in two arms: a hand-written chain of primitives, and the composite tool first with the chain as recovery.

Both arm policies were written down and frozen before the first task ran. Without that, the comparison measures how well the prompts were written rather than what the tools do. One rule bound both arms: no target identifier learned from the earlier document could be followed, only identifiers that appeared in that task's own output.

RunCallsUsefulWastedWaste rateTask success
Baseline, 28 August159640 %6 of 7
Chain arm, 30 August106440 %5 of 7
Composite first, 30 August1661062.5 %5 of 7
Composite with a search in front of it2061470 %5 of 7

The last row is reported separately because it is a measurement error made visible rather than hidden. The composite performs a search internally, so putting a search in front of it charges it twice for one retrieval. On the four tasks where it never needed a separate search, adding one cost exactly four calls and bought nothing. The composite is a tool that contains search, not a competitor to it, so the third row is the one that means anything.

The chain arm improved on its own baseline, 15 calls to 10, with no tooling change at all. Two things account for it and neither is the new tool: a policy amendment that dereferences an identifier the question already supplied instead of searching for it, and seeding the graph call on the Record rather than the Concept, which an earlier run had already written down after losing two calls to an eighty thousand character overflow. That is a measurement paying itself back.

4. The axis was not question shape, it was node kind

The baseline had predicted where the composite would win: on relation and traversal questions, since single fact lookups were already near the floor. Both halves were refuted. The composite won nothing on the traversal questions, and its only two wins were single fact lookups, both wins of material rather than of call count.

What actually predicted the outcome was the kind of the node the question was about.

Target kindResultn
Conceptresolved6 of 6
Decisionresolved2 of 2
Recordreported nothing found0 of 5
Episodenever became a candidate0 of 1

Read in the code, the cause was one line. The resolution path took the kind from the identifier prefix and then discarded it for anything outside the two semantic kinds, so record:foo was queried as a Concept with that identifier, matched nothing, and answered "unknown node". Episode had its own branch; Record never got one.

Two things make this worth a chapter rather than a bug report. The first is that the status lied in a specific direction: the contract defines "nothing found" as the question having matched nothing, when in fact the question had matched precisely and the loader had refused. A caller cannot tell those apart, and only one of them is worth retrying. The second is that the failing axis is invisible from the question. An Agent cannot look at what it is about to ask and route around a defect keyed to the kind of node it does not yet know it will land on.

The defect was found by the measurement and fixed afterwards. The Record branch shipped and was verified against the live hub on 2 September 2026, resolving all five queries that had failed, and the Episode branch shipped as well. One thing was deliberately left open: the ranking tie-break of Chapter 31's language problem, which touches every query and needs its own evaluation rather than a fix made in passing.

5. Payload crosses over at about fifteen links

Returned bytes and cited bytes were recorded separately, which turns out to matter more than either alone. On the one task where both arms resolved:

ArmReturnedCited in the answerUsed
Search, limit ten7,697 B56 B0.73 %
The composite1,406 B178 B12.66 %

Five and a half times less returned, three and a bit times more of it used. But the two payloads scale differently and that is the durable finding. A search at a fixed limit is roughly flat, about 7.7 KB whatever the answer. The composite is linear in the node's degree, measured at about 455 bytes per link, so it is the cheaper of the two below roughly fifteen links and the dearer above. Past that it degrades rather than growing without bound: a node with twenty five edges came back truncated at twenty four, which is the size limiter doing its job.

That correction matters on its own. An earlier measurement had put a link at 208 characters. That figure is a floor for a bare link, not an estimate of the response size, because the notes projected into those links routinely run past a thousand characters.

6. Attribution is the axis where only one arm can enter

Every identifier the composite's answers cited was in the list of grounds it had returned: three of three resolved tasks, no unattributable claim.

The chain arm cannot produce that number at all. A search returns hits with no statement of what an answer built on them would rest on, so attribution has to be reconstructed by hand afterwards and cannot be audited. This is the one axis where the composite is not ahead but is the only entrant, and it is what stops the efficiency metrics from quietly rewarding a tool for returning less.

7. What these runs do not support

Stated here as Chapter 29 requires. One session, one rater, seven tasks, no second grader: this is a spike, not a benchmark. The rater had read the earlier run before starting, so the absolute call counts are worth less than the difference between the arms, which that contamination affects equally. The vector arm was not stable during the run: eight calls fused both arms and four fell back to text with a read timeout, so most numbers here carry that variance. No latency was measured, by the metric's own definition.

One finding survives all of it, because both of its decisive calls ran with both arms live: a Korean question missed an English-titled Decision, and an English question missed a Korean-titled Concept. A fused semantic arm did not bridge either direction. Retrieval was matching the language of the query against the language of the title.

That is a question about the embedding space rather than about the tool, and it is the next chapter.

Continue with Chapter 31, How Embedding Models Get Compared.