Get Running in 5 Minutes
This guide will get you from zero to working GLYPH code in under 5 minutes.
Installation
Choose your language:
Python
JavaScript/TypeScript
Go
Rust
C
go get github.com/Neumenon/glyph
Basic Usage
Convert JSON to GLYPH
# Your existing Python data
data = {
"action" : "search" ,
"query" : "AI agents" ,
"limit" : 5
}
# Convert to GLYPH (one line)
glyph_str = glyph.json_to_glyph(data)
print (glyph_str)
# Output: {action=search limit=5 query="AI agents"}
Convert GLYPH back to JSON
# Convert back to Python dict
restored = glyph.glyph_to_json(glyph_str)
assert restored == data # Perfect round-trip
Parse GLYPH directly
# Parse GLYPH text
result = glyph.parse( '{name=Alice age=30 active=t}' )
# Access fields
print (result.get( "name" ).as_str()) # "Alice"
print (result.get( "age" ).as_int()) # 30
print (result.get( "active" ).as_bool()) # True
Import GLYPH
import { ... } from 'glyph-js' ;
Convert JSON to GLYPH
// Your existing JavaScript data
const data = {
action: 'search' ,
query: 'AI agents' ,
limit: 5
};
// Convert to GLYPH
const glyphText = emit ( fromJSON ( data ));
console . log ( glyphText );
// Output: {action=search limit=5 query="AI agents"}
Convert GLYPH back to JSON
// Parse and convert to JavaScript object
const value = parse ( glyphText );
const restored = toJSON ( value );
// restored is identical to original data
Parse GLYPH directly
// Parse GLYPH text
const value = parse ( '{name=Alice age=30 active=t}' );
// Access fields
console . log ( value . get ( 'name' )); // 'Alice'
console . log ( value . get ( 'age' )); // 30
console . log ( value . get ( 'active' )); // true
Import GLYPH
import " github.com/Neumenon/glyph/glyph "
Parse GLYPH text
// Parse GLYPH text
text := `{action=search query=weather limit=10}`
val , err := glyph . Parse ([] byte ( text ))
if err != nil {
log . Fatal ( err )
}
// Access fields
action := val . Get ( "action" ). String () // "search"
limit := val . Get ( "limit" ). Int () // 10
Convert Go data to GLYPH
// Convert Go map to GLYPH
data := map [ string ] interface {}{
"action" : "search" ,
"query" : "weather" ,
"limit" : 10 ,
}
v := glyph . FromJSONLoose ( data )
glyphText := glyph . CanonicalizeLoose ( v )
// {action=search limit=10 query=weather}
Convert GLYPH to Go data
// Parse and convert to Go types
val , _ := glyph . Parse ([] byte ( glyphText ))
data , err := glyph . ToJSONLoose ( val )
// data is map[string]interface{}
Token Savings Example
Let’s see the token savings in action:
import glyph
import json
# Sample data: API response with search results
data = {
"status" : "success" ,
"results" : [
{ "id" : "doc_1" , "title" : "GLYPH Guide" , "score" : 0.95 },
{ "id" : "doc_2" , "title" : "API Docs" , "score" : 0.89 },
{ "id" : "doc_3" , "title" : "Tutorial" , "score" : 0.84 }
],
"total" : 3
}
# Convert to both formats
json_str = json.dumps(data)
glyph_str = glyph.json_to_glyph(data)
# Compare
print ( f "JSON: { len (json_str) } chars" )
print ( f "GLYPH: { len (glyph_str) } chars" )
print ( f "Savings: { 100 * ( 1 - len (glyph_str) / len (json_str)) :.0f} %" )
# Output:
# JSON: 156 chars
# GLYPH: 98 chars
# Savings: 37%
These are character counts. Token savings (what LLMs count) are typically even higher—40-60% for most data shapes.
Streaming Validation
One of GLYPH’s killer features: validate tool calls as tokens stream , not after generation completes.
Why this matters : Catch bad tool names, missing params, or constraint violations at token 3-5, not token 50+. Save tokens, time, and reduce failures.
import glyph
from glyph import StreamingValidator, ToolRegistry
# Define your tools
registry = ToolRegistry()
registry.register(
name = "search" ,
args = {
"query" : { "type" : "str" , "required" : True , "min_len" : 1 },
"max_results" : { "type" : "int" , "min" : 1 , "max" : 100 , "default" : 10 }
}
)
registry.register(
name = "calculate" ,
args = {
"expression" : { "type" : "str" , "required" : True }
}
)
# Create validator
validator = StreamingValidator(registry)
# Simulate streaming tokens from LLM
tokens = [ "{" , "tool" , "=" , "unknown" , "query" , "=" , "test" , "}" ]
for token in tokens:
result = validator.push(token)
# Tool name detected
if result.tool_name:
print ( f "Tool detected: { result.tool_name } " )
# Unknown tool? Cancel immediately!
if not result.tool_allowed:
print ( f "ERROR: Unknown tool ' { result.tool_name } '" )
print ( "Cancelling generation..." )
break
# Check for errors
if result.has_errors():
print ( f "Validation error: { result.errors } " )
break
# Output:
# Tool detected: unknown
# ERROR: Unknown tool 'unknown'
# Cancelling generation...
Result : Error detected at token 4, not after full generation (50+ tokens).
Auto-Tabular Mode
When you have lists of similar objects, GLYPH automatically uses tabular encoding:
Python
Output (50-70% smaller)
import glyph
# List of similar objects (3+ items)
search_results = [
{ "id" : "doc_1" , "score" : 0.95 , "title" : "Introduction" },
{ "id" : "doc_2" , "score" : 0.89 , "title" : "Guide" },
{ "id" : "doc_3" , "score" : 0.84 , "title" : "Reference" }
]
# Convert to GLYPH (automatically uses tabular format)
text = glyph.json_to_glyph(search_results)
print (text)
Why it’s efficient : Keys appear once for the entire table, not repeated for every row.
Parse Tabular Data
# Parse tabular GLYPH
parsed = glyph.parse(text)
# Access as list
print ( f "Found { len (parsed) } results" )
# Access first result
first = parsed.index( 0 )
print (first.get( "id" ).as_str()) # "doc_1"
print (first.get( "score" ).as_float()) # 0.95
# Convert back to Python list of dicts
results = glyph.to_json(parsed)
# results is identical to original search_results
JSON Interoperability
GLYPH is a drop-in replacement for JSON with perfect round-trip conversion:
Start with any Python/JS data
Works with dicts, lists, primitives, nested structures—anything JSON supports.
Convert to GLYPH
glyph_text = glyph.json_to_glyph(data)
40-60% smaller, still human-readable.
Store or transmit
Save to database, send over network, include in LLM prompt—50%+ token savings.
Convert back when needed
restored = glyph.glyph_to_json(glyph_text)
Perfect reconstruction of original data.
Gradual Migration
You don’t need to rewrite everything. Migrate gradually:
import json
import glyph
# Phase 1: Generate JSON (what LLMs know)
llm_output = '{"action": "search", "query": "test"}'
parsed = json.loads(llm_output)
# Phase 2: Store as GLYPH (40% smaller)
stored = glyph.json_to_glyph(parsed)
save_to_db(stored)
# Phase 3: Load and convert back for next LLM
loaded = load_from_db()
as_json = glyph.glyph_to_json(loaded)
llm_context = json.dumps(as_json)
Null: _ List: [1 2 3]
Bool: t / f Map: {a=1 b=2}
Int: 42 String: hello or "hello world"
Float: 3.14 Struct: User{name=Alice age=30}
vs JSON :
No commas between elements
= instead of :
Bare strings (no quotes) when unambiguous
t/f instead of true/false
_ or ∅ instead of null
More Examples
{
"user" : "alice" ,
"active" : true ,
"score" : 0.95 ,
"tags" : [ "premium" , "beta" ],
"metadata" : null
}
Next Steps
You now have the basics! Here’s what to explore next:
Installation Guide Detailed setup for all languages
API Reference Complete API documentation
Agent Patterns Tool calling, state management, ReAct loops
Cookbook 10 practical recipes
Common Questions
Can LLMs generate GLYPH directly?
Yes, but they’re more reliable with JSON (what they’re trained on). Best practice: LLMs generate JSON, you serialize to GLYPH for storage/transmission.
Is GLYPH faster than JSON?
Parsing speed is comparable to JSON. The real benefit is token efficiency—40-60% fewer tokens means lower costs and more context space.
What about protobuf or msgpack?
Those are binary formats—not human-readable and LLMs can’t parse them. GLYPH is text-based, debuggable, and LLM-friendly.
Does it work with existing JSON APIs?
Yes! Convert at the boundaries: # Receive JSON from API
api_response = requests.get( ... ).json()
# Store as GLYPH
stored = glyph.json_to_glyph(api_response)
# Convert back when calling another API
next_api_data = glyph.glyph_to_json(stored)
Get Help