contextweaver AGENTS.md

An instruction file for contextweaver, a Python library that prepares relevant information for AI agents and helps them choose among many tools. It describes the library’s modules, data types, and boundaries.

In plain words
What is it for?
Guiding development, navigation, and maintenance of the contextweaver codebase.
Why use it?
It gives coding agents a shared reference for how the project works and clarifies that it prepares context and tool-routing decisions without running models or tools.

Instructions file for CodexOpenCode

Install

Getting it into your agent

One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.

agentmods
npx agentmods add instructions/dgenio/contextweaver/agents-md
Clone the repo
git clone --depth 1 https://github.com/dgenio/contextweaver

Made for: Codex, OpenCode.

Per session 17,577 This file is loaded in full into every session.
When invoked 17,577 The same file — it is already loaded in full.
Security scan A 0 findings. Scan, not verified.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5 $0.17577 $0.17577
Opus 5 $0.08788 $0.08788
Sonnet 5 $0.03515 $0.03515
Haiku 4.5 $0.01758 $0.01758

Measured 2d ago against content hash efe713695b91, method: parsed. Prices are Anthropic first-party input rates as of 2026-08-30, from the pricing page.

Security

Grade A, and why

contextweaver AGENTS.md scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 2d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

AGENTS.md · 413 lines

How it starts

The opening of the file, as written. The whole thing — 413 lines — stays where its author put it; the contents beside it link to each section on GitHub.

contextweaver — Agent Guide

Authority: This file is the single source of truth for agent-facing guidance. Tool-specific files (.claude/CLAUDE.md, .github/copilot-instructions.md) contain only overrides and guardrails — they defer to this file for all shared rules.

Purpose

contextweaver is a Python library for dynamic context management for tool-using AI agents. It provides two integrated engines:

  1. Context Engine — phase-specific budgeted context compilation with a context firewall
  2. Routing Engine — bounded-choice navigation over large tool catalogs via DAG + beam search

Non-goals: contextweaver is not an LLM inference layer and not a tool execution runtime. It prepares context and routes tools but never calls models or executes tools.

Module Map

Path Responsibility
types.py Core dataclasses and enums: SelectableItem, ContextItem, Phase, ItemKind, Sensitivity
envelope.py Result types: ResultEnvelope, BuildStats, DroppedItem, ContextPack, ChoiceCard, HydrationResult, RoutingDecision
diagnostics.py Versioned, payload-safe gateway events and sinks (DiagnosticEvent, DiagnosticSink, JSONL/in-memory sinks) plus deterministic aggregate reports (issues #370/#378).
inspection.py Pure JSON/Markdown report construction for offline context, routing, and artifact inspection without raw payload content (issue #398).
telemetry_contract.py Versioned JSONL telemetry handoff contract over DiagnosticEvent for downstream analytics (issue #382): EVENT_FAMILIES (8 families → event-name prefixes; shortlist/policy_denial/visibility reserved until their emitters land), classify_event, validate_event_dict (envelope shape + payload-leak heuristic), export_jsonl/read_jsonl (skip-and-collect). Hand-written envelope schema under schemas/telemetry/v1/; contract doc docs/telemetry.md.
ops_view.py Read-only gateway ops-triage view over the diagnostics JSONL (issue #668): windowed OpsSnapshot (family counts, error rate, browse/execute latency percentiles, top executed/failing tools), plain-text + Rich renders, incremental file-tailing watch_loop. Backs mcp ops.
visualize.py Self-contained HTML reports for RouteTrace / BuildStats / diagnostic-event timelines (issue #442): inline CSS only, all dynamic (untrusted) text HTML-escaped, byte-identical output for identical inputs. Backs the visualize CLI command.
config.py Configuration: ContextBudget, ContextPolicy (incl. overflow_action budget-overflow policy, issue #510), and ScoringConfig
profiles.py Routing and profile config: Mode, RoutingConfig, ProfileConfig, named presets
protocols.py Protocol interfaces: TokenEstimator, EventHook, Summarizer, Extractor, RedactionHook, SensitivityClassifier (ingestion-time labelling, issue #542), MemorySource, Labeler, Retriever, Reranker, ClusteringEngine, RoutingScoreProvider (store protocols re-exported from store/protocols.py). Bundled estimators: HeuristicEstimator (default, script-aware, dependency-free — counts CJK/Kana/Hangul/emoji ≈1 token/char, issue #525), CharDivFourEstimator (raw len // 4 primitive), TiktokenEstimator (exact, falls back to HeuristicEstimator offline). Each carries a stable name for BuildStats.token_estimator.
store/protocols.py Store-layer protocols: EventLog, ArtifactStore, EpisodicStore, FactStore
store/async_protocols.py Async counterparts AsyncEventLog / AsyncArtifactStore / AsyncEpisodicStore / AsyncFactStore (issue #495) — same surface, async def. Consumed only by the async context/ path; backend-agnostic.
store/async_bridge.py to_async(sync_store) — wraps a thread-safe sync backend as the matching async protocol via asyncio.to_thread. Thread-affine backends (SqliteEventLog, check_same_thread=True) are not valid targets (issue #495).
store/_async_to_sync.py Inverse bridges + to_sync(async_store, loop) + is_async_store() (issue #495). Drives async stores on a private _LoopThread so the existing sync pipeline can consume them; ContextManager offloads build to a worker thread when async-backed. Not public API.
store/_loop_thread.py The private _LoopThread (asyncio loop on a daemon thread) backing _async_to_sync (kept separate to isolate loop lifecycle and timeout handling). run(coro, timeout=…) bounds each op and raises StoreTimeoutError instead of hanging a stuck backend (issue #750). Not public API.
exceptions.py Custom exception hierarchy (all errors inherit ContextWeaverError). Each class carries a stable, frozen code (e.g. CW_CONFIG) plus an optional hint; str(exc) renders [code] message (hint: …). Codes are documented in docs/errors.md and golden-listed in tests/test_exceptions.py (issues #635, #637).
_utils.py Text similarity primitives: tokenize(), jaccard(), TfIdfScorer
secrets.py Pure, deterministic secret detection/scrubbing primitives: scrub_secrets(), scrub_secrets_in_list(), contains_secret(), SecretPattern (issue #428). Shared by the firewall secret-scrub, the SecretRedactor hook, the sensitivity classifier, and ChoiceCard scrubbing. No I/O; never weakens a surface (only removes characters).
_version.py Single-source version derived from importlib.metadata; fallback "0.0.0+local"
_incident_pack.py Offline incident-pack builder for contextweaver mcp incident-pack (issue #661): creates bounded redacted zip bundles with a machine-readable manifest, summaries, redacted config/catalog/diagnostics excerpts, and reproduction checklist. Private; no public API.
_incident_pack_files.py Private archive-entry helpers for incident packs: key-aware structured redaction, per-file truncation, hashes/timestamps for manifest entries, and best-effort JSON/YAML/JSONL parsing. Not public API.
_vscode_import.py Pure transform for contextweaver mcp import-vscode (issue #367): build_migration_plan converts a VS Code-family MCP config's servers/mcpServers block into an upstreams: gateway config; render_gateway_config/render_replacement_config render the two output configs (kept separate from the plan since the replacement config embeds a write-time --gateway-config path decision); write_migration applies with a default backup. Not public API.
_demos.py Demo logic for the CLI demo subcommand (exempt from print() rule)
serde.py Serialisation helpers for to_dict / from_dict
tokens.py Built-in token counter (count(), get_token_counter(), heuristic_counter(), TokenCounter alias) plus the provider-estimator registry (register_estimator(), registered_estimators(), estimator_name(), issue #493). The single source of truth for token counts — firewall, sensitivity-redaction placeholders, card budgeting (routing/cards.count_tokens), and FirewallStats/BuildStats numbers all route through it (issues #405/#493/#530); no stray len // 4 literals elsewhere. Owns the tiktoken dependency; offline it falls back to the script-aware HeuristicEstimator.
store/ In-memory data stores: EventLog, ArtifactStore, EpisodicStore, FactStore, StoreBundle
store/_sqlite_base.py Shared SQLite connection + migration scaffolding (WAL, foreign_keys=ON, _contextweaver_schema_version table). Reused by every SQLite-backed store (issue #174).
store/sqlite_event_log.py SqliteEventLog — first persistent EventLog backend; single-process, sync, append-only, schema-versioned (issue #223).
store/sqlite_episodic.py SqliteEpisodicStore — persistent EpisodicStore on _sqlite_base (issue #496). Append-only, ordered by ordinal; search delegates to a transient InMemoryEpisodicStore for byte-identical ranking. Own version table (VERSION_TABLE) so it can share a DB file with the event log / facts.
store/sqlite_facts.py SqliteFactStore — persistent FactStore on _sqlite_base (issue #496). put upserts on fact_id; get_by_key/all sorted by fact_id. Own version table; shareable DB file.
store/redis_artifacts.py RedisArtifactStore — Redis ArtifactStore for multi-process gateways (issue #426). Namespaced keys, optional per-artifact TTL, list_refs via SCAN. Lazy redis import ([redis] extra).
store/redis_event_log.py RedisEventLog — Redis EventLog (issue #426). Items in a hash keyed by id + parallel order list; append-only ordering across processes. Lazy redis import ([redis] extra).
store/s3_artifacts.py S3ArtifactStore — S3-compatible ArtifactStore (issue #426; AWS/MinIO/R2/GCS). {prefix}/{handle}.data + .json objects. Lazy boto3 import ([s3] extra).
store/json_file_artifacts.py JsonFileArtifactStore — filesystem ArtifactStore backend; {enc(handle)}.data + {enc(handle)}.json per artifact, re-instantiable against an existing directory (issue #42). Hardened (issue #497): atomic writes (temp file + os.replace), an in-memory handle→ref index built once on init so list_refs never rescans the directory, and optional max_bytes / max_artifacts quotas raising ArtifactStoreQuotaError. Persists content_hash and percent-encodes handles into filenames so the firewall's artifact:result:… handles are Windows-safe (issue #466). Optional ttl_seconds / redact_secrets lifecycle policy (issue #375) delegates to store/_json_file_ttl.py's ArtifactLifecycle.
store/_json_file_ttl.py Private TTL + redaction-before-store bookkeeping for json_file_artifacts.py (issue #375): ArtifactLifecycle (composed, not inherited) — prepare() scrubs UTF-8 content via contextweaver.secrets.scrub_secrets before write, record_put()/is_expired()/forget() manage a process-lifetime-scoped expiry dict under an injectable monotonic Clock (mirrors gateway_controls.ToolResultCache's clock convention). Not persisted across a restart. Not public API.
store/_json_file_io.py Private filesystem helpers for json_file_artifacts.py (keeps filesystem concerns isolated from store policy): on-disk suffix constants, validate_handle (path-traversal defense), encode_handle (percent-encoding), and the atomic_write primitive (issues #466/#497). Not public API.
store/testing.py Store-protocol conformance kit (issue #520): framework-agnostic check_event_log_conformance / check_artifact_store_conformance / check_episodic_store_conformance / check_fact_store_conformance, each taking a factory for an empty backend and asserting the round-trip / ordering / not-found contract. No test-framework import; ships in the core wheel. tests/test_store_conformance.py runs every bundled backend through it.
summarize/ SummarizationRule, RuleEngine, extract_facts()
summarize/structured.py Lossless JSON field projection for the firewall: parse_path / project + StructuredFirewall(keep=[...]). Deterministic, no LLM — keeps an allow-list of JSON paths inline and offloads the rest (issue #406).
context/ Full context pipeline, sensitivity enforcement, view registry, ContextManager
context/firewall_api.py Single-call firewall facade: compact_tool_result / firewalled_tool_resultCompactResult. Composes structured/text strategies, schema-preserving pass-through (reserved _cw sidecar — a caller payload already using _cw raises ConfigError unless overwrite_sidecar=True, #467), the built-in token counter, and fail-closed deterministic mode (issues #399, #402, #403, #404, #405, #406, #467).
context/manager.py ContextManager — thin orchestrator (__init__, properties, drilldown, mixin composition). Public method stubs live in flat partial-class mixins; pipeline logic lives in the delegate modules below (issue #101).
context/_manager_base.py _ManagerState — private-attribute + _build contract the manager mixins inherit and the delegate pipeline modules type their manager parameter against (ContextManager inherits it via the mixins). Not public API (issue #101).
context/_manager_ingest.py / _manager_build.py / _manager_routing.py Private partial-class mixins that preserve ContextManager's public ingestion, build, and route/call-prompt API while delegating implementation to focused modules. Their composition is private implementation detail; the public behavior/API is the contract.
context/ingest.py Tool-result ingestion helpers kept separate from the public manager façade to isolate ingestion concerns. Includes ingest_envelope — the canonical Frame-shaped seam (weaver-spec I-05) that ingests an already-firewalled ResultEnvelope without re-deriving firewalling; raw-output ingest_tool_result / ingest_mcp_result are non-canonical for spec compliance (issue #352).
context/memory_types.py MemoryEntry dataclass + PHASE_SCOPE_PREFERENCES constants for phase-aware memory ingestion (issue #293).
context/memory_fixture.py JsonFixtureMemorySource — deterministic stdlib fixture adapter implementing the MemorySource Protocol from protocols.py (issue #293).
context/memory_source.py memory_entries_to_context_items / select_memory_for_phase helpers that materialise memory entries into budgeted memory_fact candidates (issue #293).
context/handoff_types.py HandoffEntry + SessionHandoffPack dataclasses and canonical handoff category constants (issue #294).
context/handoff.py build_session_handoff_pack / render_handoff_pack — deterministic, budget-aware, sensitivity- and firewall-respecting session continuity snapshot (issue #294).
context/advisor_pack.py Advice-only planning escalation (issue #741): AdvisorRequest / AdvisorResponse + ask_advisor package a bounded, budget-truncated, strict-JSON prompt to a stronger model via call_fn (optionally GuardedCallFn-wrapped). Off-list preferred options are nulled with a deterministic marker; malformed output degrades to raw-text advice. Advice never executes or authorizes anything.
context/consolidation_types.py ConsolidationPolicy / EpisodeCluster / PromotedFact / ConsolidationReport (+ CONSOLIDATION_REPORT_VERSION) — pure-data config and result types for the memory consolidation engine (issue #498).
context/consolidation.py Memory consolidation engine (issue #498): cluster_episodes (deterministic episodic clustering/dedupe, #679), promote_clusters (fact promotion with provenance + max-sensitivity inheritance, #680; optional fail-closed call_fn merge, #682), decay_episodes / decay_facts (report-only decay over append-only stores, #681), and the consolidate(...) orchestrator → ConsolidationReport. Deterministic; apply=True upserts content-addressed facts (idempotent). Standalone functions (not a ContextManager method) mirroring handoff.py.
context/_consolidation_merge.py Private optional model-assisted canonicalizer for consolidation (issue #682): refine_canonical_text runs a user-supplied call_fn under fail-closed guardrails (no LLM SDK dep; rejects blank/ungrounded completions that introduce tokens absent from the source cluster, falling back to the deterministic text). Not public API.
context/explanation.py ContextBuildExplanation + CandidateExplanation opt-in debug surface returned by ContextManager.build(..., explain=True) (issue #291); carries resolved_weights (the per-phase scoring weights applied, issue #487). Sister to routing/explanation.py on the routing side.
context/build_policy.py Pure build-pipeline policy helpers (not public API): override_phase_budget / adjust_budget_for_header (budget math), enforce_overflow_policy (ContextPolicy.overflow_action, issue #510), and render_pack_prompt (caller-owned renderer hook, issue #410). Extracted from build.py to keep it within its size ceiling.
context/classify.py Opt-in deterministic ingestion-time sensitivity classification (issue #542): HeuristicSensitivityClassifier (implements the SensitivityClassifier protocol) + detect_sensitivity(). Runs at the start of the pipeline's sensitivity stage and over fact/episode header content; may only raise a label, never lower it. Reuses secrets.contains_secret plus PII markers.
context/secret_redaction.py Opt-in SecretRedactor RedactionHook (issue #428): substring-scrubs secret shapes from an item's text via secrets.scrub_secrets. Registered under the name "secret" for ContextPolicy.redaction_hooks; complements (does not replace) MaskRedactionHook.
routing/ Catalog, ChoiceGraph, TreeBuilder, Router (beam search), card renderer
routing/filters.py Pre-scoring helpers: filter_items(), augment_query(), suggest_clarifying_question() (issues #14, #22, #112, #116)
routing/catalog_metadata.py Catalog inventory/governance metadata (issue #377): InventoryMetadata (owner/domain/risk/side-effects/lifecycle/environment/tier, all default None = unknown) under the reserved metadata["_contextweaver"]["inventory"] namespace via attach_inventory / inventory_of / validate_inventory / is_deprecated. Round-trips through SelectableItem serde untouched.
routing/collision.py Collision & duplicate-capability analyzer (issue #381): analyze_collisionsCollisionReport (exact/near-name, description- and schema-similar findings + recommendation heuristic + render_markdown). Similarity via _utils + stdlib difflib; small schemas skipped for false-positive suppression.
routing/catalog_diff.py Catalog diff + routing impact (issue #514): diff_catalogs (added/removed/field-level changes anchored by compute_catalog_hash), routing_impact (top-1 flips + recall@k over probe queries), suggest_probes heuristic probe generator. Backs catalog diff.
routing/vector_index.py Embedding index over tool catalogs (issue #387): canonical_tool_text + VectorIndex (build / hash-based incremental refresh / query with per-section evidence / cosine duplicates). Backend-agnostic over EmbeddingBackend; deterministic with HashingEmbeddingBackend; plain-list vectors.
routing/export.py Provider-native tool exporters for routed shortlists (issue #609): to_openai_tools / to_anthropic_tools / to_gemini_function_declarationsExportedTools (wire-ready tools + deterministic sanitised-name→tool_id map with collision handling). Hydrates empty inline schemas via Catalog.hydrate (inline wins).
routing/manifest.py GraphManifest + compute_catalog_hash() for graph metadata and cache invalidation (issue #48, #15)
routing/normalizer.py CatalogNormalizer + NormalizationReport for catalog metadata hygiene (issue #44)
routing/catalog.py (validation) validate_references / Catalog.validate_referencesCatalogValidationReport of dangling depends_on/requires refs; loaders take on_invalid ("warn"/"raise"/"ignore") and raise CatalogValidationError in raise mode (issue #519)
routing/registry.py EngineRegistry and bundled TfIdfRetriever / NoOpReranker / JaccardClusteringEngine defaults (issue #47)
routing/index_cache.py Persistent, reusable fitted-index cache (issues #543/#624/#685): RoutingIndexCache (in-process LRU + optional deterministic-JSON on-disk layer) and CachedRetriever (a Retriever wrapper that loads/stores the fitted index keyed by a corpus fingerprint, transparently — warm loads score byte-identically to a cold fit). Pass via Router(retriever=CachedRetriever(TfIdfRetriever(), cache)). Codec + fingerprint live in routing/_index_codec.py.
routing/_index_codec.py Private helper for index_cache.py: index_fingerprint() (deterministic ordered-corpus SHA-256) + the IndexCodec contract and bundled TFIDF_CODEC. Not public API; names re-exported from index_cache.
routing/trace.py RouteTrace + TraceStep structured routing audit (issue #51)
routing/explanation.py RouteResult.explanation() Markdown / dict rendering (issue #226)
routing/pipeline.py RoutingPipeline composer — explicit retrieve → rerank → navigate → pack stages (issue #56)
routing/navigator.py BeamSearchNavigator (lifted from router.py) + rank_collected — the score-sort/active-filter helper is re-exported from routing/__init__.py for custom Navigator implementations (issues #56, #288)
routing/packer.py DefaultCardPacker wrapping make_choice_cards for the pipeline pack stage (issue #56)
routing/history.py RouteHistory dataclass + adjust_scores (history-aware re-routing, issue #27)
routing/feedback.py Optional feedback-aware routing scores (issue #318): ExecutionFeedback (contextweaver-native, not a weaver-spec type), DeterministicScoreProvider (default no-op), FeedbackAwareScoreProvider, aggregate_feedback. Plugs into Router(score_provider=...); default None keeps routing deterministic.
routing/selection.py Structured route→select contract (issues #515/#479), both pure/deterministic: selection_schema emits the routed candidate IDs as a provider-native constrained-selection schema (json_schema/openai/anthropic) so a model can only pick a routed tool_id ("constrain before"); validate_selectionSelectionValidation validates/repairs (strip → case-fold → unique-prefix; ambiguous matches rejected, never guessed) a returned ID against the candidates ("validate after"). Surfaced on RouteResult.selection_schema() / RouteResult.validate_selection(); to_routing_decision resolves + records the outcome. Shortlist composition (pin_ids always-include + per-namespace namespace_quota, issue #509) lives in routing/filters.compose_shortlist and is exposed via Router.route(...).
extras/embeddings.py SentenceTransformerBackend + HybridEmbeddingRetriever + HashingEmbeddingBackend (re-exported) behind the [embeddings] extra (issue #8)
extras/embeddings_hashing.py HashingEmbeddingBackend — stdlib-only deterministic EmbeddingBackend using blake2b hashing trick; no extras required (issue #266)
_schema_gen.py Dataclass → JSON Schema (Draft 2020-12) generator + make schemas-check engine (issue #225)
routing/tool_id.py Canonical tool_id grammar (parse_tool_id / format_tool_id / compute_hash8) per docs/gateway_spec.md §1
routing/primitive_id.py Unified cross-primitive identity + collision policy for tools/resources/prompts (parse_primitive_id / format_primitive_id / canonical_resource_id / canonical_prompt_id / resolve_collisions) per docs/gateway_spec.md §9. Tools keep the bare tool_id; resources/prompts get disjoint kind:: ids (issue #671).
routing/path.py tool_browse path-navigation grammar (parse_path / resolve_path) per docs/gateway_spec.md §3
routing/hydration.py Public schema-hydration helpers — SchemaSource (from raw dict / JSON file / MCP tools-list), hydrate_with_schema, lazy_schema_resolver. Reference architectures use these to resolve a tool's full input schema from a sidecar source rather than hand-rolling a _FULL_SCHEMAS dict. Inline args_schema on the catalog item wins; sidecar only fills empties. Issue #261.
adapters/ MCP, FastMCP, A2A, weaver-spec, CrewAI, Pydantic AI, smolagents, Agno, LangChain, OpenAI Agents SDK, Google ADK, Microsoft Agent Framework, OpenAPI, Agent Skills protocol adapters + MCP proxy / gateway runtime + provider-message ingestion helpers for OpenAI / Anthropic / Gemini chat histories. Framework tool-catalog adapters share adapters/_framework_common.py (issue #454). (issues #13, #28, #29, #34, #193, #194, #219, #222, #272, #274, #275, #430, #454, #501, #502, #545, #546, #547)
adapters/chainweaver.py ChainWeaver flow-export → SelectableItem(kind="flow") import (chainweaver_flow_to_selectable, chainweaver_flows_to_catalog, load_chainweaver_export, issue #334). Pure data; no ChainWeaver dependency. Preserves name/description/input+output schemas; stamps metadata["runtime"]="chainweaver" + flow id/version.
adapters/crewai.py CrewAI BaseTool (or equivalent plain-dict shape) ↔ SelectableItem (crewai_tool_to_selectable, crewai_tools_to_catalog, infer_crewai_namespace, load_crewai_catalog, issue #193)
adapters/pydantic_ai.py Pydantic AI ToolSelectableItem and ModelMessageContextItem lossless round-trip (pydantic_ai_tool_to_selectable, pydantic_ai_tools_to_catalog, load_pydantic_ai_catalog, from_/to_pydantic_ai_messages, issue #272) — heavy decode/encode helpers live in adapters/_pydantic_ai_messages.py
adapters/smolagents.py Hugging Face smolagents ToolSelectableItem and MultiStepAgent.memory.stepsContextItems (smolagents_tool_to_selectable, smolagents_tools_to_catalog, load_smolagents_catalog, from_smolagents_agent, issue #274)
adapters/agno.py Agno (formerly Phidata) Function / ToolkitSelectableItem and AgentSessionContextItems (agno_tool_to_selectable, agno_tools_to_catalog, load_agno_catalog, from_agno_session, issue #275)
adapters/_framework_common.py Shared, framework-agnostic conversion scaffolding for the framework tool-catalog adapters (issue #454): infer_namespace, strip_namespace_prefix, coerce_schema_dict, collect_tags, require_name_description. Pure/stateless, imports no framework lib. Private — not exported. New adapters reuse these instead of re-implementing namespace/schema/tag mechanics.
adapters/langchain.py LangChain BaseTool (or equivalent plain-dict shape) ↔ SelectableItem (langchain_tool_to_selectable, langchain_tools_to_catalog, infer_langchain_namespace, load_langchain_catalog, issue #502). [langchain] extra for live loading; plain-dict path needs no extra.
adapters/openai_agents.py OpenAI Agents SDK FunctionToolSelectableItem and run items → ContextItems (openai_agents_tool_to_selectable, openai_agents_tools_to_catalog, load_openai_agents_catalog, from_openai_agents_run, issue #501). Run-item ingestion lives in adapters/_openai_agents_run.py. [openai-agents] extra for live loading.
adapters/google_adk.py Google ADK tools ↔ SelectableItem and Session.eventsContextItems (google_adk_tool_to_selectable, google_adk_tools_to_catalog, load_google_adk_catalog, from_google_adk_session, issue #547). Session ingestion lives in adapters/_google_adk_session.py. [google-adk] extra for live loading.
adapters/agent_framework.py Microsoft Agent Framework (AutoGen / Semantic Kernel lineage) tools ↔ SelectableItem and thread ChatMessages → ContextItems (agent_framework_tool_to_selectable, agent_framework_tools_to_catalog, load_agent_framework_catalog, from_agent_framework_thread, issue #430). Thread ingestion lives in adapters/_agent_framework_thread.py. [agent-framework] extra for live loading.
adapters/openapi.py OpenAPI 3.0/3.1 operations → SelectableItem catalog (openapi_operation_to_selectable, openapi_spec_to_catalog, load_openapi_catalog, infer_openapi_namespace, issue #546). Routes over REST APIs; never calls them. Local $ref resolution + parameters/requestBodyargs_schema composition + method→safety tags live in adapters/_openapi_schema.py. No extra — PyYAML/jsonschema are core.
adapters/agent_skills.py Agent Skills (SKILL.md) directories → kind="skill" SelectableItems with lazy body hydration (skill_to_selectable, load_skills_catalog, parse_skill_frontmatter, SkillBodySource, issue #545). Frontmatter routes; SkillBodySource resolves the body/resources on selection (mirrors routing/hydration.SchemaSource). No extra — PyYAML is core.
adapters/_okf_io.py / _okf_materialize.py / _okf_coerce.py Private OKF-style Markdown-plus-YAML-frontmatter parsing core shared by the four knowledge-source adapters below (issues #736/#763/#767/#776): permissive frontmatter parsing (never raises — degrades to a LoadDiagnostic), the KnowledgeNode dataclass, deterministic directory walk, and materialisation into ContextItem (kind=doc_snippet, provenance under the _contextweaver metadata namespace) + deterministic relevance scoring. _okf_coerce.py holds the pure frontmatter value-coercion helpers (scalar/float/expiry coercion + JSON-safe normalisation of dates/bytes, so the to_dict/ContextItem.metadata "JSON-compatible" contract holds), split out to isolate frontmatter coercion from parsing and materialisation. Not public API; not re-exported at the adapters package level (mirrors mcp_primitives/gateway_primitives — a related family kept at submodule level to stay within adapters/__init__.py's frozen size ceiling).
adapters/okf.py OKF bundle loader as a context source (issue #736): load_okf_bundle, okf_nodes_to_context_items, select_knowledge. index.md/log.md are bundle metadata/history, excluded from concept content by default.
adapters/repo_knowledge.py Repository-knowledge bundles as context sources (issue #763): load_repo_knowledge (plain-Markdown fallback, max_files/max_total_bytes guardrails, links never auto-followed), classify_usage (deterministic usage tags — plain metadata strings, not Phase values; extending Phase is issue #587's separate concern), select_repo_knowledge.
adapters/lessons.py LessonWeaver lesson bundles as lifecycle-aware context sources (issue #767): load_lesson_bundle, LessonSelectionPolicy (excludes rejected/deprecated/unreviewed-candidate lessons by default), eligible_lessons, select_lessons — every exclusion is reported with a reason, never silent.
adapters/expertise_pack.py ExpertisePacks as bounded context sources (issue #776): load_expertise_pack validates pack structure (an index.md declaring version, every node carrying a key) — the canonical schema is tracked externally at dgenio/weaver-spec#184 and not yet bound. detect_conflicts is deterministic-only (literal same-key text disagreement, scoped by task_tags/expiry) — no LLM-backed contradiction inference.
adapters/proxy_runtime.py ProxyRuntime shared core + ExposureMode enum + UpstreamCall Protocol (issue #29)
adapters/gateway_diagnostics.py / gateway_catalog_diagnostics.py Sanitized ProxyRuntime instrumentation plus exact gateway/proxy static-schema exposure calculations: catalog, browse/hydrate/execute/view events, savings, artifact-view usage, and latency (issues #370/#378).
adapters/mcp_gateway.py Two-tool gateway dispatch (tool_browse + tool_execute + tool_view, issues #28 / #34)
adapters/mcp_proxy.py Transparent proxy dispatch (stripped tools/list + tool_hydrate + tool_execute, issue #13)
adapters/mcp_upstream.py Concrete UpstreamCall adapters (StubUpstream, McpClientUpstream, MultiplexUpstream)
adapters/_config_coerce.py Private config-value coercion helpers (interpolate_env for ${env:VAR}, coerce_bool, opt_positive_number, str_tuple, str_map) shared by upstream_config.py / startup_policy.py / artifact_policy.py (issue #366). Not public API.
adapters/upstream_config.py Pure-data config for one live upstream MCP server (issues #366/#368): UpstreamSpec (type: stdio|http|sse, command/args/env or url/headers, namespace, required, include_tools/exclude_tools globs, timeout), parse_upstreams_config.
adapters/startup_policy.py Fault-tolerant multi-upstream startup policy (issue #374): StartupPolicy (mode: degraded|strict, upstream_timeout_seconds, min_healthy_upstreams, fail_on_empty_catalog), UpstreamStatus, StartupReport, detect_tool_name_collisions (diagnostic only — routing still resolves collisions first-registered-wins via MultiplexUpstream).
adapters/artifact_policy.py Artifact lifecycle policy for mcp serve --state-dir (issue #375): ArtifactPolicy (ttl_seconds, max_bytes, max_artifacts, redact_secrets), wired into JsonFileArtifactStore.
adapters/upstream_launch.py Live multi-upstream launch behaviour (issues #366/#368/#374): launch_upstreams connects every configured UpstreamSpec under AsyncExitStack, classifies failures via gateway_error.classify_upstream_exception, and composes survivors behind MultiplexUpstream; NamespacedFilteredUpstream applies namespace-prefixing + include/exclude filtering at the list_tools boundary. Connect-step timeouts bound only session.initialize() (a self-contained RPC) — never the stdio_client/ClientSession context-manager entry itself, since wrapping that in asyncio.wait_for schedules a new Task and violates anyio's same-task cancel-scope invariant when AsyncExitStack closes it later from the caller's task.
adapters/mcp_gateway_server.py Bind mcp_gateway onto mcp.server.Server over stdio (issue #28); optional primitive_runtime= also advertises/dispatches the four resource/prompt meta-tools (issues #669/#670)
adapters/mcp_primitives.py MCP resource/prompt → SelectableItem(kind="resource"/"prompt") converters + resources/read / prompts/get result→envelope wrappers (issues #669/#670). Emits ids via routing/primitive_id.
adapters/gateway_primitives.py PrimitiveGatewayRuntime + PrimitiveUpstream Protocol — bounded-choice routing + firewall for resources/prompts, sharing the tool runtime's ContextManager (issues #669/#670/#555).
adapters/_primitive_index.py Private single-kind catalog+graph+router+browse helper for gateway_primitives (isolates catalog/graph/router/browse mechanics from adapter wrappers). Not public API.
adapters/mcp_gateway_primitives.py The four resource/prompt gateway meta-tools (resource_browse / resource_read / prompt_browse / prompt_get) + dispatch, mirroring mcp_gateway (issues #669/#670).
adapters/mcp_primitive_upstream.py Concrete PrimitiveUpstream adapters mirroring mcp_upstream: StubPrimitiveUpstream (in-process), McpClientPrimitiveUpstream (wraps an MCP ClientSession), MultiplexPrimitiveUpstream (multi-server fan-out). Transport errors raise (the runtime classifies them) per the Protocol contract (issues #669/#670).
adapters/mcp_proxy_server.py Bind mcp_proxy onto mcp.server.Server over stdio (issue #13)
adapters/sidecar_contract.py HTTP sidecar wire contract (issue #674): RouteRequest/RouteResponse/CompactRequest/CompactResponse/SidecarError dataclasses + SIDECAR_API_VERSION. Pure, dependency-free; the published JSON Schemas live under schemas/sidecar/v1/.
adapters/sidecar.py HTTP sidecar runtime (issue #675/#676): SidecarConfig + SidecarApp.dispatch — transport-free (method, path, headers, body) → (status, json) over the sync Router (/v1/route) and compact_tool_result facade (/v1/compact). Optional bearer-token auth, per-client rate limiting (reuses gateway_controls.RateLimiter), body-size cap, and typed SidecarError responses; never raises across the HTTP boundary.
adapters/_sidecar_http.py Stdlib http.server.ThreadingHTTPServer binding for SidecarApp (issue #675). No third-party dependency. Public re-exports: serve_api (blocking serve) + make_sidecar_server (build-only, for tests). Not public API itself.
adapters/_sidecar_validation.py Stateless parsing + field-validation helpers shared by sidecar.py and sidecar_contract.py (request-body JSON decode, bearer-token extraction, typed contract-field coercions). Pure, dependency-free; raises ConfigError on malformed input. Not public API.
adapters/gateway_error.py Structured GatewayError (codes + §3.4 wire shape) + retryable hint. Upstream-error taxonomy: classify_upstream_exception maps timeouts/connection/auth/permission/rate failures to UPSTREAM_TIMEOUT/UPSTREAM_UNAVAILABLE/AUTH_FAILED/PERMISSION_DENIED/RATE_LIMITED (fallback UPSTREAM_ERROR); redact_upstream_detail strips control chars + caps length on model-visible detail (issue #485).
adapters/gateway_validation.py Untrusted-schema hardening for the gateway ingest path (issues #464/#484): SchemaLimits/SchemaFinding/SkippedTool/CatalogRefreshReport, check_schema_health (meta-validation + iterative size/depth/property bounds), build_validator (cached per tool_id). Pure, deterministic; iterative traversal avoids stack exhaustion on hostile schemas.
adapters/gateway_args.py Opt-in deterministic tool-call argument repair (issue #488): normalize_args (stringified-object parse + schema-demanded str→int/number/boolean/null coercion) + Repair. Gated behind ProxyRuntime(tolerant_args=True); never renames keys, drops keys, or fuzzy-matches.
adapters/gateway_policy.py Pure-data config + result types for the dispatch-path controls (issues #529/#482/#483): RetryPolicy (bounded backoff), RateLimit/RateLimitPolicy (per-session quotas), DryRunReport. All defaults inert; to_dict/from_dict for mcp serve --config.
adapters/gateway_controls.py Runtime mechanisms behind gateway_policy (issues #529/#482/#512): call_with_retry (retry loop, injectable sleep), RateLimiter (sliding-window + cumulative counters, injectable clock), ToolResultCache (TTL+LRU read-only response cache). All opt-in; wired into ProxyRuntime.execute/browse/view.
adapters/gateway_authz.py Runtime authorization / policy gate (issue #373): ToolPolicy (ordered PolicyRules + default), PolicyContext, PolicyDecision, policy_gate_error. Pure/deterministic (first-match, case-sensitive globs). Evaluated before tool_execute dispatch and — via meta_tool="tool_view" rules — before tool_view raw egress (issue #746). Default allow (inert); denyPOLICY_DENIED, require_approvalAUTH_REQUIRED. to_dict/from_dict for the policy block of mcp serve --config.
adapters/gateway_visibility.py Audience-scoped catalog visibility profiles (issue #379): VisibilityProfile (glob include/exclude over namespaces/domains, risk/lifecycle exclusion, side-effect + environment allowlists), evaluate_visibility/filter_catalog (denials carry reasons), parse_profiles for a visibility_profiles: config block. Mirrors gateway_authz's first-match pattern; exclude rules fail open on unknown inventory metadata, allowlists fail closed. Applied at serve startup before ChoiceCards.
adapters/catalog_pin.py Catalog pinning against tool-surface drift (issue #656): PinPolicy (expected_hash, mode: warn|strict), check_catalog_pin via routing.manifest.compute_catalog_hash, enforce_pin (strict-mode mismatch raises with both hashes + re-pin hint). pin: block of mcp serve --config.
adapters/live_refresh.py Notification-driven live catalog refresh (issue #424): LiveRefreshPolicy + LiveRefresher turn upstream tools/list_changed into ProxyRuntime's atomic register_tool_defs_sync — debounced, sliding-minute rate-limited, inert by default; make_message_handler wires it to the ClientSession message handler threaded through launch_upstreams.
adapters/serve_lifecycle.py Graceful shutdown for the serve loops (issue #626): ShutdownController — SIGINT/SIGTERM capture (graceful where loops lack signal support), drain-then-cancel of in-flight work, defensive flush/close of stores and sinks with per-object error collection → ShutdownReport. Transport-agnostic.
adapters/memory_server.py Standalone MCP memory server (issue #632): build_memory_server / run_memory_server_stdio expose episodic/fact stores as four MCP tools (memory_add_episode/search_episodes/put_fact/get_facts) with deterministic content-hash ids, the gateway ARGS_INVALID error shape, and opt-in read-path secret scrubbing via the shared contextweaver.secrets helpers. Backs mcp memory-serve.
adapters/gateway_scorecard.py Tool-surface health scorecard (issue #380): build_scorecard joins inventory metadata (#377) with diagnostic-event streams (#382) into a deterministic report (usage/latency/failure hot-spots, unused/deprecated-in-use, collision counts via #381) + Markdown/CSV/JSON renders. Backs mcp scorecard.
adapters/gateway_status.py Gateway status surface for mcp status (issue #655): GatewayStatus snapshot + rate-limited atomic StatusWriter (injectable clock, coalescing, force()), read_status (ConfigError with --state-dir hint), render_status (uptime + 30s staleness warning).
adapters/gateway_doctor.py / _doctor_checks.py Gateway preflight for mcp doctor (issue #395): run_doctorDoctorReport of never-raising DoctorFindings — config/key-set/XOR checks, catalog load + references + weak-metadata, ChoiceCard schema-hiding probe, hydration, artifact-store writability, optional-extras info, opt-in live upstream launch + routing smoke queries. Check bodies live in the private _doctor_checks.py (size split).
adapters/sampling_call_fn.py MCP sampling-backed call_fn (issue #623): make_sampling_call_fn / make_async_sampling_call_fn bridge the firewall's Summarizer seam to the connected client's model via sampling/createMessage. Sync variant runs on a worker thread through the server loop with a deadlock guard + timeout; non-text results raise so consumers fall back to the deterministic path. Opt-in only.
adapters/wire_capture.py Record/replay harness pinning gateway protocol behaviour with committed golden transcripts (issue #654): WireRecorder / save_transcript / load_transcript / replay_and_verify at the dispatch boundary (JSON-RPC framing is SDK-owned; content bodies JSON-decoded for field-level diffs, volatile paths normalised).
adapters/gateway_presets.py Named gateway policy presets (issue #664): GatewayPreset.from_preset("safe"|"balanced"|"throughput") bundles a ToolPolicy + RetryPolicy + RateLimitPolicy + CacheConfig (also defined here — pure-data config for gateway_controls.ToolResultCache). Selectable via mcp serve --policy-preset / policy_preset config key; an explicit policy/retry/rate_limits/cache block wins over the preset for that block. Deterministic to_dict() backs mcp serve --print-effective-policy.
adapters/_proxy_dispatch.py Private dispatch helpers keeping proxy_runtime.py within its size ceiling: persist_result_artifacts, execute_policy_error/view_policy_error (policy-context construction + gate call), rate_limited_error, unverified_annotations, build_dry_run_report, UpstreamNameIndex. Not public API.
adapters/openai_messages.py OpenAI Chat Completions messagesContextItem round-trip (from_/to_openai_messages, issue #219)
adapters/anthropic_messages.py Anthropic Messages API messagesContextItem round-trip (from_/to_anthropic_messages, issue #222)
adapters/gemini_contents.py Google Gemini contents[]ContextItem round-trip (from_/to_gemini_contents, issue #222)
extras/otel.py OpenTelemetry GenAI integration (OTelEventHookinvoke_agent / execute_tool spans + GenAI SemConv attributes, gated behind the [otel] extra, issue #224).
extras/llm_summarizer.py Optional LlmSummarizer / LlmExtractor — LLM-backed Summarizer / Extractor plugins for the firewall. Take a user-supplied call_fn (no LLM SDK dep, no extra) and degrade to the rule-based path on any failure (issue #26). Optional provider_metadata surfaces on FirewallStats.llm_provider for audit; truncated inputs carry a deterministic omission marker (issue #384).
extras/llm_guard.py GuardedCallFn — policy envelope for user-supplied LLM call_fn callables (issue #494): GuardPolicy (call cap, consecutive-failure circuit breaker with cooldown/half-open trial, timeout accounting — post-hoc by default, opt-in thread-enforced hard timeout) + live GuardStats. Injectable monotonic clock. Rejections raise PolicyViolationError so plugins degrade to their deterministic fallbacks. No LLM SDK dep.
extras/catalog_enrich.py Offline LLM-assisted catalog metadata enrichment (issue #383): enrich_catalog emits reviewable EnrichmentSuggestions from metadata-only prompts (enum values validated against #377 vocabularies; malformed output + guard rejections collected as skips), never mutating the catalog; apply_suggestions is the explicit reviewed opt-in.
extras/ranker.py / _ranker_examples.py Telemetry-trained tool reranker behind the [ranker] extra (issue #388): deterministic featurize, sklearn-gated ToolRanker (fixed-seed fit, JSON coefficient + model-card persistence — no pickle, pure-Python prediction so saved models load without sklearn), evaluate_ranker vs a lexical baseline. Example derivation from DiagnosticEvents in the private sibling.
extras/model_setup.py Local embedding-model setup helpers behind models doctor / models download (issue #386): EmbeddingModelConfig (the models.embeddings block), network-free run_model_doctor (extra/torch/cache/model-presence checks with install hints), and an explicit download_model (the only network-touching call).
extras/memory/ External-memory backend adapters that implement EpisodicStore / FactStore against an existing long-lived memory deployment without widening the Protocols (issue #195).
extras/memory/mem0.py Mem0EpisodicStore + Mem0FactStore — wrap a mem0.Memory instance scoped by user_id; writes go through Memory.add(infer=False) and items are stamped with cw_episode_id / cw_fact_id metadata for canonical-ID resolution. Gated behind the [mem0] extra (issue #195).
extras/memory/zep.py ZepEpisodicStore + ZepFactStore — wrap a zep_cloud.Zep client scoped by user_id; persist items as JSON graph episodes (graph.add(type="json")) stamped with cw_* IDs, resolving back via graph.episode.get_by_user_id. Episodic search is client-side (Zep graph search is edge/node-shaped). Gated behind the [zep] extra (issue #195).
extras/memory/_zep_common.py Internal helpers backing zep.py (isolates shared Zep scope, scan, coercion, and write mechanics): shared cw_* constants, the ZepBackendError exception, the JSON/scan helpers (_episode_records / _episode_uuid / _episode_payload), the defensive payload-coercion helpers (_coerce_str_tags / _coerce_metadata), and the _ZepStoreBase scope/scan/write base. Carries the same [zep]-extra import guard (issue #195).
extras/memory/langmem.py LangMemEpisodicStore + LangMemFactStore — wrap any LangGraph BaseStore scoped by a namespace tuple; canonical ID is the store key, value is the dataclass to_dict() payload (direct, lossless KV). search delegates to BaseStore.search. Gated behind the [langmem] extra (issue #195).
eval/ Evaluation harness (issue #12): EvalCase / EvalDataset (gold datasets), evaluate_routingRoutingEvalReport (top-k recall, MRR, confidence gap, beam steps), evaluate_contextContextEvalReport (budget utilisation + token savings vs naive concat). Pure-stdlib, deterministic; backs the eval CLI subcommand.
eval/consolidation.py Consolidation quality evaluation harness (issue #683): evaluate_consolidationConsolidationEvalReport (precision / coverage against an optional gold set + dedup ratio). Pure-stdlib, offline, deterministic.
eval/metrics.py Canonical rank-based routing metrics — recall_at_k (classic fractional recall@k), precision_at_k, reciprocal_rank (issue #354). Single source of truth imported by both eval/routing.py and benchmarks/benchmark.py so the harness and the benchmark script can no longer define the same names with different semantics.
__main__.py CLI: 15 top-level subcommands (start, demo, build, route, print-tree, init, ingest, replay, stats, inspect, budget-check, eval, consolidate, verify, serve-api) plus the mcp and catalog Typer sub-apps. start prints deterministic deployment-intent guidance without side effects (issue #660); inspect renders payload-safe context/routing/artifact reports (issue #398); catalog lint surfaces normalization + reference findings with --json and CI exit codes (issue #538).
_mcp_cli.py Backs the mcp Typer sub-app. Hosts mcp serve, mcp inspect, mcp stats, mcp generate-configs, mcp incident-pack, and mcp import-vscode; accepts native contextweaver, raw MCP tools/list, and {tools:[...]} catalog shapes. mcp serve --diagnostics FILE appends sanitized JSONL and --quiet suppresses lifecycle stderr; both are config-file keys. mcp serve --state-dir DIR (config key state_dir) persists gateway state — events.sqlite3 + artifacts/ — so artifact handles and event history survive a restart (issue #511); omit it for the in-memory default. An artifacts: config block (issue #375) wires TTL/quota/redaction into that store. mcp generate-configs emits deterministic multi-client recipe artifacts from one canonical mcp serve --config input (issue #659). mcp incident-pack creates local redacted triage bundles and never reads shell history automatically (issue #661). mcp serve --policy-preset (config key policy_preset) selects a named GatewayPreset (issue #664); an explicit policy/retry/rate_limits/cache block still wins over the preset for that block. mcp serve --print-effective-policy prints the resolved bundle as JSON and exits without requiring the catalog to exist on disk. The default serve path remains a static catalog + stub upstream; an upstreams: config block (issues #366/#368/#374) switches to _serve_live(), which launches real upstream MCP servers via adapters.upstream_launch.launch_upstreams under a startup: fault-tolerance policy — resources/prompts are not yet supported over live upstreams. mcp import-vscode (issue #367) migrates a VS Code MCP config into an upstreams: gateway config via _vscode_import.py; defaults to --dry-run.
data/ Packaged data files shipped inside the wheel via [tool.setuptools.package-data]. Exposes gateway_catalog_path() (resolves mcp_gateway_catalog.yaml to a concrete Path for both editable installs and zipped wheels — falls back to a persistent cache under tempfile.gettempdir()/contextweaver/ for zipimport). Issue #264.
examples/recipes/ MCP-client integration recipes: installed-CLI configs for Claude Desktop, Claude Code, GitHub Copilot, and Cursor plus gateway_config.yaml; serve_gateway.py remains a legacy/custom-runtime launcher (issues #278, #279, #346, #371, #429, #437).

Read the full file on GitHub · 413 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 2d ago First seen · 413 lines · 17,577 tokens per session scan A efe713695b91

Subscribe to this mod's changes

contextweaver AGENTS.md is an instructions file published in the GitHub repository dgenio/contextweaver (9 stars, last pushed 2d ago), licensed Apache-2.0. It adds 17,577 tokens to every session, about $0.0879 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.