feat(tools): export provider-neutral knowledge tools and record a no-use retrieval - #168
Merged
Conversation
17 tasks
tangletools
approved these changes
Aug 21, 2026
tangletools
left a comment
Contributor
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 0c2281ab
This PR was opened by the trusted drewstone account.
This approval is provisional and was applied by the local stand-in because the pr-reviewer webhook host is unreachable (2026-08-21). CI on this head is fully green. The full PR reviewer audit re-runs via the resweep when the service returns and will publish findings if it detects issues.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Two gaps, both from #151, and one of them is what makes every earlier PR in this wave reachable by an agent.
No tool adapter. Knowledge exported no
ToolDefinition, and agent-runtime exported none either (grep'd: it imports agent-knowledge in 5 files, none of which expose search, read, record, or resolve). Every consumer had to write its own adapter, which is how the discovery-lab fork started.No
no-usedisposition. A use receipt requires a selected rank, so a retrieval that influenced nothing left no record at all. "No evidence of use" and "evidence of no use" were indistinguishable in the ledger — and the second is the interesting one when you are measuring whether retrieval changes behaviour.What
createKnowledgeTools({ stores, runId, retrieverVersion, actorId?, pagesDirectory?, intake?, brief?, recordRetrieval? })returns fourToolDefinitions using the neutral shape from@tangle-network/agent-interface. Knowledge owns every handler; a runtime transports the definitions and the calls and runs no knowledge loop.knowledge_search→buildKnowledgeBriefover the run's chain, then a retrieval receipt on every call, handed torecordRetrievaland returned in the result. Retrieval is recorded by the infrastructure, not claimed by the run.knowledge_read→ chain read by qualified id. An id visible at two origins is reportedambiguouswith both candidates and is never silently resolved to one.knowledge_record→applyKnowledgeWriteBlocksinto this run's store, with the intake gate and the inherited chain entries as its corpus.knowledge_resolve→resolveRunScopedCitations, returning each reference's status without hiding an ambiguity.retrieverVersionis required rather than inferred: a bundled build cannot read its own manifest, and a receipt that guessed the version would be a receipt that lies about what ranked the results.createKnowledgeRetrievalDisposition/verifyKnowledgeRetrievalDispositionrecord a retrieval that influenced nothing. The disposition binds to oneretrievalReceiptDigest, carriesrelation: 'irrelevant' | 'no-use', and has no rank — that absence is the whole point.irrelevantmeans the returned pages did not bear on the question;no-usemeans they did and the consumer used none of them.Simplification
Simplification: the block that copies actor identity from a retrieval receipt into a downstream record (
runId,actorId,profileDigest,executionRef,retrievalReceiptDigest) was about to exist twice. It is nowretrievalIdentity(retrieval), and bothuseMaterialanddispositionMaterialroute through it, so a downstream record cannot disagree with the receipt it references.Net: +531 / -10 lines, 9 files, 1 identity-copy block collapsed to 1 owner before a second copy existed, 0 new schemas beyond the disposition itself (it reuses the receipt module's version, digest algorithm, consumer ref, evidence refs, and attribute normalizers).
Not done here: no MCP or provider-specific packaging;
ToolDefinitionis the neutral contract and adapting it is the runtime's job. No sensitivity-policy seam on the tools; the application still filters by supplying roots and brief options.Tests: +4 (a search mints a receipt that the visibility snapshot verifies and joins, which is the contract that makes retrieval provable through the tool rather than only through the API; a recorded proposal with a dangling cite is refused, which proves the intake gate is actually wired into the tool and not merely typed; an id visible at two origins reports both candidates and resolves only when qualified, the run-scoped invariant that is easy to break by "helpfully" picking one; a disposition verifies against its own retrieval and is refused against another, the binding that stops a no-use record from being reattached), -0 deleted. No shape assertions.
Proof
128 local failures — the same number and the same files as the four merged PRs before this one and as clean
origin/mainon this macOS host. Every one raisesknowledge transaction directory escaped its rootfrom the/var->/private/varsymlink undertmpdir(). Linux CI has no such symlink; the new tests realpath their roots and are green locally.Closes #157
Refs #151