Stream attributes

Stream attributes are mutable, application-owned JSON metadata stored beside a stream. They are not part of the append-only byte stream and do not affect offsets, reads, snapshots, bootstrap, content type, or closed state.

The protocol details are defined in the extensions spec.

bucketpathstringrequired

Bucket ID.

streampathstringrequired

Stream ID within the bucket.

Attribute object

{
  "title": "Support session",
  "metadata": {
    "purpose": "customer-support",
    "environment_id": "env_019e2590d33f711fabf42f2857cecd8a",
    "agent": {
      "id": "agent_019e390add9f7bac9b6cc806db46fcbd",
      "version": 2
    }
  }
}

Top-level fields are optional:

FieldTypeDescription
titlestringApplication-defined display title.
metadataobjectArbitrary application metadata.

Ursula does not define top-level fields for application concepts such as agents or environments. Store that data inside metadata when needed.

Unknown top-level fields are ignored and not stored. Place any additional fields inside metadata.

The encoded attribute object is limited to 16 KiB. Larger documents are rejected with 400 Bad Request.

Read attributes

GET /{bucket}/{stream}/attrs
StatusMeaning
200Attributes returned as application/json.
404Stream not found or expired.
410Stream is gone.

When no attributes are set, the response body is {}.

Replace attributes

PUT /{bucket}/{stream}/attrs
Content-Type: application/json

{"title":"Renamed session","metadata":{"purpose":"debugging"}}

PUT replaces the complete attribute object. It does not merge with the previous value. Submitting {} clears attributes.

StatusMeaning
204Attributes replaced, cleared, or already equal to the request.
400Missing Content-Type, non-JSON content type, invalid JSON, or attributes over the 16 KiB limit.
404Stream not found or expired.
410Stream is gone.

Attributes can be updated after a stream is closed. Stream closure only prevents further appends.

Create with attributes

You can set initial attributes on stream creation with the Stream-Attrs header:

curl -X PUT http://127.0.0.1:4437/demo/session-1 \
  -H 'Stream-Attrs: {"title":"Support session","metadata":{"purpose":"customer-support"}}'

If the stream already exists, the submitted attributes must match the stored attributes for the create request to return 200 OK. A mismatch returns 409 Conflict.

curl http://127.0.0.1:4437/demo/session-1/attrs
curl -X PUT http://127.0.0.1:4437/demo/session-1/attrs \
  -H 'Content-Type: application/json' \
  --data-binary '{"title":"Renamed session","metadata":{"purpose":"debugging"}}'
curl -X PUT http://127.0.0.1:4437/demo/session-1/attrs \
  -H 'Content-Type: application/json' \
  --data-binary '{}'