Skip to main content

OpenAnchor

LLM token-attribution middleware: capture, attribute, and observe every LLM call — with real OpenTelemetry export and real semantic caching.

OpenAnchor sits alongside your LLM calls (via a LangChain middleware today, or by calling its collector API directly from any provider) and captures token consumption events, breaks them down across 6 dimensions (phase, operation type, prompt template, session, model, and pattern), and exposes that data through a query API. It also ships real OTEL span export and a real semantic-caching layer, both backed by actual embeddings and storage — not mocked stand-ins.

PyPI Python 3.9+ Tests: 169 Passing License: Proprietary (free w/ attribution)


30-Second Start

from openanchor import TokenCollector, Analytics, AttributionModel

collector = TokenCollector()
collector.set_session("session_1")

collector.capture_event(
    call_id="call_1",
    model="gpt-4",
    provider="openai",
    input_tokens=120,
    output_tokens=45,
)

attribution = AttributionModel(collector.store)
analytics = Analytics(collector, attribution)

summary = analytics.get_summary("session_1")
print(summary["total_tokens"], summary["by_operation"])

Or wrap a LangChain runnable directly:

from openanchor.middleware.langchain import OpenAnchorMiddleware

middleware = OpenAnchorMiddleware(project_name="my_app")
wrapped_chain = middleware(my_langchain_runnable)

result = wrapped_chain.invoke({"model": "gpt-4", "prompt": "..."})
print(middleware.get_session_stats())

See examples/basic_usage.py and examples/mcp_openanchor.py for full runnable examples.


What's actually implemented

Capability Status
Token capture + 6D attribution (phase/operation/prompt/session/model) Real, tested
In-memory + SQLite event storage (indexed, WAL, connection-reused) Real, tested
LangChain middleware (OpenAnchorMiddleware, WrappedRunnable) Real, tested
OpenTelemetry span export (openanchor.otel) Real, tested — see below
Semantic caching (openanchor.semantic_cache, 12 MCP tools) Real, tested — see below
Cost governance / token profiles / optimization tracking (okf_*) Real, tested
Docker image with a working entry point Real (python -m openanchor)

Observability (OpenTelemetry)

Every TokenCollector.capture_event call is wrapped in a real OTEL span (token counts, model, provider, operation type, and cost-if-provided as span attributes) — not a mocked stand-in. Tracing is off by default (the collector's hot path shouldn't pay tracing overhead or make network calls unless asked to):

from openanchor import configure_tracing

configure_tracing(exporter="console")  # safe default, no network calls
# or: configure_tracing(exporter="otlp", otlp_endpoint="http://localhost:4318/v1/traces")

Full details, env-var-only configuration, and the span attribute reference: OTEL_SETUP_GUIDE.md. Tests use OTEL's in-memory span exporter (tests/test_otel.py) to verify real spans are produced.


Semantic caching

openanchor.semantic_cache implements real embedding-based caching:

  • Embeddings: uses a local Ollama server (nomic-embed-text or similar) when reachable at localhost:11434, and automatically falls back to a deterministic, dependency-free feature-hashing embedder when it isn't — so the cache always works, online or offline.
  • Storage: SQLite-backed (SemanticCacheStore), storing embeddings + responses + real lookup history (for real hit-rate stats, not hardcoded numbers).
  • Lookup: real cosine-similarity search, not string matching.
from openanchor import SemanticCache
from openanchor._mcp_tools import OpenAnchorMCPHandler

cache = SemanticCache(cache_db_path="cache.db")
handler = OpenAnchorMCPHandler(cache)

await handler.cache_prompt_embedding("Summarize this report", response="...")
matches = await handler.find_cached_similar("Summarize this report for me")

All 12 MCP tools (cache_prompt_embedding, find_cached_similar, analyze_cache_hit_rate, get_cache_statistics, etc) compute real numbers from actual cache contents and lookup history — see openanchor/_mcp_tools.py. Tests: tests/test_semantic_cache.py, tests/test_mcp_tools.py.

MCP connector security

If you expose these tools over a network port via SemanticCache.start_mcp_connector(), the defaults are deliberately locked down: binds to 127.0.0.1 (not 0.0.0.0), no CORS origins allowed (not *), and least-privilege read-only permissions (not wildcard actions/roles). Widening any of that requires explicit opt-in — see openanchor/_mcp_connector.py and PRODUCTION_DEPLOYMENT.md.


Privacy

OpenAnchor's job is intercepting and storing metadata about LLM calls, so its privacy posture matters:

  • Raw prompt/response text capture is off by default. The LangChain middleware's WrappedRunnable.invoke() records only a SHA-256 hash and length of the input/output by default — never the actual text — unless you construct OpenAnchorMiddleware(capture_raw_content=True).
  • Opt-in captures are redacted by default. When raw capture is enabled, excerpts are run through best-effort PII/secret redaction (emails, phone numbers, API keys, credit-card-like numbers, SSNs) before being stored, unless you explicitly disable that with redact_captured_content=False.
  • Retention/TTL. SqliteEventStore(retention_days=N) automatically purges events older than the retention window (in addition to the existing manual .clear()), so persisted call data doesn't accumulate indefinitely once a retention policy is configured.
from openanchor import SqliteEventStore
from openanchor.middleware.langchain import OpenAnchorMiddleware

store = SqliteEventStore("events.db", retention_days=30)
middleware = OpenAnchorMiddleware(
    store=store,
    capture_raw_content=False,       # default; only hash+length stored
    # capture_raw_content=True,      # opt in to store excerpts
    # redact_captured_content=True,  # default when opted in
)

See openanchor/privacy.py and tests/test_privacy.py.


Installation

pip install openanchor
# with OTLP exporter support:
pip install "openanchor[otel]"

Docker

docker build -t openanchor .
docker run -p 8080:8080 openanchor
curl http://localhost:8080/health

See PRODUCTION_DEPLOYMENT.md for details.


Documentation


Testing

pip install -e ".[dev]"
pytest tests/ -v
ruff check .
mypy openanchor/
bandit --ini .bandit -r openanchor/

169 tests across 9 test files, covering the collector/attribution/analytics core, the LangChain middleware (including the token-capture hot path), SQLite and in-memory storage, OTEL span export, semantic caching, the MCP connector's security defaults, the OKF cost-governance/token-profile/ optimization-tracking modules, and the __main__ CLI entry point.


License

Proprietary License — free to use with explicit attribution. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

openanchor-0.6.0.tar.gz (57.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

openanchor-0.6.0-py3-none-any.whl (47.4 kB view details)

Uploaded Python 3

File details

Details for the file openanchor-0.6.0.tar.gz.

File metadata

  • Download URL: openanchor-0.6.0.tar.gz
  • Upload date:
  • Size: 57.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for openanchor-0.6.0.tar.gz
Algorithm Hash digest
SHA256 36d5af6e7c277d854d6b2a3f4fda34843ebf140c8d93415160f1aff5b2add5c6
MD5 f429f5afa677cfcd6119d376e4263901
BLAKE2b-256 e90e18030ac3b573ffb640c607754f8d4c5ac4f45aea0a92d32bf33a50a607a0

See more details on using hashes here.

File details

Details for the file openanchor-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: openanchor-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 47.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for openanchor-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 001ddd4d2d1e1e91db88d284e6367f0cf98af64d91f80ef3fcf062e6c8796ac9
MD5 86582947c832ddff515e0676065813ad
BLAKE2b-256 0e42e547efff34f8e9d6d0c7c369e8c6d166218ea504fd1b74a1df156c5badd0

See more details on using hashes here.

Release history Release notifications | RSS feed

0.6.1

2 files

This release

0.6.0 This release

2 files

0.5.0

2 files

0.4.0

2 files

0.2.0

2 files

0.1.4

1 file

0.1.2

2 files

0.1.1

1 file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page