Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ This package turns raw sources and generated markdown knowledge into a versionab
- [CLI](#cli) — `init` → `source-add` → `index` → `search` → `lint`
- [Design](#design) — the invariants (immutable sources, cited claims, deterministic graph)
- [Agent-Eval integration](#agent-eval-integration) — readiness bundles + release reports
- [Memory adapters](#memory-adapters) — generic memory contract + Neo4j Agent Memory bridge
- [Research loop](#research-loop) — `runKnowledgeResearchLoop` + control-loop adapter
- [Researcher profile](#researcher-profile) — sandbox `AgentProfile` for `runLoop`
- [Pluggable knowledge sources](#pluggable-knowledge-sources) — live authorities → eval re-runs
Expand Down Expand Up @@ -106,6 +107,10 @@ from `@tangle-network/agent-knowledge`.

The `/viz` subpath exports graph insight helpers without UI dependencies.

The `/memory` subpath exports an optional memory adapter contract. Use it to
bridge episodic or graph-native memory systems into the same source-grounded
readiness/eval machinery without making `agent-knowledge` own the database.

## Agent-Eval Integration

To answer whether a candidate knowledge base actually improves agent task success, run an `@tangle-network/agent-eval` improvement loop (`runImprovementLoop`) over your KB variants on a real task corpus; each run is scored into a `RunRecord`.
Expand Down Expand Up @@ -143,6 +148,38 @@ Pass `readiness.report` to `blockingKnowledgeEval()` from
`@tangle-network/agent-eval`; use `readiness.questions` and
`readiness.acquisitionPlans` to drive UI or connector workflows.

## Memory Adapters

`agent-knowledge` does not store operational memory itself. It defines the
contract that lets a runtime read/write memory through any backend, then turn
memory hits into `SourceRecord` evidence for readiness, linting, and eval gates.

```ts
import {
createNeo4jAgentMemoryAdapter,
memoryHitToSourceRecord,
} from '@tangle-network/agent-knowledge/memory'

const memory = createNeo4jAgentMemoryAdapter({ client: neo4jMemoryClient })

const context = await memory.getContext('What does this user prefer?', {
scope: { userId: 'user-123', sessionId: 'session-456' },
limit: 5,
})

const sourceRecords = context.hits.map((hit) =>
memoryHitToSourceRecord(hit, { scope: { userId: 'user-123' } }),
)
```

The Neo4j adapter is runtime dependency-free: pass the real
`@neo4j-labs/agent-memory` client in products, or a fake client in tests. CI
typechecks against `@neo4j-labs/agent-memory@0.4.0` and covers the published
TypeScript SDK surface: `shortTerm.addMessage/searchMessages/getContext`,
`longTerm.addEntity/addPreference/addFact/searchEntities/searchPreferences`,
and `reasoning.getSimilarTraces`. Generic `search` / `getContext` and
snake_case bridge-style methods remain supported for non-hosted clients.

## Research Loop

Use `runKnowledgeResearchLoop()` when an agent is acting as a researcher or
Expand Down
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
"import": "./dist/cli.js",
"default": "./dist/cli.js"
},
"./memory": {
"types": "./dist/memory/index.d.ts",
"import": "./dist/memory/index.js",
"default": "./dist/memory/index.js"
},
"./sources": {
"types": "./dist/sources/index.d.ts",
"import": "./dist/sources/index.js",
Expand Down Expand Up @@ -69,6 +74,7 @@
},
"devDependencies": {
"@biomejs/biome": "^2.4.15",
"@neo4j-labs/agent-memory": "0.4.0",
"@tangle-network/sandbox": "^0.4.0",
"@types/node": "^25.6.0",
"tsup": "^8.0.0",
Expand Down
9 changes: 9 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export * from './indexer'
export * from './inspect'
export * from './kb-store'
export * from './lint'
export * from './memory/index'
export * from './proposals'
export * from './propose-from-finding'
export * from './release'
Expand Down
32 changes: 32 additions & 0 deletions src/memory/adapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { memoryHitToSourceRecord } from './source-record'
import type {
AgentMemoryAdapter,
AgentMemoryContext,
AgentMemoryHit,
AgentMemorySearchOptions,
} from './types'

export async function defaultGetMemoryContext(
adapter: Pick<AgentMemoryAdapter, 'search'>,
query: string,
options: AgentMemorySearchOptions = {},
): Promise<AgentMemoryContext> {
const hits = await adapter.search(query, options)
return {
query,
hits,
sourceRecords: hits.map((hit) => memoryHitToSourceRecord(hit, { scope: options.scope })),
text: renderMemoryContext(hits),
}
}

export function renderMemoryContext(hits: AgentMemoryHit[]): string {
return hits
.map((hit, index) => {
const label = hit.title ?? `${hit.kind}:${hit.id}`
const score =
typeof hit.normalizedScore === 'number' ? ` score=${hit.normalizedScore.toFixed(3)}` : ''
return [`[${index + 1}] ${label}${score}`, hit.text].join('\n')
})
.join('\n\n')
}
5 changes: 5 additions & 0 deletions src/memory/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './adapter'
export * from './neo4j'
export * from './schemas'
export * from './source-record'
export * from './types'
Loading
Loading