Skip to main content

opsen

Run your agents. Know what each one cost.

You point a session at a task ID; we run it, meter it, and tell you what that task cost across compute and tokens together. Your agent code does not change — not one line, not one import.


Quickstart

pip install opsen
from opsen import Client

c = Client(api_key=os.environ["OPSEN_KEY"])

with c.session("job_8812", labels={"customer": "acme"}, budget_usd=2.00) as s:
    s.fs.write("agent.py", open("agent.py").read())
    s.exec("python3 agent.py")
    print(s.cost())
Cost(total=$0.019806 compute=$0.000006 tokens=$0.019800 calls=3)

agent.py is unmodified. Its Anthropic or OpenAI client picks up a base URL we inject into the session, so every model call is attributed without you instrumenting anything.

The query most people actually came for:

c.costs(group_by="labels.customer")
# [{"labels.customer": "acme", "total_usd": 412.55, "tasks": 1104}, ...]

Label sessions with whatever your business is organised by — customer, tenant, workflow, feature — and group on it. We do not model your business; you attach the labels and we join on them.


What you don't have to do

Manage session lifecycle. TTL is mandatory and enforced. Idle sessions suspend and resume transparently. Orphans are reaped. Wedged sessions are detectable (c.stuck_sessions()) rather than something you discover on an invoice.

Instrument your agent. No wrapper, no callback, no SDK inside the sandbox.

Hold provider keys in the sandbox. See below — this is the part worth reading even if you skip the rest.


Credentials

Register your provider key once:

k = c.add_provider_key("anthropic", "sk-ant-...")
s = c.session("job_1", provider_key_id=k["id"])

The key is sealed at rest and never enters the sandbox. Your agent gets a session token instead: scoped to one session, capped by that session's budget, dead when the session ends, revocable, useless anywhere else.

The token arrives as ANTHROPIC_API_KEY (and the OpenAI and Google equivalents) alongside a base URL, so your agent's SDK sends it the way it sends any API key and nothing in your code changes. It is a credential, so it travels in a header rather than the URL — a token in a path ends up in every access log and proxy record between you and us, and rotating it would mean rotating a URL you have embedded.

This matters because agent code is not trustworthy code. A prompt injection or a bad dependency that exfiltrates a provider key gets a credential with no spending limit and no expiry, usable from anywhere, against every project on your account. The same attack against a session token gets the remaining budget on one session.

Inbound credential headers from the sandbox are stripped, so an agent cannot route around metering by supplying its own key.


Budgets

s = c.session("job_1", budget_usd=2.00)

Enforced at the model call, not reported afterwards. When the cap would be breached the call returns 402 and the session is terminated.

One honest limitation. The cap is a pre-flight estimate. Output is bounded exactly by max_tokens; input is not — we can only see the request body, and the provider also counts system prompts, tool schemas and cache blocks that never reach us. We start pessimistic and calibrate against what the provider actually reports for your traffic. In practice this lands a few percent under the cap. It is not a guarantee that you will never exceed a budget by a cent; it is a guarantee that a runaway agent stops.

While a budgeted session is still calibrating, its first call runs alone and concurrent calls get 429 with budget_calibrating. You cannot bound N calls whose individual cost you cannot yet bound.

Tenant-level ceilings — spend per window, concurrent sessions, requests per minute — bound the account rather than the session, so a leaked API key cannot mint unlimited budgeted sessions.


Errors, and why the distinction matters

A 429 from us and a 429 from your model provider need opposite responses. Ours means slow down or raise a limit. Theirs means retry with backoff. Every response carries x-opsen-error-source, and the SDK turns it into types:

Exception Cause Retry?
BudgetExceeded your session cap Never. Retrying a cost control is how it becomes a cost leak
SessionGone terminated, expired, reaped No — start a new session
TenantLimited our ceiling Only if .retryable — true for rate, false for spend
ProviderError the model provider failed Yes, with backoff
try:
    result = s.call_model(payload)
except BudgetExceeded as e:
    alert(f"job {s.task_id} hit its cap at ${e.body['would_reach_usd']}")
except TenantLimited as e:
    if e.retryable: ...

call_model implements these rules already, including honouring retry-after and jittering backoff. Most callers never touch it — your agent's own SDK goes through the injected base URL — but it exists so the rules are written down somewhere executable.

Failed calls are never billed and are reported separately as failed_calls, so your cost-per-call has the right denominator.


One worker, many jobs

A long-lived worker can be re-pointed. Cost stays with the job that incurred it:

w = c.session("job_A")
w.exec("python3 worker.py")
w.retag("job_B")
w.exec("python3 worker.py")

c.task_cost("job_A")   # only job_A's compute and tokens
c.task_cost("job_B")

Idle suspension

Agents spend most of their wall clock waiting on model responses, and billing that as active compute is the default failure of every full-duration provider. We suspend on idle and resume transparently.

Resuming costs roughly 180 ms on the next call, so this is a trade rather than a free win. Named policies, because the right answer depends on how you value latency:

policy idle window for
interactive (default) 15 min user-facing agents where resume latency shows
balanced 3 min
batch 30 s long-idle background work
never —

The default is conservative on purpose. At 2 vCPU / 4 GiB, suspending over a two-minute idle window saves about half a cent and costs 180 ms of first-token time — a bad trade for anything a human is waiting on.


What happens if opsen is down

Your model calls go through our gateway, so this is a fair question to ask before you route production traffic through anyone. The answer depends on whether you asked for a cost guarantee.

No budget set — we fail open. The call is forwarded and served. Usage for that window may not be recorded, and the response carries x-opsen-degraded: accounting so a client that cares can buffer and reconcile. You never asked us to guard anything, so we do not stand in the way.

Budget set — we fail closed. The call is refused with 503 cost_control_unavailable rather than made without the cap you asked for.

That second one is deliberate and it is the less convenient choice, so here is the reasoning. Outages correlate with runaway spend — provider degradation, retry storms, agents looping on errors are the same conditions that break us and the same ones that empty a budget. A cap that disappears exactly when it is needed is not a cap. And the security model depends on it: your sandbox holds a session token instead of your provider key precisely BECAUSE the token is bounded by the cap. Failing open would quietly hand back an unbounded credential.

So: set a budget on sessions where a wrong number costs you more than a paused minute, and leave it unset where availability matters more. You choose per session, and the behaviour is the same whether we are healthy or not.


Runtimes

runtime="auto" picks a backend. You can pin one. Nothing else about the backend is visible through the API, which is deliberate: the same code runs against any of them, and you are not writing against a particular provider's semantics.

Metadata

Release files for opsen 0.1.6

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

Source distribution (sdist)

Source distribution for opsen 0.1.6
File Size Uploaded Provenance
opsen-0.1.6.tar.gz 13.4 kB With provenance Details

Built distribution (wheel)

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

Total release size: 26.8 kB

Release files / opsen-0.1.6.tar.gz

Download URL opsen-0.1.6.tar.gz
Size 13.4 kB
Tags Source
SHA-256 checksum
How to use checksums
5a3b131c35298a4fead3c6e9da8e83bd905287af1ba8ac07e1d490218b9ea9fe
BLAKE2b-256 checksum
How to use checksums
48abfb34c74d31a37635d3ba4dfaf958798b0ae6402df1b075f3d054e7347e8a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 8, 2026.

Transparency log

Release files / opsen-0.1.6-py3-none-any.whl

Download URL opsen-0.1.6-py3-none-any.whl
Size 13.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b127c4a168a64582c2719792e30268b7f6c0fba9528395acf26c62552ec969db
BLAKE2b-256 checksum
How to use checksums
ee9687281aca447d8254bcb4a03b1f30ccfed7126e4efd3daa29e8a2b8895dfe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 8, 2026.

Transparency log

Security for opsen 0.1.6

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for opsen-0.1.6.tar.gz

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 Sep 8, 2026.

Transparency log

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