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: 248 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/

248 tests across 14 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, the __main__ CLI entry point, the 6D attribution analyzer, and the federated-learning / multi-agent-optimization / model-evolution modules.


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.1.tar.gz (72.9 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.1-py3-none-any.whl (57.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: openanchor-0.6.1.tar.gz
  • Upload date:
  • Size: 72.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.16

File hashes

Hashes for openanchor-0.6.1.tar.gz
Algorithm Hash digest
SHA256 d81db59cb36ce0c1e5164a72009cfb5e028e4ecb8537ae9bc693d23c27583d8f
MD5 2167a08510a71397ed8453faf1f9f437
BLAKE2b-256 84203f82a7b2f8c4d213703d4caa52aeac814d846a01359f09c643991a51e336

See more details on using hashes here.

File details

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

File metadata

  • Download URL: openanchor-0.6.1-py3-none-any.whl
  • Upload date:
  • Size: 57.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.16

File hashes

Hashes for openanchor-0.6.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b9ae7ba10c799907c0d1ca0b08d4e91462f6e9a24621943fa36c6c9e6207615a
MD5 63ec9c6f167f72bc98db5de81285488f
BLAKE2b-256 b074f9933290855a7235f9d6104748766445c8cf8eec26062ee7702047bc4ae6

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.6.1 This release

2 files

0.6.0

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