Forking
Forking copies the ancestor graph up to a selected step and starts a new run from that fork point. The copied steps keep their original IDs because they are the same content-addressed records.
How Forking Works
Run.fork(from_step_id) resolves the step ref, walks ancestors root-first, builds a new graph containing those steps, sets refs.mainand refs.fork_point to the selected step, and records metadata.forked_from.
1from opentine import Run, StepKind
2
3run = Run(id="original", model_info="claude-sonnet-4-20250514")
4
5search_step = run.add_step(StepKind.think, {"text": "Search for papers"})
6tool_step = run.add_step(
7 StepKind.tool,
8 {"name": "search", "arguments": {"query": "RLHF"}},
9 outputs={"results": ["paper_a"]},
10 parent_ids=[search_step.id],
11)
12summary_step = run.add_step(
13 StepKind.done,
14 {"text": "Summary..."},
15 outputs={"text": "Summary..."},
16 parent_ids=[tool_step.id],
17)
18bad = run.add_step(
19 StepKind.error,
20 {"text": "Fetch failed"},
21 error={"type": "HTTPError", "message": "404"},
22 parent_ids=[summary_step.id],
23)
24
25forked = run.fork(summary_step.id, new_run_id="retry-01")
26forked.save("retry-01.tine")
What the Fork Contains
The fork contains the selected step and its ancestors. Descendants after the fork point and unrelated sibling branches are excluded.
print([step.short_id for step in forked.steps])
print(forked.status.value) # "running"
print(forked.refs["main"] == summary_step.id) # True
print(forked.refs["fork_point"]) # full fork-point step ID
print(forked.metadata["forked_from"]) # original run IDCLI Workflow
Step refs can be numeric traversal indexes, full IDs, or unique ID prefixes.
tine show failed.tine
tine fork failed.tine --from-step 2 --save retry.tine
tine fork failed.tine --from-step 6d4a0b270a5f --save retry-by-prefix.tine
tine diff failed.tine retry.tineFork Into a Harness
The CLI can pass fork context into an external harness when you specify a harness and prompt. The harness run is still a new recorded graph.
tine fork failed.tine \
--from-step 2 \
--harness codex \
--prompt "Retry from this context with a narrower search." \
--save retry_codex.tineContinue With a Native Agent
For native opentine agents, use agent.resume_sync() or the async agent.resume() API to continue from a forked run.
1from opentine import Agent, Run
2from opentine.models.anthropic import Anthropic
3
4source = Run.load("failed.tine")
5forked = source.fork("6d4a0b270a5f")
6
7agent = Agent(model=Anthropic("claude-sonnet-4-20250514"))
8resumed = agent.resume_sync(
9 forked,
10 prompt="Retry with a narrower source set and cite each claim.",
11)
12resumed.save("retry_completed.tine")
Cost and Provenance
Forking does not re-execute the retained steps. It gives you a precise provenance boundary: everything before the fork point is the same recorded work, and everything after it belongs to the new branch.