Node creation caps provenance at ten:
sourceObservationIds: observations.slice(0, 10).map((o) => o.id)
but mergeNode() re-unions with no cap:
function mergeNode(existing, incoming, obsIds, capturedAt) {
return {
...existing,
sourceObservationIds: [...new Set([
...existing.sourceObservationIds,
...incoming.sourceObservationIds,
...obsIds
])],
...
Because extraction re-observes the same entities continuously, the array grows monotonically for
the lifetime of the graph. There is no slice, length check, or config knob on that path (I
grepped slice|MAX|cap|limit around the field in dist/index.mjs for 0.9.28 — the create-time
slice is the only one).
Impact. graph-query returns node objects verbatim and accepts no field projection
(limit, maxDepth, nodeType, offset, query, startNodeId), so every consumer pays for
the accumulated provenance on every call. For an LLM agent that cost is context window.
Measured on a ~3-day-old graph (1,870 nodes / 2,974 edges):
|
|
graph/query "circuit" → 3 nodes |
22,514 chars |
worst node (asset_capital.py) |
500 ids, 15,159 chars, of which 633 chars is signal |
| waste on that node |
~95% |
500 is not a ceiling, just that day's value. The cost is worst precisely where the graph is most
useful, since the most heavily-referenced entities accumulate the most provenance.
There is also no per-node update endpoint (extract / build / reset /
snapshot-rebuild only), so operators cannot compact existing nodes in place; reset discards
the whole graph.
Suggested fixes (either would resolve it):
- Bound the merge, keeping the N most recent ids — mirrors the create-time cap and makes the two
paths consistent:
const MAX = getGraphMaxSourceIds(); // e.g. GRAPH_MAX_SOURCE_IDS, default 10
sourceObservationIds: [...new Set([...])].slice(-MAX)
- Add a projection/verbosity parameter to
graph-query (e.g. includeSources: false, or
returning sourceObservationCount instead of the full array) so consumers can opt out.
Ideally both: (1) bounds storage growth, (2) lets callers control payload independently.
Workaround in use. A local stdio proxy in front of the MCP shim truncates the field and adds
sourceObservationCount so provenance size is still visible. It takes the query above from
22,514 → 2,311 chars (90% reduction) with node properties preserved verbatim. Happy to
contribute the upstream patch if the maintainer prefers a PR over an issue.
Environment: @agentmemory/agentmemory 0.9.28, iii-engine 0.11.2, Windows 11,
EMBEDDING_PROVIDER=local, OpenAI-compatible LLM provider.
Node creation caps provenance at ten:
but
mergeNode()re-unions with no cap:Because extraction re-observes the same entities continuously, the array grows monotonically for
the lifetime of the graph. There is no
slice, length check, or config knob on that path (Igrepped
slice|MAX|cap|limitaround the field indist/index.mjsfor 0.9.28 — the create-timeslice is the only one).
Impact.
graph-queryreturns node objects verbatim and accepts no field projection(
limit,maxDepth,nodeType,offset,query,startNodeId), so every consumer pays forthe accumulated provenance on every call. For an LLM agent that cost is context window.
Measured on a ~3-day-old graph (1,870 nodes / 2,974 edges):
graph/query "circuit"→ 3 nodesasset_capital.py)500 is not a ceiling, just that day's value. The cost is worst precisely where the graph is most
useful, since the most heavily-referenced entities accumulate the most provenance.
There is also no per-node update endpoint (
extract/build/reset/snapshot-rebuildonly), so operators cannot compact existing nodes in place;resetdiscardsthe whole graph.
Suggested fixes (either would resolve it):
paths consistent:
graph-query(e.g.includeSources: false, orreturning
sourceObservationCountinstead of the full array) so consumers can opt out.Ideally both: (1) bounds storage growth, (2) lets callers control payload independently.
Workaround in use. A local stdio proxy in front of the MCP shim truncates the field and adds
sourceObservationCountso provenance size is still visible. It takes the query above from22,514 → 2,311 chars (90% reduction) with node
propertiespreserved verbatim. Happy tocontribute the upstream patch if the maintainer prefers a PR over an issue.
Environment:
@agentmemory/agentmemory0.9.28, iii-engine 0.11.2, Windows 11,EMBEDDING_PROVIDER=local, OpenAI-compatible LLM provider.