Skip to main content

Local AI cost, latency, prompt, and workflow tracking.

Project description

OpenHarness

Local AI cost and workflow tracking for engineering teams.

No cloud. No signup. SQLite by default.

Install

pip install quadrant-openharness
openharness setup --demo
openharness costs

Use whichever pip command points at Python 3.10+ on your machine: pip, pip3, or python -m pip.

The package installs both command names:

openharness costs
agentharness costs

For the latest code from GitHub instead of PyPI:

pip install "git+https://github.com/Quadrant-Labs/openharness.git"

Why this exists

AI agents and AI-backed workflows can make thousands of model calls before anyone notices the bill. OpenHarness starts with the smallest useful wedge: track model calls locally, estimate cost, then show engineers where the money and latency go.

Proxy / start usage

openharness start runs a local forwarding proxy in front of an AI provider. Your app sends requests to OpenHarness, OpenHarness forwards them to the provider, then records model, token usage, latency, status, estimated cost, and optional tags in local SQLite.

This is the easiest way to use OpenHarness because your application does not need to import an OpenHarness SDK. Any OpenAI-compatible client, shell script, internal service, or agent runner can point at the local proxy.

Start an OpenAI-compatible proxy:

openharness start openai --port 8787

Then point your app at it:

export OPENAI_BASE_URL=http://127.0.0.1:8787/v1
export OPENAI_API_KEY=sk-...

Run your app normally, then view costs:

openharness costs --last 30d

Python example

from openai import OpenAI

client = OpenAI(
    api_key="sk-...",
    base_url="http://127.0.0.1:8787/v1",
)

response = client.chat.completions.create(
    model="gpt-5.5",
    messages=[{"role": "user", "content": "Review this PR for risky changes."}],
)

print(response.choices[0].message.content)

Node example

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  baseURL: "http://127.0.0.1:8787/v1",
});

const response = await client.chat.completions.create({
  model: "gpt-5.5",
  messages: [{ role: "user", content: "Review this PR for risky changes." }],
});

console.log(response.choices[0].message.content);

curl example

curl http://127.0.0.1:8787/v1/chat/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "x-openharness-team: platform" \
  -H "x-openharness-service: pr-review-bot" \
  -d '{
    "model": "gpt-5.5",
    "messages": [{"role": "user", "content": "Review this PR."}]
  }'

Tag traffic

You can tag all traffic at proxy startup:

openharness start openai \
  --team platform \
  --service pr-review-bot \
  --env production \
  --project ai-platform

Or tag individual requests with headers:

x-openharness-org: acme
x-openharness-team: platform
x-openharness-service: pr-review-bot
x-openharness-env: production
x-openharness-workflow: pr_reviews
x-openharness-step: review

Then use org-level showback:

openharness org --last 30d

Other providers

The proxy has initial usage extraction for Anthropic and Gemini:

openharness start anthropic --port 8788
openharness start google --port 8789

For any other OpenAI-compatible provider, use generic mode with an upstream base URL:

openharness start generic --target https://api.openrouter.ai/v1 --port 8787
openharness start generic --target https://api.groq.com/openai/v1 --port 8787
openharness start generic --target https://api.together.xyz/v1 --port 8787
openharness start generic --target http://localhost:11434/v1 --port 8787

If you pass --target without a provider, OpenHarness automatically uses generic mode:

openharness start --target https://api.example.com/v1

Generic mode forwards every path under the target URL and tries to extract usage from common response shapes such as usage.prompt_tokens, usage.completion_tokens, usage.input_tokens, usage.output_tokens, and usageMetadata.promptTokenCount. If OpenHarness does not know the model price, it still records tokens, latency, status, tags, and model name, but cost is reported as unknown/zero until that model is added to the pricing catalog.

Prompt previews

Prompt previews are off by default. To store a local 240-character prompt preview for each JSON request:

openharness start openai --record-prompt-preview

Notes

  • OpenHarness estimates costs from provider usage metadata in non-streaming JSON responses.
  • Streaming calls are forwarded, but they may not be costed unless the provider returns parseable usage data.
  • The proxy stores data locally in .openharness/openharness.db unless OPENHARNESS_DB is set.
  • The old command also works: openharness proxy --provider openai --port 8787.

Org gateway mode

For a team or org, run OpenHarness as a shared gateway and tag traffic by owner:

openharness start openai \
  --host 0.0.0.0 \
  --port 8787 \
  --org acme \
  --team platform \
  --service pr-review-bot \
  --env production

Apps can also tag individual requests with headers:

x-openharness-org: acme
x-openharness-team: platform
x-openharness-service: pr-review-bot
x-openharness-env: production
x-openharness-workflow: pr_reviews
x-openharness-step: review

Or set tags on the proxy process:

export OPENHARNESS_ORG=acme
export OPENHARNESS_TEAM=platform
export OPENHARNESS_SERVICE=pr-review-bot
export OPENHARNESS_ENV=production

Org showback:

openharness org --last 30d

Example sections:

Spend by team
Spend by service
Spend by environment
Spend by workflow
Spend by customer
Spend by provider/model

Budget policies:

openharness budget init
openharness budget check

Then enable hard-stop enforcement in the proxy:

openharness start openai --enforce-budgets --budget-file .openharness/budgets.json

Budget config shape:

{
  "budgets": [
    {
      "name": "PR review bot monthly hard stop",
      "limit_usd": 1000,
      "period_days": 30,
      "action": "block",
      "filters": {
        "service": "pr-review-bot"
      }
    }
  ]
}

Export for finance, platform, or dashboards:

openharness export --format csv --output usage.csv
openharness export --format json --output usage.json

Command shape

OpenHarness is meant to feel like a terminal tool first:

openharness setup
openharness start openai --team platform --service pr-review-bot --env production
openharness costs --last 7d
openharness org --last 30d
openharness budget check
openharness export --format csv --output usage.csv

The longer names still work when you want them:

openharness proxy --provider openai
openharness report --days 30
openharness org-report --days 30

Python API

The Python API is still useful for apps that want explicit workflow and step labels in code.

Manual tracking:

from openharness import tracker

tracker.record(
    provider="openai",
    model="gpt-5.5",
    input_tokens=5000,
    output_tokens=1200,
    workflow="create_pr",
    step="review",
    latency_ms=4200,
    prompt_name="pr_review",
)

Workflow tracking:

from openharness import tracker

with tracker.workflow("create_feature"):
    with tracker.step("research"):
        tracker.record("anthropic", "claude-sonnet-4-6", 2000, 900)

    with tracker.step("code"):
        tracker.record("openai", "gpt-5.4-mini", 8000, 2400)

OpenAI wrapper:

from openai import OpenAI
from openharness import track_openai

client = track_openai(OpenAI())
response = client.chat.completions.create(
    model="gpt-5.5",
    messages=[{"role": "user", "content": "Review this PR"}],
)

The wrapper records model, tokens, latency, estimated cost, workflow, step, status, and errors when the SDK response exposes usage data.

CLI

openharness init
openharness record --provider openai --model gpt-5.5 --input-tokens 5000 --output-tokens 1200 --workflow pr_reviews
openharness costs --last 30d
openharness org --last 30d
openharness scan
openharness start openai --port 8787
openharness budget check
openharness export --format csv --output usage.csv
openharness pricing
openharness doctor

scan is currently an alias for reporting local OpenHarness data. A future version can inspect source trees and provider logs.

Storage

By default OpenHarness writes to:

.openharness/openharness.db

Override it with:

export OPENHARNESS_DB=/path/to/openharness.db

Pricing catalog

Costs are estimates calculated from a small built-in catalog. Prices are per 1 million tokens and were checked on 2026-06-16 against official provider docs:

Provider billing can include regional processing, priority tiers, cache storage, search grounding, images, audio, discounts, taxes, and enterprise terms. Treat OpenHarness v0.1 numbers as directional until you wire in billing exports.

Development

python -m pip install -e .
PYTHONPATH=src python -m unittest discover -s tests
python -m openharness demo --reset
python -m openharness report

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

quadrant_openharness-0.1.2.tar.gz (31.5 kB view details)

Uploaded Source

Built Distribution

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

quadrant_openharness-0.1.2-py3-none-any.whl (29.7 kB view details)

Uploaded Python 3

File details

Details for the file quadrant_openharness-0.1.2.tar.gz.

File metadata

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

File hashes

Hashes for quadrant_openharness-0.1.2.tar.gz
Algorithm Hash digest
SHA256 a5681cf59039f4b128a7cfa9fb18c3f1fe2aa36885f0baa6d7cb8a92c45d9b24
MD5 4ea6a35c250ee8c238aa71786a3f17b2
BLAKE2b-256 39b170c328d74024d6137f5647e54741dfa0397fd897071dc42ed71aca47bf2a

See more details on using hashes here.

Provenance

The following attestation bundles were made for quadrant_openharness-0.1.2.tar.gz:

Publisher: publish.yml on Quadrant-Labs/openharness

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

File details

Details for the file quadrant_openharness-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for quadrant_openharness-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 0dc7be03f1b1a4634637dc0d332dcacf6464999621667f2c93adf8d5a1c7f017
MD5 efb4e5116171d3a24138312e60bdd9e5
BLAKE2b-256 518a24a652e4892fafd4282eaa596300d81d6e942895e460beb4d1725b0db278

See more details on using hashes here.

Provenance

The following attestation bundles were made for quadrant_openharness-0.1.2-py3-none-any.whl:

Publisher: publish.yml on Quadrant-Labs/openharness

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