Skip to main content

Ganivra Python SDK

Ganivra measures the cost and unit economics of AI executions without proxying model traffic or storing prompts and responses.

Install

python -m pip install ganivra

Ganivra requires Python 3.10 or newer and currently instruments synchronous OpenAI Responses API calls.

Initialize before creating the OpenAI client

import ganivra
from openai import OpenAI

ganivra.init(api_key="gv_live_your_workspace_key")
client = OpenAI()

response = client.responses.create(
    model="gpt-5",
    input="Explain our refund policy simply.",
)

Initialization automatically captures model, input/output/cached token counts, latency, status, error type, and environment. Ganivra creates execution and step IDs and exports the metadata on a bounded background queue.

Add business context for unit economics

def answer_for(account, credits_debited):
    with ganivra.trace(
        metadata={"channel": "voice"},
        application="support-platform",
        workflow="support_answer",
        feature="support_chatbot",
        customer_id=account.id,
        plan_key=account.plan_key,
        credits=credits_debited,
        prompt_id="support_answer",
        prompt_version="v1",
    ):
        return client.responses.create(
            model="gpt-5",
            input="Explain our refund policy simply.",
        )

Trace metadata is optional. It enables customer, feature, workflow, prompt, and margin reporting. Use the stable tenant or account identifier already present in each authenticated request as customer_id; customers do not need to be registered with Ganivra first. Configure customer pricing plans separately when you want revenue derived automatically instead of sending revenue_usd per execution. The metadata mapping accepts additional bounded JSON dimensions and is inherited by nested traces. Use pseudonymous identifiers where appropriate.

Pricing rates stay in Ganivra; never look up a rate or calculate revenue in the instrumented request. Subscription and per-execution plans only need customer_id. Token and hybrid plans use the token/execution telemetry captured by the SDK. For a credit/unit plan, also pass the exact usage attribute configured on the plan—credits above—with the units your application already deducted. Send plan_key when customers can choose or change plans without a manual Ganivra assignment. Ganivra combines the plan and credit usage with the rate configured in your workspace.

Treat one billable customer action as one trace/execution. If one trace produces multiple model calls, the inherited transaction-level credit value is repeated on the resulting events and counted once. Start a separate trace for each independently billed action.

Track MCP tool calls through the same API

Ganivra 0.4 adds ganivra.mcp_call(...). It uses the same API key, background queue, batching, retries, /v1/events endpoint, and active trace as automatic model instrumentation. The helper measures latency and outcome around the tool call but never receives or inspects its arguments or result.

import ganivra

with ganivra.trace(
    application="customer-operations-platform",
    workflow="lead_qualification",
    feature="sales_agent",
    customer_id=account.id,
) as execution:
    with ganivra.mcp_call(
        server="crm-server",
        tool="search_accounts",
        transport="streamable_http",
        auth_type="oauth",
        metadata={
            "result_count": 3,
            "cache_hit": False,
            "region": "us-east",
        },
        provider_reported_cost_usd=0.002,
    ) as tool_call:
        result = mcp_client.call_tool("search_accounts", arguments)

The emitted MCP event shares execution.execution_id with model calls inside the surrounding trace. On success it records status="success"; if the tool raises, Ganivra records only the exception class as error_type and re-raises the original exception unchanged.

Shared execution_id is sufficient for execution-level cost attribution. When you also need an explicit parent-child edge, use the yielded MCP step_id as the next trace's parent_step_id:

with ganivra.trace(
    execution_id=execution.execution_id,
    parent_step_id=tool_call.step_id,
):
    response = client.responses.create(
        model="gpt-5",
        input=build_model_input(result),
    )

The OpenAI event remains a normal model event with no event_type; only the MCP tool event sends event_type="mcp".

MCP helper parameters

Parameter Required Guidance
server Yes Stable logical MCP server name, such as crm-server; do not send a URL containing credentials
tool Yes Exact stable tool name advertised by the server
transport No Category such as stdio, sse, or streamable_http
auth_type No Coarse category such as oauth, api_key, or none; never send scopes or credentials
metadata No Bounded counts, categories, IDs, and booleans only
provider_reported_cost_usd No Exact known cost; send 0 only when the tool is known to be free
execution_id No Override when joining a trace created in another process or service
parent_step_id No Step that directly caused this MCP invocation

Do not place tool arguments, tool results, prompts, responses, OAuth scopes, workspace IDs, tokens, secrets, personal data, or request/response bodies in metadata. Ganivra rejects these content-bearing fields at ingestion.

MCP cost behavior

  • If the MCP provider returns an exact cost, pass it through provider_reported_cost_usd.
  • If a tool has a fixed contract rate, configure provider mcp, model <server>/<tool>, and a request component rate in Ganivra.
  • Send provider_reported_cost_usd=0 only for a confirmed free tool call.
  • If no exact cost or rate exists, omit cost. Ganivra marks the step unpriced rather than silently treating unknown cost as zero.

When not to use the Python helper

Use the REST event contract directly when MCP calls happen in Node.js, Java, Go, another service, or existing middleware that already measures tool calls. Do not duplicate the event from both the Python helper and REST integration; if retries are possible, keep one stable event_id in the direct REST path.

Record confirmed purchases (optional)

Event telemetry works on its own and provides AI cost plus plan-rated unit economics. After your payment webhook is verified and your application has updated the customer's credits or subscription, optionally send the confirmed financial transaction so Ganivra can reconcile plan-rated revenue with payment actuals.

result = ganivra.transactions.create(
    external_id=payment_intent.id,  # stable provider ID; retries are idempotent
    customer_id=account.id,
    transaction_type="credit_purchase",
    amount=3999,
    currency="INR",
    amount_usd=47,
    units_purchased=1000,
    plan_key="growth",
    source="stripe",
)

For USD, send only amount and currency="USD". For another currency, send exactly one of amount_usd or exchange_rate_to_usd. Use transaction_type="subscription_payment" for renewals and transaction_type="refund" for refunds. Include execution_id when a payment belongs to a particular AI result. This call is synchronous and raises ganivra.GanivraAPIError if Ganivra does not accept the transaction; only call it after your own payment and entitlement updates succeed.

Configuration

ganivra.init(
    api_key="gv_live_your_workspace_key",
    endpoint="https://api.ganivra.com",
    environment="production",
    queue_size=1000,
    batch_size=20,
    timeout_seconds=2.0,
    max_retries=2,
)

For local Ganivra development, set endpoint="http://127.0.0.1:8000". Call ganivra.flush() in short-lived scripts when you want to wait briefly for queued telemetry.

Privacy and failure behavior

  • OpenAI requests continue going directly from your application to OpenAI.
  • Prompt and response bodies are never collected.
  • OpenAI API keys are never collected.
  • Telemetry failures never change the OpenAI result or exception your code sees.
  • A full queue or unavailable Ganivra endpoint drops telemetry instead of blocking the application.

Prefer the language-independent REST API when automatic Python instrumentation is not appropriate. The canonical API contract is documented at docs/API.md in the Ganivra project.

Metadata

Release files for ganivra 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ganivra 0.4.0
File Size Uploaded Provenance Actions
ganivra-0.4.0.tar.gz 13.5 kB Without provenance Details for ganivra-0.4.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for ganivra 0.4.0
File Interpreter ABI Platform Actions
ganivra-0.4.0-py3-none-any.whl Python 3 none any Details for ganivra-0.4.0-py3-none-any.whl

Total release size: 28.0 kB

Release files / ganivra-0.4.0.tar.gz

Download URL ganivra-0.4.0.tar.gz
Size 13.5 kB
Tags Source
SHA-256 checksum
How to use checksums
ae7538ffe2fa9122209230b99b1faf81f8891a946f606c352f357f8c179332c8
BLAKE2b-256 checksum
How to use checksums
1974cd6f1c7999d67466d42cafe46137c64f699db820212a1f9c3dcc2879d807
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release files / ganivra-0.4.0-py3-none-any.whl

Download URL ganivra-0.4.0-py3-none-any.whl
Size 14.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d81b62190f8a93e2cd4b245fbf44bca64ad2088a9d9e0d7a348cdefc71e93f8c
BLAKE2b-256 checksum
How to use checksums
af7593f634f4216797c0293b783aa1894748b04c818b59763bdc4708c9c8413f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Security for ganivra 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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