Docs target current release v0.7.0.v0.7.1 is under review

Steps

A Step is one recorded node in a run graph. Native agents use five kinds: thinking text, tool calls, model-facing work, successful completion, and errors.

step_kinds.py
from opentine import StepKind

StepKind.think
StepKind.tool
StepKind.model
StepKind.done
StepKind.error

Create steps through Run

Run.add_step() resolves parent references, computes the content address, records the timestamp, and appends the step to stable traversal order.

steps.py
1from opentine import Run, StepKind
2
3run = Run(id="research-01")
4
5step = run.add_step(
6    kind=StepKind.tool,
7    inputs={"name": "fetch", "arguments": {"url": "https://example.com"}},
8    outputs={"result": "Example Domain"},
9    tool_info={"name": "fetch"},
10    duration=0.8,
11    cost=0.0,
12    usage={"input": 0, "output": 0},
13)
14
15print(step.id)        # full 64-character SHA-256 hex digest
16print(step.short_id)  # first 12 characters, for display
17print(step.parent_ids)

Recorded fields

A portable v2 step records its full ID, parent_ids, kind, inputs, outputs, model and tool metadata, error data, timestamp, duration, cost, and input/output usage. parent_id remains a compatibility view of the last parent.

What the ID covers

The ID is a full SHA-256 hash of the canonical step kind, parent links, inputs, outputs, model metadata, tool metadata, and error data. Timestamp, duration, cost, and usage are recorded but excluded from identity. That distinction lets a diff report cost or usage drift even when two steps have the same ID.

step_identity.py
1from opentine import StepKind, step_id
2
3sid = step_id(
4    StepKind.tool,
5    {"name": "fetch", "arguments": {"url": "https://example.com"}},
6    parent_id="<full-parent-step-id>",
7    outputs={"result": "Example Domain"},
8    tool_info={"name": "fetch"},
9)
10
11assert len(sid) == 64

Immutability boundary

Step is a frozen dataclass, so its fields cannot be reassigned. Treat the nested dictionaries as immutable after creation as well; Python does not deep-freeze those containers.

V3 events

Repository recordings normalize activity into model, tool, human, policy, approval, subagent, and error events. V3 object IDs bind the object type, schema version, and canonical stored bytes after redaction. They are not interchangeable with v2 step IDs.