← Back to blog

opentine v0.3.0: git-shaped provenance for agent runs

0xcircuitbreaker··8 min read

opentine 0.3.0 gives agent runs a Git-shaped repository without abandoning the portable artifact that came first.

Portable *.tine files remain format v2. The new .tine/ repository is a separate verified v3 object model for teams that need durable history, semantic operations, synchronization, and policy seams around many runs.

That distinction is the release.

A note about 0.2.1

Provider-neutral usage and billing were developed under version 0.2.1, but 0.2.1 was never tagged or published to PyPI. Those changes were folded into 0.3.0, which is the first public release that contains them.

There is no 0.2.1 artifact to install or document as a public release. Upgrade directly to 0.3.0:

python -m pip install --upgrade "opentine==0.3.0"
python -c "import opentine; print(opentine.__version__)"
tine pricing check

Version 0.3 supports Python 3.11 through 3.14. The cryptography package is now a core dependency, so Ed25519 signing, signed pricing catalogs, and the encrypted reference remote work with a plain pip install opentine. The crypto extra remains only as a compatibility alias for older installation instructions.

Two formats, two jobs

A .tine file is still the portable compatibility artifact:

run.save("result.tine")

It remains format v2. A 0.3 reader loads v1 and v2, migrates v1 in memory, and writes v2 when an older artifact is re-saved.

A .tine/ repository stores immutable v3 objects:

  • blob for prompts, outputs, patches, tool results, artifacts, and manifests
  • event for model, tool, human, policy, approval, error, and subagent activity
  • run for the event graph and the manifests that governed it
  • attestation for evaluations, approvals, signatures, and provenance claims
  • annotation for separately versioned metadata

Object IDs bind the object type, schema version, and canonical stored bytes. Redaction happens before canonicalization and hashing. Refs update with compare-and-swap semantics, and fsck recomputes identities and validates typed links, refs, shallow boundaries, and event cycles.

tine init .
tine migrate-v3 result.tine --repo . --ref heads/imported
tine fsck --repo .
tine repo-log heads/imported --repo .

Migrating into a repository is optional; existing v2 files continue to work. The v2-to-v3 migrator is strict by default. It retains the exact source artifact as a legacy blob, records the original integrity and signature result, builds newly redacted v3 objects, and stores a deterministic ID map.

A legacy signature authenticates only that byte-exact legacy blob. It is never presented as a signature over the newly generated v3 objects. Because the preserved blob is not redacted, review it for secrets before pushing the repository. --allow-unverified exists as an explicit recovery path, not a default.

Semantic repository operations

The repository is shaped around agent behavior rather than transcript line merging.

It can search and inspect runs, select the minimal causal context for an event, compare two runs semantically, fork from the last useful event, resume work, attach evaluations or approvals, and promote a run through a ref update.

tine object run:sha256:... --repo . --resolve-blobs
tine pack --repo . --output run.pack
tine fetch https://runs.example --tenant team --repo .
tine push https://runs.example --tenant team --repo .

Semantic diff reports common and divergent events alongside cost, latency, tool path, artifacts, usage, billing, and evaluation scores. It compares run graphs; it does not pretend that agent transcripts should be line-merged.

Current models without guessed prices

The native examples now use current model IDs:

from opentine.models.anthropic import Anthropic
from opentine.models.google import Google
from opentine.models.ollama import Ollama
from opentine.models.openai import OpenAI

OpenAI("gpt-5.6")
Anthropic("claude-sonnet-5")
Google("gemini-3.5-flash")
Ollama("qwen3")

Provider-scoped Chat Completions adapters cover Kimi/Moonshot, DeepSeek, GLM/Z.AI, Grok/xAI, Groq, Qwen, Together, Mistral/Ministral, OpenRouter, and direct Nous/Hermes. Named local presets cover LM Studio, vLLM, Unsloth, llama.cpp, LocalAI, Jan, SGLang, TGI, MLX-LM, NVIDIA NIM, TensorRT-LLM, KoboldCpp, and LiteLLM.

Model transport is not a pricing allowlist. A provider can accept a model identifier that is newer than opentine's bundled catalog. That model remains runnable, but its billing state is visibly unknown until an exact card or local overlay supplies the rate. Local runtimes are unmetered by default unless infrastructure rates are provided.

Every built-in adapter returns compatible text, tool-call, and known-subtotal fields plus normalized usage and explicit billing metadata. Billing distinguishes:

  • complete when every observed dimension has a pinned rate
  • partial when a known subtotal exists but something remains unpriced
  • unknown when no exact price can be determined
  • unmetered when a local API has no API charge

Calculations use Decimal arithmetic, effective dates, cache and reasoning dimensions, context thresholds, and service-tier rules. Inference never performs a live price lookup.

tine pricing list --provider kimi
tine pricing show openai gpt-5.6
tine pricing check

The signed snapshot covers current families including GPT-5.6, Claude Sonnet 5, Kimi K3, DeepSeek V4, Gemini 3.5 Flash, Grok 4.5, GLM-5.2, Qwen 3.7, and current Mistral/Ministral models. Budget(strict_cost=True) can stop before another model call once billing becomes indeterminate.

Record what already runs

Recorder captures code state, the dirty patch, environment, policy, budget, and pricing manifests, then appends immutable model, tool, human, policy, approval, subagent, and error events.

Importers normalize native opentine traces, JSONL, OpenTelemetry GenAI spans, and complete OTLP/JSON exports. Framework importers best-effort normalize common serialized records from LangChain, LlamaIndex, AutoGen, CrewAI, and OpenAI Agents.

The CLI can also record external agent harnesses:

tine run --harness codex --prompt "Inspect this repository" --save run.tine
tine run --harness gemini --prompt "Explain the failing test" --save run.tine
tine run --harness grok --prompt "Review this patch" --save run.tine

Built-in profiles also include Claude Code, Cursor, Hermes, Kimi Code, OpenClaw, OpenCode, Pi, and an explicit generic command.

Give agents repository tools without handing over the release gate

Inside a repository, the MCP integration can expose search, verified inspection, causal context, semantic diff, fork and resume, evaluation, and attestation.

Promotion is deliberately different. It is not enabled by the shipped MCP server, and custom hosts must opt in. MCP fork and resume operations may write only experiments/*; mainline, promotion, tag, and remote-tracking refs remain operator-controlled.

An attestation is also a claim, not automatically a cryptographic identity. Its signer label is self-asserted unless the caller attaches and independently verifies a signature.

A self-hosted remote foundation

The minimal HTTP remote provides capability discovery, missing-object negotiation, filtered and shallow fetch, bounded pack downloads, resumable uploads, and compare-and-swap ref updates.

The reference backend adds tenant namespaces, reader/writer/admin authorization, encrypted filesystem objects, SQLite metadata, and hash-chained audit records with an authenticated head outside SQLite. OIDC/JWKS verification and pluggable storage, index, identity, authorization, key, audit, retention, and admission interfaces provide the extension seams for a production deployment.

The boundary matters: the bundled WSGI server is for development and small self-hosted installations. It is not a turnkey high-availability service, hosted control plane, or payment product. Static bearer tokens are for development; operators remain responsible for TLS, KMS and identity configuration, backups, retention, rate limiting, and host hardening.

Call this an enterprise repository foundation, not a finished enterprise SaaS.

Upgrade without erasing the old workflow

If portable artifacts are enough, upgrade the package and keep using them:

python -m pip install --upgrade "opentine==0.3.0"
tine verify result.tine
tine cost result.tine

Adopt a repository when the extra semantics are useful:

tine init .
tine migrate-v3 result.tine --repo . --ref heads/main
tine fsck --repo .

Use tine migrate for legacy-file-to-v2 migration. Use tine migrate-v3 for importing a v2 artifact into a repository. They are intentionally different operations.

OpenTine still starts with the same premise: every run is an artifact. Version 0.3 adds the repository needed to preserve, verify, search, branch, evaluate, and synchronize those artifacts as a body of work.

Install opentine 0.3.0 from PyPI, read the tagged README, review the complete 0.3.0 changelog, and use the tagged format, repository, pricing, and security references for implementation details.