Serialization

Current .tine artifacts use format_version == 1.Run.load() rejects missing, old, or future versions with an explicit error. Migration tooling and multi-version read support are future work.

Save and Load

Run.save(path) writes a JSON artifact with a graph, refs, transcript, manifest, policy snapshot, cache provenance, and metadata. Native runs currently store policies: {} unless the caller or harness explicitly captures policy metadata.

save_load.py
1from opentine import Agent, Run
2from opentine.models.anthropic import Anthropic
3from opentine.tools.search import search
4from opentine.tools.web import fetch
5
6agent = Agent(
7    model=Anthropic("claude-sonnet-4-20250514"),
8    tools=[search, fetch],
9)
10
11run = agent.run_sync("Research distributed systems consensus algorithms")
12run.save("consensus_research.tine")
13
14loaded = Run.load("consensus_research.tine")
15print(len(loaded.steps))
16print(loaded.refs["main"])
17print(loaded.total_cost)

Integrity Metadata

Saved artifacts include metadata.integrity. The digest covers the redacted artifact body outside metadata. It is a checksum, not a signature; a user who can edit the file can also rewrite the digest.

verify.py
1from opentine import Run
2
3result = Run.verify_integrity("consensus_research.tine")
4if not result.ok:
5    raise SystemExit(result.reason)
6
7print(result.algorithm, result.actual)

Content-Addressed Step IDs

Step IDs are full SHA-256 hashes over kind, parent_ids, inputs, outputs, model/tool metadata, and errors. Timing and cost are retained as recorded facts, but they are outside the ID hash.

step_ids.py
1from opentine import StepKind, step_id
2
3sid = step_id(
4    kind=StepKind.tool,
5    parent_ids=["3b4f9b9d4fd1..."],
6    inputs={"name": "search", "arguments": {"query": "raft paxos pbft"}},
7    outputs={"result": "Search results..."},
8    model_info="claude-sonnet-4-20250514",
9    tool_info={"name": "search"},
10    error={},
11)
12
13print(sid) # full SHA-256 digest

Top-Level Fields

The v1 top-level fields are format_version, run_id,created_at, status, graph, refs, transcript, manifest, policies, cache, and metadata.

consensus_research.tine
1{
2  "format_version": 1,
3  "run_id": "consensus_research",
4  "created_at": 1775754181.234,
5  "status": "completed",
6  "graph": {
7    "steps": {
8      "3b4f9b9d4fd1...": {
9        "id": "3b4f9b9d4fd1...",
10        "parent_ids": [],
11        "kind": "think",
12        "inputs": {"text": "I should compare consensus algorithms."},
13        "outputs": {},
14        "model_info": "claude-sonnet-4-20250514",
15        "tool_info": {},
16        "error": {},
17        "timestamp": 1775754181.300,
18        "duration": 1.23,
19        "cost": 0.0012
20      },
21      "a7f3b2c1d4e5...": {
22        "id": "a7f3b2c1d4e5...",
23        "parent_ids": ["3b4f9b9d4fd1..."],
24        "kind": "tool",
25        "inputs": {"name": "search", "arguments": {"query": "Raft Paxos PBFT"}},
26        "outputs": {"result": "..."},
27        "model_info": "claude-sonnet-4-20250514",
28        "tool_info": {"name": "search"},
29        "error": {},
30        "timestamp": 1775754182.464,
31        "duration": 0.87,
32        "cost": 0.0
33      }
34    },
35    "order": ["3b4f9b9d4fd1...", "a7f3b2c1d4e5..."]
36  },
37  "refs": {
38    "main": "a7f3b2c1d4e5..."
39  },
40  "transcript": [
41    {"role": "user", "content": "Research distributed systems consensus algorithms"}
42  ],
43  "manifest": {
44    "kind": "opentine-native",
45    "resume": true,
46    "replay": ["cache", "rerun"],
47    "model": {"name": "claude-sonnet-4-20250514"},
48    "tools": ["search", "fetch"]
49  },
50  "policies": {},
51  "cache": {},
52  "metadata": {
53    "integrity": {
54      "algorithm": "sha256",
55      "digest": "7d42b8a91c0f..."
56    }
57  }
58}

Inspecting Steps

Run.steps is a traversal view over graph.order. Direct graph access is available through run.graph.steps.

inspect.py
1from opentine import Run
2
3run = Run.load("consensus_research.tine")
4
5for step in run.steps:
6    print(f"ID:      {step.id}")
7    print(f"Parents: {step.parent_ids}")
8    print(f"Kind:    {step.kind.value}")
9    print(f"Inputs:  {step.inputs}")
10    print(f"Outputs: {step.outputs}")
11    print()

Design Notes

  • Graph storage: Steps are stored under graph.steps by full ID, with graph.order for stable traversal.
  • Refs: Named tips such as main and fork_point keep branch metadata out of step payloads.
  • Policies: The top-level policies field is reserved for captured policy metadata. The native runtime does not automatically serialize active policy objects today.
  • Redaction: Common secret-bearing keys are redacted before saving.
  • Compatibility: v1 is the active compatibility promise for the 0.1.x beta.