Skip to main content

Autotune Hook

Project description

Autotune Hook

Python instrumentation for reporting OpenRouter calls to AutoTune.

Zero-code: with_session is the only line (recommended)

With AUTOTUNE_ENDPOINT (and usually AUTOTUNE_API_KEY) in the environment, entering a session auto-enables process-wide httpx interception: every OpenRouter chat completion made by any httpx-based SDK (openai-python, pydantic-ai) is preflighted against cloud workflow policy and shadow-reported or proxied accordingly. No hook construction, no transport wiring, no decorator — the session context is the only AutoTune line in application code, and it carries all dynamic attribution:

from autotune_hook import with_session

with with_session(
    workflow="slack-agent",
    session_id=thread_id,
    user_id=user_id,
):
    completion = client.chat.completions.create(...)  # any httpx-based SDK

Workflow, project, session, and user are code-only: the hook deliberately never reads them from env vars, because they vary with code and callers. The only attribution default that rides the environment is AUTOTUNE_ENVIRONMENT (deployment-static by nature). Requires the httpx extra (pip install autotune-hook[httpx]).

Controls:

  • AUTOTUNE_INTERCEPT=0 — kill switch: sessions only attribute, never install interception (for apps wired with a decorator or explicit transport instead).
  • AUTOTUNE_HOOK_MODE=observe — report-only tee semantics: no preflight, no proxy, AutoTune being down can never block a model call. The default (full) honors the cloud policy envelope, including proxy mode.
  • enable_interception() / disable_interception() — explicit runtime control over the same machinery (mirrors the TypeScript hook's enableInterception()).

Per-call overrides can also ride request headers wherever the SDK lets you add them (openai-python extra_headers): x-autotune-workflow, x-autotune-project, x-autotune-environment, x-autotune-session-id, x-autotune-user-id. Headers beat the session context and are stripped before the provider sees the request.

Non-httpx HTTP stacks (requests, aiohttp) are not intercepted — use the wrapper/decorator below or the drop-in proxy base URL for those.

Transport integration (explicit wiring)

Same machinery, scoped to one client instead of the process. Wrap the app's httpx transport and every OpenRouter chat completion through it is visible to AutoTune. mode="observe" (default) is a pure tee; mode="full" adds the preflight/proxy envelope:

import httpx
from autotune_hook import AutotuneAsyncTransport

client = httpx.AsyncClient(transport=AutotuneAsyncTransport(mode="full"))
openrouter = AsyncOpenAI(base_url="https://openrouter.ai/api/v1", http_client=client)

Already wrapping transports (retries, sanitizers)? Put the AutoTune transport outermost so one logical call maps to one recorded run — the final response the app saw.

Wrapper / decorator integration

For call sites that hold the request payload directly, and for non-httpx stacks. These also honor cloud workflow policy: the request is preflighted, and AutoTune answers with an explicit envelope — {"mode": "shadow", "ttl_seconds": N} (execute the wrapped call, report its output in the background, and skip further preflights for that workflow until the TTL expires) or {"mode": "proxy", "response": {...}} (return the AutoTune-executed response). Any response without the envelope falls back to the app's own call, so an intermediary's bare 200 can never be mistaken for an LLM response. Streaming requests pass through unobserved.

from autotune_hook import AutotuneHook

hook = AutotuneHook(workflow="email-triage")

def call_openrouter(payload):
    return hook.openrouter_call(
        payload,
        lambda: openrouter_client.chat.completions.create(**payload),
    )

Decorator form:

@hook.openrouter()
def call_openrouter(**payload):
    return openrouter_client.chat.completions.create(**payload)

Integrations stack safely: a call already observed by a decorator or an explicit transport is suppressed at the interception layer, so one logical call is never recorded twice.

Sessions

from autotune_hook import with_session

with with_session(session_id=run_id, user_id=user_id, workflow="ocr"):
    ...  # every hooked/intercepted call inside is attributed

Sessions nest (inner values win), flow through async code and asyncio.to_thread, and carry workflow, project, environment, session_id, and user_id.

Reporting behavior

Reports ride a single background thread with a bounded queue: they never block the calling thread or event loop, overflow drops reports (with a warning) rather than growing memory, and flush_reports() drains pending reports at worker shutdown (also registered via atexit). Inline data: URLs larger than 256 bytes (base64 images) are replaced with a size-and-hash placeholder before reporting; disable with AUTOTUNE_HOOK_REDACT_DATA_URLS=0. Reports whose serialized size exceeds AUTOTUNE_HOOK_MAX_REPORT_BYTES (default 4 MB) are dropped with a warning.

Configuration

Set AUTOTUNE_ENDPOINT and, when required, AUTOTUNE_API_KEY in the environment. If AUTOTUNE_ENDPOINT is unset, the hook stays fully out of the way.

Dynamic attribution belongs in code, not static process env. Pass workflow, session, user, project, and environment values through with_session(...), AutotuneHook(...), or per-call metadata/headers so each request is attributed to the right run.

Project details


Download files

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

Source Distribution

autotune_hook-0.2.0.tar.gz (22.7 kB view details)

Uploaded Source

Built Distribution

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

autotune_hook-0.2.0-py3-none-any.whl (17.4 kB view details)

Uploaded Python 3

File details

Details for the file autotune_hook-0.2.0.tar.gz.

File metadata

  • Download URL: autotune_hook-0.2.0.tar.gz
  • Upload date:
  • Size: 22.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for autotune_hook-0.2.0.tar.gz
Algorithm Hash digest
SHA256 07931608ce6287a84373f20b3061cc4c8d29c276e67756ebab77b3ba267732e5
MD5 66adb9ae85c18742660d3c3d3b5696f5
BLAKE2b-256 4b8d7971935b8d3492e38b5ca3cb8b6167c5fca58b1be4c86e205fcf6c885ce4

See more details on using hashes here.

Provenance

The following attestation bundles were made for autotune_hook-0.2.0.tar.gz:

Publisher: publish-python-hook.yml on shellzbt/sota-autotune

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file autotune_hook-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: autotune_hook-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 17.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for autotune_hook-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a2f687f00d8ebcea41232a37a7722dcae5ec5dd4c70130ffe4b1be7bf6c1a5cb
MD5 08520d7b4f1b64aed8cfa159e1f5c9a1
BLAKE2b-256 42a086e3578e553014b5bae296fe009526c52acb7c5039032adc1cd263d5f57b

See more details on using hashes here.

Provenance

The following attestation bundles were made for autotune_hook-0.2.0-py3-none-any.whl:

Publisher: publish-python-hook.yml on shellzbt/sota-autotune

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

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