Skip to main content

metergraph (Python)

Zero-runtime-dependency capture for OpenAI, Anthropic, Gemini, and Python Vercel AI Gateway clients. wrap() initializes capture from the environment, so setup is one line per client; call metergraph.init(...) before the first wrap() only to pass options in code.

import metergraph
from openai import OpenAI

# Anthropic() and google-genai's genai.Client() wrap the same way.
client = metergraph.wrap(OpenAI())
metergraph.set_session("ticket-123")

with metergraph.trace("ticket-workflow"):
    with metergraph.route("ticket-classifier", unit="answer"):
        model = metergraph.model_for("ticket-classifier", default="gpt-4.1-mini")
        client.chat.completions.create(model=model, messages=[...])

# Emit this after the user-visible task resolves. It shares the bounded async
# transport and contains no prompt or output content.
metergraph.record_outcome(
    "ticket-classifier",
    model=model,
    task_completed=True,
    feedback_score=1,
    turns_to_resolution=2,
    escalated=False,
)

Vercel's supported Python surface is AI Gateway through the OpenAI or Anthropic SDK. Point either client at the public gateway and wrap() detects it automatically:

import os
import metergraph
from openai import OpenAI

gateway = metergraph.wrap(OpenAI(
    api_key=os.getenv("AI_GATEWAY_API_KEY") or os.getenv("VERCEL_OIDC_TOKEN"),
    base_url="https://ai-gateway.vercel.sh/v1",
))

gateway.chat.completions.create(
    model="anthropic/claude-sonnet-4.6",
    messages=[{"role": "user", "content": "Hello"}],
)

Creator-qualified model IDs are normalized for gateway catalog pricing. Sync, async, streaming, tool calls, and OpenAI Responses API calls are captured. Use metergraph.wrap(client, provider="vercel") only when a compatible client is behind a custom gateway URL that cannot be detected automatically.

Configuration:

  • METERGRAPH_APP_TOKEN — required bearer token
  • METERGRAPH_INGEST_URL — optional override; defaults to the hosted HTTPS endpoint
  • METERGRAPH_CAPTURE_TEXT=0 — opt out of content capture globally
  • METERGRAPH_DISABLED=1 — process kill switch
  • METERGRAPH_QUEUE_SIZE, METERGRAPH_BATCH_SIZE, METERGRAPH_FLUSH_SECONDS

Delivery is bounded and off the request path. Queue overflow or a collector outage drops capture and increments internal counters; it never changes the provider call. Each wire batch is bounded to 512 KiB after optional gzip. SDK 0.3 captures the scrubbed provider request and a normalized response envelope, including assistant content and tool calls, by default. Provider credentials and transport headers are removed. Request and response are each limited to 100 KiB of UTF-8 with an explicit truncation marker. capture_text=False on route() or trace() overrides the global content policy for a sensitive operation. The equivalent initialization option is metergraph.init(capture_text=False). The public open-source server continues to discard content even when the SDK sends it; the hosted dashboard retains content under the workspace retention period.

metergraph.trace(name, trace_id=..., parent_span_id=...) is a sync/async context manager and decorator. Calls inside one trace share a trace ID and receive distinct span IDs. Calls outside a trace become deterministic single-span traces after ingestion. Manual IDs can join work across process boundaries; automatic W3C HTTP propagation is not included.

Config reads are ETag-aware and fail open to the default model. record_outcome requires a stable session ID and the model actually used so a session-sticky canary can compare task completion and optional feedback, turn-count, escalation, abandonment, edit-distance, and regeneration signals.

OpenAI Batch API output JSONL is captured per inference when a wrapped client.files.content() / retrieve_content() result is read. Anthropic message batches are captured per inference while iterating a wrapped client.messages.batches.results() result. Run result consumption inside a route() context so the asynchronous batch retains its product route. Batch rows carry real per-result usage and the batch pricing flag; job-management polls themselves are not miscounted as model calls.

Set up with an AI coding agent

Paste this into Claude Code, Codex, Cursor, or any coding agent inside the codebase you want instrumented:

Instrument this codebase's LLM API costs with the `metergraph` PyPI package
(https://github.com/PioneerSquareLabs/metergraphsdk): pip install metergraph,
then wrap every OpenAI()/AsyncOpenAI(), Anthropic()/AsyncAnthropic(), and
genai.Client() construction in place, e.g. client = metergraph.wrap(OpenAI()).
OpenAI or Anthropic clients pointed at https://ai-gateway.vercel.sh are Vercel
AI Gateway clients and are detected automatically; keep their creator/model ID
and AI_GATEWAY_API_KEY / VERCEL_OIDC_TOKEN configuration unchanged.
wrap() returns the same client and initializes itself from the environment:
METERGRAPH_APP_TOKEN is required (capture is silently off without it) and
METERGRAPH_INGEST_URL is only for self-hosted servers. Add both to
.env.example, and never commit a real token. SDK 0.3 captures scrubbed provider
requests and normalized responses by default for the hosted dashboard; use
METERGRAPH_CAPTURE_TEXT=0 or capture_text=False around sensitive operations.
Provider credentials and transport headers must never be captured. Capture is
fail-open, so do not change call sites, arguments, or error handling; sync,
async, and streaming work unchanged. Use metergraph.trace("stable-name") to
group multi-call workflows. Attribution to the calling function is automatic;
optionally pin stable names on key LLM-calling functions with
@metergraph.track. On
serverless, call metergraph.flush() before the handler returns. When done,
list every client you wrapped and flag LLM calls made outside the official
openai / anthropic / google-genai SDKs, since those are not captured.

Download files

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

Source Distribution

metergraph-0.3.2.tar.gz (39.6 kB view details)

Uploaded Source

Built Distribution

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

metergraph-0.3.2-py3-none-any.whl (25.8 kB view details)

Uploaded Python 3

File details

Details for the file metergraph-0.3.2.tar.gz.

File metadata

  • Download URL: metergraph-0.3.2.tar.gz
  • Upload date:
  • Size: 39.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.3

File hashes

Hashes for metergraph-0.3.2.tar.gz
Algorithm Hash digest
SHA256 79a7664551faa031fb61eee538493428f5f058fac5a3a8bfb3bb48a06b71626c
MD5 9f7c54d5d5dd67c3f4b69cd2edf741d0
BLAKE2b-256 317d66e7ca582815ef358bbf4ca7b66d6c0a6a23b6575125383e6835651961dd

See more details on using hashes here.

File details

Details for the file metergraph-0.3.2-py3-none-any.whl.

File metadata

  • Download URL: metergraph-0.3.2-py3-none-any.whl
  • Upload date:
  • Size: 25.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.3

File hashes

Hashes for metergraph-0.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 f51e458cefac81f0c20cd802f4a82ac56fa7fc123f961c9115f0e15c0b1e528f
MD5 f2bf3cf2b248e135cc3f6b2bbc8dc917
BLAKE2b-256 2f1060457b50f48f7e14dd41ea5f5ce52f3affcfae70f32033e91c67fe9ebd7f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page