Git for agent runs. Fork, replay, resume any execution. ~250 lines core. Any model.
Project description
opentine
Git for agent runs. Fork, replay, resume any execution.
~250 lines of core. Any model. Zero lock-in.
A tine is the prong of a fork. opentine literally forks your agent runs.
Every agent execution becomes a run tree — content-addressed, serializable, forkable. Pause on your laptop, resume on a server. Branch from step 7 with a different prompt. Diff two runs side by side. All in ~250 lines of core.
Quickstart
pip install opentine
Write a 5-line agent:
from opentine import Agent
from opentine.models.anthropic import Anthropic
agent = Agent(model=Anthropic("claude-sonnet-4-20250514"))
run = agent.run_sync("What is opentine?")
run.save("result.tine")
See what happened:
tine show result.tine
# fe3a767307a4 model=claude-sonnet-4-20250514 steps=1 cost=$0.0006 completed
└── + done "A tine is one of the pointed prongs or spikes that extend from
the head of a fork..."
Real Demo Output
Here's demo_research.py running a research agent with search + web tools:
$ python examples/demo_research.py
Detected Anthropic (claude-sonnet-4-20250514) via ANTHROPIC_API_KEY
Researching: What is opentine?
=== Run Tree ===
0. [think] I'll search for information about "opentine"...
1. [tool] search(query='opentine developer tool')
2. [think] Let me try a more specific search...
3. [tool] search(query='"opentine" software tool')
4. [think] Found the website, let me fetch it...
5. [tool] fetch(url='https://opentine.com/')
6. [done] (see answer below)
=== Answer ===
Opentine is an open-source Python framework that provides "Git for agent
runs" — a version control system for AI agent executions. It's ~250 lines
of core code that lets developers track, debug, and manage AI agent
workflows.
- Creates forkable run trees: every step is content-addressed and immutable
- Enables debugging and replay: fork from any step, modify, resume
- Model agnostic: works with Claude, GPT, Gemini, Llama, and more
- Cost savings: cached steps mean you don't burn tokens re-executing
=== Run Info ===
Model: claude-sonnet-4-20250514
Steps: 7
Cost: $0.0320
Status: completed
Saved: demo_research.tine
The demo auto-detects whichever API key you have set. Works with any provider.
The Killer Demo
Your agent fails after 10 steps. Instead of re-running everything:
# See where it went wrong
tine show failed_run.tine
# Fork from step 3, before the bad tool call
tine fork failed_run.tine --from-step 3 --save fixed_run.tine
# Compare the runs
tine diff failed_run.tine fixed_run.tine
Three commands. No re-running the first 3 steps. No lost context. No wasted API calls.
Why opentine?
| Install size | Forkable runs | Any model | Core LOC | |
|---|---|---|---|---|
| LangChain | 166 MB | No | Partial | ~200k |
| LangGraph | 51 MB | Checkpoints only | Partial | ~50k |
| CrewAI | 173 MB | No | Partial | ~30k |
| smolagents | 198 MB | No | Partial | ~15k |
| opentine | <5 MB | Yes | Yes | ~250 |
How It Works
Every agent execution produces a run tree: a content-addressed DAG of steps.
graph TD
A["◆ run_a3f8"] --> B["● think"]
A --> C["▶ tool: search"]
C --> D["● think"]
D --> E["▶ tool: read_url"]
E --> F["✔ done"]
A --> |"fork from C"| G["◆ run_b7c1 (forked)"]
G --> H["▶ tool: search (different query)"]
H --> I["● think"]
I --> J["✔ done"]
style A fill:#FF6900,color:#fff
style G fill:#FF6900,color:#fff
Each step is hashed from its inputs — identical inputs always produce the same step ID. This means:
- Fork = copy the tree up to a point, then diverge
- Replay = re-execute from a step, compare outputs
- Diff = walk two trees, highlight where they diverge
- Pause/Resume = serialize the tree + pending state to a
.tinefile
Model Support
opentine treats every model equally. No first-class provider. Swap with one line.
from opentine.models.anthropic import Anthropic
from opentine.models.openai import OpenAI
from opentine.models.google import Google
from opentine.models.ollama import Ollama
# Same agent, different brain
agent = Agent(model=Anthropic("claude-sonnet-4-20250514"))
agent = Agent(model=OpenAI("gpt-4o"))
agent = Agent(model=Google("gemini-2.0-flash"))
agent = Agent(model=Ollama("llama3.1"))
Any OpenAI-compatible provider works out of the box:
from opentine.models.compat import Kimi, DeepSeek, Qwen, GLM, Groq, Together, Mistral
agent = Agent(model=Kimi("moonshot-v1-8k"))
agent = Agent(model=DeepSeek("deepseek-chat"))
agent = Agent(model=Qwen("qwen-plus"))
agent = Agent(model=GLM("glm-4-flash"))
agent = Agent(model=Groq("llama-3.1-70b-versatile"))
agent = Agent(model=Together("meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo"))
agent = Agent(model=Mistral("mistral-large-latest"))
Built-in Tools
from opentine.tools import web, search, fs, shell, python
agent = Agent(
model=Anthropic("claude-sonnet-4-20250514"),
tools=[web.fetch, search.search, fs.read, fs.write, shell.run],
)
Tools are plain Python functions with type hints. No decorators, no schemas, no framework. opentine introspects the signature.
CLI Reference
tine run <script.py> Execute agent, stream steps, save run tree
tine ls List recent runs (status, cost, model)
tine show <run_id> Pretty-print the tree (like git log --graph)
tine replay <id> [--from N] Replay from a step
tine fork <id> --from-step N Branch a new run
tine diff <run_a> <run_b> Side-by-side comparison
tine resume <run_id> Resume a paused run
The Name
A tine is a prong of a fork.
opentine is an open-source tool that forks your agent runs — branching execution trees the way git branches code. The .tine file extension stores serialized run trees, and the tine CLI is the command you type.
Contributing
We welcome contributions. Please open an issue or PR.
git clone https://github.com/0xcircuitbreaker/opentine.git
cd opentine
uv sync --all-extras
uv run pytest
uv run ruff check .
License
Apache 2.0 — see LICENSE.
Built by the opentine contributors.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file opentine-0.1.0.tar.gz.
File metadata
- Download URL: opentine-0.1.0.tar.gz
- Upload date:
- Size: 35.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d0203268ff9f909b3a3ed142d4c7f8b454892530195fd720a9a6c5dfe32762c9
|
|
| MD5 |
d5268d2e938b548b1790e2bc9395df9f
|
|
| BLAKE2b-256 |
69b75816fc3a849c94a23ce74e2936afc9ab5ad0f888100ba289dad921040f52
|
File details
Details for the file opentine-0.1.0-py3-none-any.whl.
File metadata
- Download URL: opentine-0.1.0-py3-none-any.whl
- Upload date:
- Size: 27.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2126d08c294e884336ec0de755d3c8b6a1b82f7704e98013c270b229c346a866
|
|
| MD5 |
2bef6f3f266f161fde2f4f71e73f5a47
|
|
| BLAKE2b-256 |
3c5c594a92db16dcc7bf67f0c614ae8499cb0d31b0c7e9e60bddb9c2978f9e9d
|