AGONRows Format¶
Row-based tabular encoding for uniform arrays—AGON's most commonly selected format.
Overview¶
AGONRows is a row-based encoding format optimized for uniform arrays of objects with consistent field structure. It's similar to TOON's approach and produces nearly identical output for uniform arrays (tabs vs commas as delimiters).
Best for:
- User lists, transaction logs, simple metrics
- Consistent field structure across records (2-10 fields)
- Flat or shallow nesting
- Homogeneous data types per field
Basic Example¶
Let's encode a simple user list:
Format elements:
[3]- Array length declaration{id name role}- Field headers (tab-separated)- Rows - Tab-delimited values
| Element | Tokens | Purpose |
|---|---|---|
[3] |
2 | Array length (enables validation) |
{id name role} |
5 | Field headers (schema) |
| Row 1 | 5 | 1 Alice admin |
| Row 2 | 4 | 2 Bob user |
| Row 3 | 5 | 3 Charlie user |
| Total | 26 | 58% savings vs pretty JSON (62 tokens) |
Why it works: Eliminates repeated field names ("id":, "name":, "role":) and JSON syntax overhead ({, }, ").
Format Specification¶
Syntax¶
Components:
- Array length:
[N]where N is the number of records - Field headers:
{field1 field2 ...}tab-separated field names - Rows: Tab-delimited values, one row per record
Delimiters¶
Default: Tab character (\t)
Custom delimiter:
from agon import AGONRows
# Use pipe delimiter instead of tab
encoded = AGONRows.encode(data, delimiter="|")
Encoding Rules¶
Primitives¶
AGONRows infers types from content—no type markers needed:
| Type | Example Input | Encoded Output |
|---|---|---|
| String | "Alice" |
Alice |
| Integer | 42 |
42 |
| Float | 3.14 |
3.14 |
| Boolean | true |
true |
| Null | null |
`` (empty cell) |
Missing Values¶
Missing/null values → Empty cell (consecutive delimiters):
Row 2 has empty email field (two consecutive tabs).
Quoting¶
Simple values (no special characters) → Unquoted:
Values with spaces, tabs, or newlines → Quoted:
Quotes in values → Escaped with backslash:
Nested Objects¶
Nested objects → Indented key-value pairs:
Indentation: 2 spaces per level
Arrays¶
Primitive arrays → Inline with delimiter:
Object arrays → Tabular format (primary use case):
Complete Example¶
Real-world data from toon.json:
{
"context": {
"task": "Our favorite hikes together",
"location": "Boulder",
"season": "spring_2025"
},
"friends": ["ana", "luis", "sam"],
"hikes": [
{
"id": 1,
"name": "Blue Lake Trail",
"distanceKm": 7.5,
"elevationGain": 320,
"companion": "ana",
"wasSunny": true
},
{
"id": 2,
"name": "Ridge Overlook",
"distanceKm": 9.2,
"elevationGain": 540,
"companion": "luis",
"wasSunny": false
},
{
"id": 3,
"name": "Wildflower Loop",
"distanceKm": 5.1,
"elevationGain": 180,
"companion": "sam",
"wasSunny": true
}
]
}
| Format | Tokens | Savings |
|---|---|---|
| Pretty JSON | 229 | baseline |
| Compact JSON | 139 | +39.3% |
| AGONRows | 96 | +58.1% |
30.9% savings vs compact JSON!
When AGONRows Wins¶
- Uniform arrays with 3+ records having identical field structure
- Consistent field types (all records have same fields with same types)
- 2-10 fields per record (sweet spot for row-based format)
- Simple data types (strings, numbers, booleans—not deeply nested objects)
- Transaction logs (timestamp, user, action, status)
- User lists (id, name, email, role)
- Metrics/analytics (date, metric_name, value, unit)
- Flat CSV-like data being sent to LLMs
When AGONRows Loses¶
- Wide tables (10+ fields) → AGONColumns wins (type clustering)
- Irregular structure (fields vary between records) → JSON fallback
- Deeply nested objects with no arrays → JSON or Struct
- Sparse data (many nulls) → AGONColumns handles better
- Repeated nested patterns (e.g.,
{fmt, raw}everywhere) → Struct wins
Example where Columns wins:
# 12 fields - wide table
employee_data = [
{
"id": 1, "name": "Alice", "email": "alice@example.com",
"age": 28, "city": "NYC", "state": "NY", "zip": "10001",
"phone": "555-0001", "dept": "Eng", "title": "SWE",
"salary": 120000, "start_date": "2020-01-15"
},
# ... more records
]
result = AGON.encode(employee_data, format="auto")
# → Selects "columns" (better type clustering for 12 fields)
Direct Usage¶
For advanced use cases, use AGONRows encoder directly:
from agon import AGONRows
# Encode with default options
encoded = AGONRows.encode(data)
# Custom delimiter
encoded = AGONRows.encode(data, delimiter="|")
# Without header (for LLM prompts)
encoded = AGONRows.encode(data, include_header=False)
# With header (for decoding)
encoded_with_header = AGONRows.encode(data, include_header=True)
# → @AGON rows\n\n[3]{id...}
# Decode
decoded = AGONRows.decode(encoded)
assert decoded == data # Lossless
Edge Cases¶
Single item array
All null values
(Two consecutive tabs for empty cells)
Special characters in values
data = [{"name": "Alice\tBob", "quote": "He said \"hi\""}]
result = AGON.encode(data, format="rows")
# → [1]{name quote}
# "Alice\tBob" "He said \"hi\""
(Automatic quoting and escaping)
Comparison with TOON¶
For uniform arrays, AGONRows and TOON produce near identical output:
Both achieve the same token savings vs JSON.
TOON and AGONRows are nearly identical! The only difference is that AGONRows uses tabs (\t) while TOON uses commas (,) as delimiters.
FAQ¶
When should I use Text vs Columns?
Use Text when:
- 2-10 fields per record
- Consistent structure
- Mixed data types
Use Columns when:
- 10+ fields (wide tables)
- Numeric-heavy data
- Sparse data (many nulls)
Can I customize the delimiter?
Yes! Use AGONRows encoder directly:
Does AGONRows handle nested objects?
Yes, with indentation:
Is AGONRows the same as TOON?
For uniform arrays: Yes, near identical output.
Overall: AGON includes safety features (auto mode, JSON fallback) that TOON doesn't have.
Next Steps¶
AGONColumns Format¶
Learn about columnar encoding for wide tables
AGONStruct Format¶
Learn about template-based encoding
Benchmarks¶
See AGONRows performance on real datasets
API Reference¶
Complete API documentation