Run graphs
A portable v2 run stores a content-addressed directed acyclic graph. Run.steps is its stable ordered view; graph.steps, parent_ids, and named refs retain the graph structure.
1from opentine import Run, StepKind
2
3run = Run(
4 id="research-01",
5 model_info="claude-sonnet-5",
6 user_prompt="Find recent papers on RLHF",
7)
8
9plan = run.add_step(
10 StepKind.think,
11 {"text": "Search, inspect sources, then summarize."},
12)
13search = run.add_step(
14 StepKind.tool,
15 {"name": "search", "arguments": {"query": "RLHF papers 2025"}},
16 outputs={"result": "..."},
17 parent_id=plan.id,
18 tool_info={"name": "search"},
19)
20done = run.add_step(
21 StepKind.done,
22 {"text": "Summary complete."},
23 parent_id=search.id,
24 cost=0.003,
25 usage={"input": 800, "output": 220},
26)
27
28print(run.total_cost)
29print(run.total_duration)
30print(run.total_tokens)
Navigate
Use root, child, ancestor, and lookup helpers rather than assuming the artifact is one flat chain.
1roots = run.root_steps()
2children = run.children(plan.id)
3
4# Ordered root-to-target, including the requested step.
5lineage = run.ancestors(done.id)
6
7# Full IDs and unique prefixes both resolve.
8same_step = run.get_step(done.short_id)
Branching
A parent may have multiple children. A step can also carry multiple parent_ids, which is why the serialized primitive is a DAG even though simple agent runs often look like a tree.
1left = run.add_step(
2 StepKind.tool,
3 {"name": "search", "arguments": {"query": "RLHF"}},
4 parent_id=plan.id,
5)
6right = run.add_step(
7 StepKind.tool,
8 {"name": "fetch", "arguments": {"url": "https://example.com"}},
9 parent_id=plan.id,
10)
11
12assert run.children(plan.id) == [left, right]
Run state
Runs track running, paused, completed, or failed status alongside transcript, cache, manifest, policies, metadata, and tags. Aggregate cost, duration, and token usage are methods computed from recorded steps.
Repository runs
A v3 repository represents execution with immutable event and run objects plus typed parent and causal links. Its IDs and operations are separate from portable v2 step IDs. See repository v3.