tea-protocol 0.1.0

Canonical protocol types for the tea-rs project
Documentation

tea-protocol

Canonical, provider-neutral protocol types for tea-rs.

The crate is intentionally limited to pure domain values and JSON serialization contracts. It does not execute models or tools, persist sessions, evaluate policy, manage asynchronous tasks, or depend on Tokio.

Status

Protocol 1.0 is implemented. The Cargo package is named tea-protocol, while Rust code imports it as tea_protocol.

Protocol surface

The crate owns four distinct contracts:

  • CommandEnvelope and AgentCommand: requested actions that a host accepts or rejects;
  • EventEnvelope and AgentEvent: observable lifecycle and streaming output;
  • RecordEnvelope and SessionRecord: required append-only facts for replay and recovery;
  • ProtocolErrorEnvelope and ProtocolError: stable machine-readable failures with safe diagnostics.

Shared types include:

  • UUIDv7 strong IDs for sessions, runs, turns, messages, tools, approvals, commands, events, records, branches, causation, and correlation;
  • decimal-string SessionSequence values for authoritative session-local ordering;
  • canonical RFC 3339 UTC millisecond timestamps;
  • user, assistant, and tool-result messages;
  • text, thinking, image, and tool-call content blocks;
  • exact decimal cost and JavaScript-safe token usage;
  • bounded reverse-domain metadata.

Example

use std::str::FromStr;

use tea_protocol::{
    AgentCommand, CommandEnvelope, CommandId, ProfileId, ProtocolMetadata,
    ProtocolTimestamp,
};

let command = CommandEnvelope::new(
    CommandId::from_str("0195a0b1-5e3b-7ef0-8ec1-0aa7aa000001")?,
    None,
    ProtocolTimestamp::from_str("2026-07-23T09:30:12.123Z")?,
    AgentCommand::CreateSession {
        profile_id: ProfileId::from_str("minimal-assistant")?,
        metadata: ProtocolMetadata::default(),
    },
)?;

let json = serde_json::to_string_pretty(&command)?;
assert!(json.contains(r#""type": "create_session""#));
# Ok::<(), Box<dyn std::error::Error>>(())

Compatibility rules

Protocol versions are independent from crate SemVer. This crate currently writes 1.0 and accepts known envelopes from protocol major version 1 when every known field remains valid.

Within the same protocol major:

  • unknown optional object fields on known types are ignored;
  • bounded namespaced metadata is preserved at documented extension points;
  • unknown commands are rejected as unsupported_command;
  • unknown durable records stop replay as unsupported_record;
  • unknown observable events are skippable only when their validated envelope explicitly declares compatibility: "skippable_observation";
  • unknown enum values are rejected unless the specific type documents preservation, such as StopReason;
  • duplicate JSON object keys are rejected recursively at public envelope and metadata boundaries.

Canonical JSON uses camelCase fields, a type discriminator, and snake_case discriminator values.

Ordering and durability

SessionSequence is the authoritative order for observable session events and durable records. UUID and timestamp ordering must not drive replay.

Events and records are intentionally different:

  • text deltas and tool progress can be transient observations;
  • final messages, approval transitions, tool execution boundaries, interruption state, branch changes, compaction provenance, and turn checkpoints are durable records;
  • every protocol 1.0 durable record kind is required for replay and cannot be skipped.

This crate defines record values only. Store append transactions, expected-sequence concurrency, reducers, projections, and SQLite persistence are supplied by tea-session and tea-session-sqlite.

Resource limits

Public constants expose the exact limits. Important defaults include:

Value Limit
Metadata namespaces 16
Encoded metadata 16 KiB
Metadata depth 8
Text/thinking block 1 MiB
Inline Base64 image 6 MiB encoded
Tool arguments 256 KiB, depth 32
Streaming delta 64 KiB
Unknown skippable event 64 KiB
Error technical message 4 KiB
Token count Number.MAX_SAFE_INTEGER

Transport adapters must additionally enforce frame and request limits before deserialization.

Security boundary

Constructors, deserialization, and serialization validate wire invariants. Public enums remain matchable by adapters, but directly constructed invalid values cannot cross the JSON boundary.

Protocol errors contain stable codes, English technical diagnostics, safe details, and optional correlation IDs. Internal causes, stack traces, credentials, authorization headers, filesystem secrets, and raw provider bodies are not serialized by default.

See the public Tea documentation for protocol compatibility and session durability guidance.