Skip to main content

LLM Observer Proxy

CI

LLM Observer Proxy runs a temporary LiteLLM data plane for each evaluation or agent run and stores its observable LLM traffic under a stable run_id. It records requests, responses, streaming output, tool calls, token usage, cost estimates, errors, and provider-visible reasoning content.

It is independently installable and can be embedded into any evaluation platform, agent runner, or orchestration service through its HTTP API.

How It Works

There are two HTTP layers:

  1. The control plane listens on port 8790 by default. An orchestrator uses it to create, inspect, and stop run-scoped proxies.
  2. Each data plane listens on a separate, automatically allocated port. An agent uses the returned URL as an OpenAI-compatible or Anthropic-compatible LLM endpoint.

One control-plane process can manage multiple concurrent data planes. Stopping a data plane preserves its history on disk, and history remains readable after the control plane restarts.

The observer can only record information exposed by the upstream API. It cannot obtain hidden chain-of-thought that a provider does not return.

Requirements

  • Python 3.11, 3.12, or 3.13
  • A provider API key or a custom LiteLLM configuration
  • Local permission to start subprocesses and bind data-plane ports

Install

Install the command in the current Python environment:

python -m pip install llm-observer-proxy

Or install it as an isolated command with uv:

uv tool install llm-observer-proxy

Run it directly without a permanent installation:

OPENAI_API_KEY=your-openai-api-key uvx llm-observer-proxy

Because the distribution name and console command are both llm-observer-proxy, uvx resolves the package and starts the server in one command. It caches the isolated environment for subsequent runs.

For a source checkout, install the locked development environment instead:

uv sync --extra dev

LiteLLM is pinned because the observer callback adapts specific response and streaming internals. The package declares the subset of LiteLLM Proxy runtime dependencies needed by the tested LLM data plane rather than installing the full litellm[proxy] extra.

Quick Start

The bundled catalog includes gpt-5.5 and reads the OpenAI credential from the environment:

export OPENAI_API_KEY=your-openai-api-key
llm-observer-proxy

In another terminal, check the control plane:

curl http://127.0.0.1:8790/healthz

Create a data plane for a run:

curl -X POST http://127.0.0.1:8790/api/runs/run-001/proxy \
  -H 'Content-Type: application/json' \
  -d '{}'

The data plane serves every model in the selected catalog or custom LiteLLM configuration. Each LLM request selects a route through its own model field. The create response includes a dynamically allocated bare base_url, for example http://127.0.0.1:45678, plus openai_base_url (http://127.0.0.1:45678/v1) and anthropic_base_url (http://127.0.0.1:45678). Use the explicit URL for the client SDK, or call an endpoint directly:

curl http://127.0.0.1:45678/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "gpt-5.5",
    "messages": [{"role": "user", "content": "Reply with one short sentence."}]
  }'

Read the normalized history:

curl http://127.0.0.1:8790/api/runs/run-001/history

Stop the data plane without deleting its history:

curl -X DELETE http://127.0.0.1:8790/api/runs/run-001/proxy

Configuration

The command accepts these options:

--host HOST                 Control-plane bind host (default: 127.0.0.1)
--port PORT                 Control-plane port (default: 8790)
--env-file PATH             KEY=VALUE file loaded before startup (default: .env)
--artifact-root PATH        Artifact storage root
--model-catalog PATH        Model catalog JSON
--log-level LEVEL           Python log level

Paths are resolved in this order:

  1. --artifact-root and --model-catalog
  2. LLM_OBSERVER_PROXY_ARTIFACT_ROOT and LLM_OBSERVER_PROXY_MODEL_CATALOG_PATH
  3. ./artifacts and ./config/models.json in the working directory
  4. The package's secret-free bundled model catalog

Relative paths are resolved against the process working directory. LITELLM_BIN can select a specific LiteLLM executable.

Model Catalog

A model catalog has this shape:

{
  "llm_observer_proxy": {
    "base_url": "https://api.openai.com",
    "api_key": "os.environ/OPENAI_API_KEY",
    "litellm_settings": {
      "drop_params": true
    }
  },
  "models": [
    {
      "id": "gpt-5.5",
      "upstream_api": "openai"
    }
  ]
}

id is the public model alias exposed by the data plane. upstream_api selects LiteLLM's openai or anthropic provider adapter. Optional input and output token prices are used for local cost estimates. Other catalog properties, including name and provider, are accepted but ignored. Environment references use LiteLLM's os.environ/NAME syntax, which prevents a literal credential from being written to the generated configuration. See config/models.example.json for a complete example.

For advanced provider routing, pass a server-local LiteLLM YAML path as litellm_config_path in the create request. The observer callback is added to that configuration automatically.

Control API

Method Path Purpose
GET /healthz Check control-plane health
GET /api/proxies List process-local running and archived proxies
POST /api/runs/{run_id}/proxy Create a run-scoped data plane
GET /api/runs/{run_id}/proxy Read proxy state
DELETE /api/runs/{run_id}/proxy Stop a data plane
GET /api/runs/{run_id}/history Read normalized history
GET /api/runs/{run_id}/conversation Read the latest conversation

The create payload may be empty. Optional fields are port, bind_host, litellm_config_path, litellm_env, and strip_callbacks. Unknown fields are ignored. The complete request and response contract is documented in docs/control-plane-api.md.

Artifacts

Each run writes:

artifacts/runs/<run_id>/platform/llm/
  config.yaml
  conversation_snapshot.json
  events.jsonl
  litellm.log

The generated YAML is retained as a run artifact. Keep provider credentials in environment variables rather than writing literal values into a model catalog or custom YAML.

Supported Scope

The supported data-plane surface is LiteLLM's OpenAI-compatible LLM API and Anthropic /v1/messages, plus the control and history APIs documented above. LiteLLM MCP routes, its administration UI, database persistence, and enterprise gateway features are not part of this project's compatibility contract. In particular, the mcp package is intentionally not installed because MCP routes are not used by the observer and are lazy-loaded by the pinned LiteLLM version.

Troubleshooting

  • The control plane starts, but proxy creation returns 502: inspect the returned log_path or the run's litellm.log. Missing provider variables and invalid custom YAML are the most common causes.
  • LiteLLM cannot be found: install the package and command in the same environment, or set LITELLM_BIN to an executable path.
  • Proxy creation returns 409: the run_id already has a running data plane, a requested port is unavailable, or the selected configuration is invalid.
  • History is empty: confirm the agent is using the returned data-plane URL, not the provider URL directly.

Security

The control API is an administrative interface: it can start subprocesses, select listening ports, pass child environment values, and read server-local LiteLLM configurations. Version 0.1.x has no built-in authentication. Bind it to loopback or a trusted private network and read .github/SECURITY.md before remote deployment.

History can contain prompts, model output, tool output, and credentials. Apply appropriate filesystem permissions, access control, and retention policies to the artifact root.

Development

uv sync --extra dev
uv run pytest
LLM_OBSERVER_PROXY_RUN_INTEGRATION=1 uv run pytest tests/test_integration_proxy.py
uv build
uvx twine check dist/*

License

Apache-2.0. See LICENSE and NOTICE.

Authors

Metadata

Release files for llm-observer-proxy 0.1.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 llm-observer-proxy 0.1.0
File Size Uploaded
llm_observer_proxy-0.1.0.tar.gz 43.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for llm-observer-proxy 0.1.0
File Interpreter ABI Platform
llm_observer_proxy-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 75.2 kB

Release files / llm_observer_proxy-0.1.0.tar.gz

Download URL llm_observer_proxy-0.1.0.tar.gz
Size 43.4 kB
Tags Source
SHA-256 checksum
How to use checksums
44c9231326a1e586460705d9bf070b0822f4e7a9c9c8f4ad282547e35deedc63
BLAKE2b-256 checksum
How to use checksums
b9ef493ab06ca4c49a4941c1db54d607c239504fc7f835ae30b43d39486170b2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 10, 2026.

Transparency log

Release files / llm_observer_proxy-0.1.0-py3-none-any.whl

Download URL llm_observer_proxy-0.1.0-py3-none-any.whl
Size 31.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ea51b7244baa572b71f47b6a50adde7b2602995a7741242927222ee602c6f7ed
BLAKE2b-256 checksum
How to use checksums
8e1571bc4ae8d70a3cfc269146f18ab7c6ab6d739aa6f1f86d101e2303072e8e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

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