Documentation Index Fetch the complete documentation index at: https://mintlify.com/Neumenon/glyph/llms.txt
Use this file to discover all available pages before exploring further.
Overview
GLYPH patches enable efficient incremental updates to structured state. Instead of sending the entire state document after each change, send only the operations that transform one state to another.
Why Patches?
Token Efficiency Send O(1) operations instead of O(n) full state
Base Hash Verification Cryptographic proof you’re updating the correct version
Optimistic Concurrency Detect and reject conflicting updates
Audit Trail Log operations for debugging and replay
Patch Operations
GLYPH supports four core patch operations:
Operator Name Purpose Example =Set Replace a value = score 95+Append Add to list/map + items {id=3 name=widget}~Increment Add to number ~ count 1-Delete Remove key/index - items[0]
Set Operation (=)
Replace a field value completely.
# Before
{score=90 status=pending}
# Patch
= score 95
= status=complete
# After
{score=95 status=complete}
import glyph
# Create patch
patch = glyph.patch([
( "=" , "score" , 95 ),
( "=" , "status" , "complete" ),
])
# Apply to state
state = { "score" : 90 , "status" : "pending" }
new_state = glyph.apply_patch(state, patch)
# {"score": 95, "status": "complete"}
Append Operation (+)
Add an element to a list or a key-value pair to a map.
# Before
{items=[{id=1 name=foo} {id=2 name=bar}]}
# Patch
+ items {id=3 name=baz}
# After
{items=[{id=1 name=foo} {id=2 name=bar} {id=3 name=baz}]}
import glyph
# Append to list
patch = glyph.patch([
( "+" , "items" , { "id" : 3 , "name" : "baz" }),
])
state = { "items" : [{ "id" : 1 , "name" : "foo" }, { "id" : 2 , "name" : "bar" }]}
new_state = glyph.apply_patch(state, patch)
# {"items": [{"id": 1, "name": "foo"}, {"id": 2, "name": "bar"}, {"id": 3, "name": "baz"}]}
Increment Operation (~)
Add a numeric value to an existing number (supports negative increments).
# Before
{count=5 score=100}
# Patch
~ count 1
~ score -10
# After
{count=6 score=90}
import glyph
# Increment counters
patch = glyph.patch([
( "~" , "count" , 1 ),
( "~" , "score" , - 10 ),
])
state = { "count" : 5 , "score" : 100 }
new_state = glyph.apply_patch(state, patch)
# {"count": 6, "score": 90}
Delete Operation (-)
Remove a key from a map or an index from a list.
# Before
{temp_data=xyz count=5 items=[a b c]}
# Patch
- temp_data
- items[1]
# After
{count=5 items=[a c]}
import glyph
# Delete fields
patch = glyph.patch([
( "-" , "temp_data" , None ),
( "-" , "items[1]" , None ),
])
state = { "temp_data" : "xyz" , "count" : 5 , "items" : [ "a" , "b" , "c" ]}
new_state = glyph.apply_patch(state, patch)
# {"count": 5, "items": ["a", "c"]}
Base Hash Verification
Patches include a base fingerprint - the first 16 characters of the SHA-256 hash of the canonical form of the base state. This enables:
Optimistic concurrency : Reject patches applied to stale state
Streaming validation : Verify state consistency without full doc transfer
Debugging : Trace state divergence in distributed systems
@patch @base=1a2b3c4d5e6f7890
= score 95
+ events "Goal!"
@end
The @base= attribute contains the first 16 hex characters of sha256(canonicalize(baseState)).
Creating Patches with Base
import glyph
# Base state
base_state = { "score" : 90 , "events" : []}
# Create patch with base fingerprint
patch = glyph.PatchBuilder(target) \
.with_base_value(base_state) \
.set( "score" , 95 ) \
.append( "events" , "Goal!" ) \
.build()
# Patch includes: @base=1a2b3c4d5e6f7890
Applying Patches with Base Verification
import glyph
from glyph import stream
# Receiver verifies base hash before applying
@handler.on_patch
def handle_patch ( sid , seq , payload , state ):
# Base hash already verified by handler
patch = glyph.parse_patch(payload)
new_state = glyph.apply_patch(state.value, patch)
handler.cursor.set_state(sid, new_state)
return new_state
@handler.on_base_mismatch
def handle_mismatch ( sid , frame ):
# State diverged - request full resync
logger.warning( f "State mismatch on { sid } " )
request_full_state(sid)
Concurrent Safety
Base hash verification prevents the “lost update” problem in distributed systems.
The Problem
1. Agent A reads state: {count=5} (hash: abc123...)
2. Agent B reads state: {count=5} (hash: abc123...)
3. Agent A writes: {count=6} (hash: def456...)
4. Agent B writes: {count=6} ❌ Overwrites A's update!
The Solution
1. Agent A reads state: {count=5} (hash: abc123...)
2. Agent B reads state: {count=5} (hash: abc123...)
3. Agent A sends patch with @base=abc123... → Accepted
4. Agent B sends patch with @base=abc123... → Rejected (base mismatch)
5. Agent B re-reads state: {count=6} (hash: def456...)
6. Agent B sends patch with @base=def456... → Accepted
Example: Optimistic Concurrency
import glyph
from glyph import stream
def update_with_retry ( writer , sid , seq , update_fn , max_retries = 3 ):
"""Apply update with optimistic concurrency control."""
for attempt in range (max_retries):
# Read current state
state = read_state(sid)
base_hash = glyph.fingerprint_loose(state)
# Compute patch
patch = update_fn(state)
# Send with base hash
try :
writer.write_frame(
sid = sid,
seq = seq,
kind = "patch" ,
payload = patch,
base = base_hash[: 16 ],
)
return # Success
except BaseMismatchError:
# State changed, retry
logger.info( f "Retry { attempt + 1 } / { max_retries } " )
continue
raise Exception ( "Max retries exceeded" )
# Usage
update_with_retry(
writer,
sid = 1 ,
seq = 5 ,
update_fn = lambda state : glyph.patch([( "~" , "count" , 1 )])
)
Token Savings
Operation Full State Patch Savings Increment counter ~120 tokens ~8 tokens 93% Append to list ~200 tokens ~15 tokens 92% Update 1 of 10 fields ~180 tokens ~12 tokens 93% Update 3 of 10 fields ~180 tokens ~35 tokens 80%
When to Use Patches
For state that changes frequently (counters, progress, live metrics). Example: Agent updating turn count, token usage, or task completion percentage.
When the full state is large but updates are small. Example: 10KB agent memory, updating a single field.
When multiple agents may update the same state concurrently. Example: Multi-agent planning with shared task queue.
For streaming logs, events, or observation history. Example: ReAct loop appending tool results to observations.
Next Steps
Fingerprinting Deep dive into SHA-256 state hashing
GS1 Streaming Learn about frame-based patch delivery
Agent Patterns See patches in multi-agent coordination
API Reference Explore patch APIs in all languages