← All lessons/Foundations
5
Foundations

Writing Records in Depth

Every write option: JSON write, batch write, TTL, and the internal write path.

Prerequisite: Lesson 4 complete

What you'll learn

  • Basic JSON write with POST /v1/agents/:id/write
  • Write with ttl_ms — automatic expiry via _expires_at_ms
  • Batch write with POST /v1/agents/:id/write/batch
  • GroupCommitter — one fsync per batch
  • Write path: JSON → MsgPack → AES-GCM → BLAKE3 → Ed25519 → WAL → segment
Challenge

Write a 'user upgrade' event (user_id, from_plan, to_plan). Then batch-write 5 page_view events.

Interactive Walkthrough

What you'll learn

Every write option: JSON write, raw MessagePack write, batch write, TTL, and what the write path looks like internally.

Basic JSON write

curl -s -X POST http://localhost:7475/v1/agents/users/write \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer spx_root_YOUR_ROOT_KEY" \
  -d '{
    "payload": {
      "type": "user_signup",
      "user_id": "usr_001",
      "email": "bob@example.com",
      "plan": "starter",
      "source": "landing_page"
    }
  }' | python3 -m json.tool

Write with a TTL

Records expire after ttl_ms milliseconds. An internal sweeper tombstones them automatically.

# This record expires in 1 hour (3,600,000 ms)
curl -s -X POST http://localhost:7475/v1/agents/sessions/write \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer spx_root_YOUR_ROOT_KEY" \
  -d '{
    "payload": {"session_token": "tok_xyz", "user_id": "usr_001"},
    "ttl_ms": 3600000
  }' | python3 -m json.tool

The engine injects _expires_at_ms into the payload before storing. The TTL sweeper runs every 60 seconds and tombstones expired records.

Batch write

curl -s -X POST http://localhost:7475/v1/agents/events/write/batch \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer spx_root_YOUR_ROOT_KEY" \
  -d '{
    "records": [
      {"payload": {"event": "page_view", "page": "/pricing", "user": "usr_001"}},
      {"payload": {"event": "button_click", "button": "start_trial", "user": "usr_001"}},
      {"payload": {"event": "form_submit", "form": "trial_signup", "user": "usr_001"}}
    ]
  }' | python3 -m json.tool

Batch writes are coalesced by the GroupCommitter — all records in one batch share a single fsync, giving much higher throughput than individual writes.

Write response fields

FieldMeaning
content_hashPermanent address of this record
parent_hashThe record this chains from
sequence1-based integer position in the strand
ts_hlcHLC timestamp of this record

The write path (internals)

  1. JSON payload → MessagePack encode
  2. AES-256-GCM encrypt (key derived from SAPIX_MASTER_SEED + agent_id via HKDF)
  3. Compute content_hash = BLAKE3(parent_hash ‖ ts_hlc ‖ flags ‖ encrypted_payload)
  4. Sign content_hash with agent's Ed25519 key
  5. Append to WAL (plaintext for crash recovery)
  6. GroupCommitter fsync
  7. Move to encrypted segment file

Challenge

Write a "user upgrade" event with these fields: user_id, from_plan, to_plan, upgraded_at. Then write a batch of 5 page_view events for that user.

---

← Previous
Lesson 4: Organisms and Agents
Next →
Lesson 6: Reading Records in Depth