You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
contextweaver routes tools based on static metadata (descriptions, tags, names) using TF-IDF and Jaccard scoring. It has no knowledge of which tools are actually used together in practice. This means:
A tool frequently called after another gets no routing score boost
Common tool sequences (e.g., "search" → "summarize" → "email") are invisible to the routing engine
The EpisodicStore exists but only stores individual events, not tool usage relationships
ChainWeaver (#11, #12) captures runtime traces and proposes candidate flows. But contextweaver has no mechanism to receive this relationship data and use it to improve routing decisions.
Why it matters
Pillar 3 — "Use an LM to understand the relationship between tools" starts with observing which tools relate in practice, not just in description.
Smarter routing — If "search_emails" is followed by "summarize_text" 80% of the time, and the user just called "search_emails", "summarize_text" should be boosted in the next routing decision.
Unit tests: record pairs, query scores, top-k, integration with Router
No new runtime dependencies
Implementation Notes
classCoOccurrenceTracker:
"""Tracks and queries tool co-occurrence frequency across sessions."""defrecord(self, tool_a: str, tool_b: str) ->None:
"""Record that tool_b was used after tool_a."""
...
defscore(self, tool_a: str, tool_b: str) ->float:
"""Co-occurrence score (0.0-1.0), normalized by total observations."""
...
deftop_k(self, tool_a: str, k: int=5) ->list[tuple[str, float]]:
"""Top-k tools most frequently used after tool_a."""
...
defexport(self) ->dict[str, dict[str, int]]:
"""Export raw counts for use by ChainWeaver's chain analysis."""
...
Integration with Router:
# In Router.route() scoring:base_score=self.scorer.score(query, candidate_id)
co_score=self.co_occurrence.score(last_tool_used, candidate_id) ifself.co_occurrenceelse0.0final_score= (1-co_weight) *base_score+co_weight*co_score
Files likely touched:
src/contextweaver/store/co_occurrence.py — new module
src/contextweaver/routing/router.py — optional co-occurrence signal
Context
contextweaver routes tools based on static metadata (descriptions, tags, names) using TF-IDF and Jaccard scoring. It has no knowledge of which tools are actually used together in practice. This means:
ChainWeaver (#11, #12) captures runtime traces and proposes candidate flows. But contextweaver has no mechanism to receive this relationship data and use it to improve routing decisions.
Why it matters
ChainAnalyzer.suggest_flows()(docs: add LlamaIndex ReActAgent integration guide + example #77) and determinism scoring ([eval] Add routing and context evaluation harness with gold-standard datasets #12). contextweaver can be the observation source.Acceptance Criteria
CoOccurrenceTrackerclass that records tool usage pairsrecord(tool_a: str, tool_b: str) -> None— record that tool_b followed tool_a in a sessionscore(tool_a: str, tool_b: str) -> float— co-occurrence score (0.0–1.0, normalized)top_k(tool_a: str, k: int) -> list[tuple[str, float]]— most frequently paired toolsEpisodicStoreor a new lightweight store (append-only, per conventions)Routercan optionally use co-occurrence scores as a signal (blended with TF-IDF/BM25 scores)co_occurrence_weight: float = 0.0(default off, backward-compatible)Implementation Notes
Integration with Router:
Files likely touched:
src/contextweaver/store/co_occurrence.py— new modulesrc/contextweaver/routing/router.py— optional co-occurrence signaltests/test_store_co_occurrence.py— newsrc/contextweaver/store/__init__.py— exportDependencies