Overview
The Event object is the fundamental building block of Fabraix’s observability system. Every action, decision, and interaction in your agent’s lifecycle is captured as an Event.
Event Structure
The Event object has a precise structure designed for flexibility and comprehensive tracking:
interface Event {
id : string ; // Unique identifier (UUID)
timestamp : datetime ; // ISO 8601 timestamp
trace_id : string ; // Session identifier
type : EventType ; // Event category
content : string ; // Stringified JSON payload
schema : string ; // JSON Schema definition
}
Field Definitions
A unique identifier for the event (typically a UUID). This ID is generated by your system and should be globally unique. Example : "e7d4f3a2-8b1c-4d9e-a5f6-2c3d4e5f6a7b"
The precise time when the event occurred, formatted as ISO 8601. Format : YYYY-MM-DDTHH:mm:ss.sssZExample : "2024-01-15T14:30:45.123Z"
The unique session identifier returned from /register-agent-run. This links the event to a specific agent session. Example : "f4f4f4f4-f4f4-f4f4-f4f4-f4f4f4f4f4f4"
The logical category of the event. Must be one of:
user - Human user input
model_input - Data sent to LLM
model_output - LLM responses
system - System-level events
tool - Tool/function calls
environment - External system data
memory - Memory operations
error - Error conditions
The actual event data as a stringified JSON object. This must validate against the provided schema. Example :"{ \" location \" : \" London, UK \" , \" units \" : \" celsius \" }"
A stringified JSON Schema that defines the structure of the content field. This enables dynamic validation and understanding of diverse event types. Example :"{ \" type \" : \" object \" , \" properties \" :{ \" location \" :{ \" type \" : \" string \" }, \" units \" :{ \" type \" : \" string \" }}}"
Content and Schema Relationship
The power of Fabraix’s data model lies in the relationship between content and schema. The schema defines what the content should look like, enabling:
Dynamic Validation : Content is validated against its schema
Type Safety : Clear contracts for event data
Flexibility : Support for any data structure
Documentation : Self-describing events
Here’s how content and schema work together for a tool call:
# The schema defines the tool's signature
tool_schema = {
"type" : "function" ,
"name" : "search_database" ,
"description" : "Search the customer database" ,
"parameters" : {
"type" : "object" ,
"properties" : {
"query" : {
"type" : "string" ,
"description" : "Search query"
},
"filters" : {
"type" : "object" ,
"properties" : {
"status" : {
"type" : "string" ,
"enum" : [ "active" , "inactive" , "pending" ]
},
"created_after" : {
"type" : "string" ,
"format" : "date-time"
}
}
},
"limit" : {
"type" : "integer" ,
"minimum" : 1 ,
"maximum" : 100 ,
"default" : 10
}
},
"required" : [ "query" ]
}
}
# The content contains the actual arguments
tool_content = {
"query" : "enterprise customers" ,
"filters" : {
"status" : "active" ,
"created_after" : "2024-01-01T00:00:00Z"
},
"limit" : 25
}
# Submit the event
log_event(
trace_id = trace_id,
event_type = "tool" ,
content = json.dumps(tool_content),
schema = json.dumps(tool_schema)
)
Event Type Examples
User Event
Captures input from human users:
{
"type" : "user" ,
"content" : "{ \" message \" : \" What's the weather in Paris? \" , \" user_id \" : \" user-123 \" }" ,
"schema" : "{ \" type \" : \" object \" , \" properties \" :{ \" message \" :{ \" type \" : \" string \" }, \" user_id \" :{ \" type \" : \" string \" }}}"
}
Data sent to the LLM:
{
"type" : "model_input" ,
"content" : "{ \" messages \" :[{ \" role \" : \" system \" , \" content \" : \" You are helpful \" },{ \" role \" : \" user \" , \" content \" : \" What's 2+2? \" }], \" temperature \" :0.7}" ,
"schema" : "{ \" type \" : \" object \" , \" properties \" :{ \" messages \" :{ \" type \" : \" array \" , \" items \" :{ \" type \" : \" object \" }}, \" temperature \" :{ \" type \" : \" number \" }}}"
}
Model Output Event
LLM responses:
{
"type" : "model_output" ,
"content" : "{ \" response \" : \" 2+2 equals 4 \" , \" confidence \" :0.99, \" tokens_used \" :15}" ,
"schema" : "{ \" type \" : \" object \" , \" properties \" :{ \" response \" :{ \" type \" : \" string \" }, \" confidence \" :{ \" type \" : \" number \" }, \" tokens_used \" :{ \" type \" : \" integer \" }}}"
}
Memory Event
Memory operations:
{
"type" : "memory" ,
"content" : "{ \" operation \" : \" write \" , \" key \" : \" user_preferences \" , \" value \" :{ \" language \" : \" en \" , \" timezone \" : \" EST \" }}" ,
"schema" : "{ \" type \" : \" object \" , \" properties \" :{ \" operation \" :{ \" type \" : \" string \" , \" enum \" :[ \" read \" , \" write \" , \" delete \" ]}, \" key \" :{ \" type \" : \" string \" }, \" value \" :{ \" type \" : \" object \" }}}"
}
Environment Event
External system interactions:
{
"type" : "environment" ,
"content" : "{ \" source \" : \" weather_api \" , \" data \" :{ \" temperature \" :22, \" conditions \" : \" sunny \" }}" ,
"schema" : "{ \" type \" : \" object \" , \" properties \" :{ \" source \" :{ \" type \" : \" string \" }, \" data \" :{ \" type \" : \" object \" }}}"
}
Handling Complex Data
Images and Binary Data
For images and binary data, use base64 encoding within the JSON:
import base64
# Encode image
with open ( "image.png" , "rb" ) as f:
image_base64 = base64.b64encode(f.read()).decode( 'utf-8' )
# Include in event
content = {
"image" : image_base64,
"format" : "png" ,
"description" : "User uploaded screenshot"
}
schema = {
"type" : "object" ,
"properties" : {
"image" : {
"type" : "string" ,
"contentEncoding" : "base64"
},
"format" : {
"type" : "string" ,
"enum" : [ "png" , "jpg" , "gif" ]
},
"description" : {
"type" : "string"
}
}
}
Nested Structures
Support complex nested data structures:
content = {
"order" : {
"id" : "order-123" ,
"customer" : {
"id" : "cust-456" ,
"name" : "Alice Smith" ,
"tier" : "premium"
},
"items" : [
{
"product_id" : "prod-789" ,
"quantity" : 2 ,
"price" : 29.99
}
],
"metadata" : {
"source" : "web" ,
"campaign" : "summer-sale"
}
}
}
# Schema can validate complex nested structures
schema = {
"type" : "object" ,
"properties" : {
"order" : {
"type" : "object" ,
"properties" : {
"id" : { "type" : "string" },
"customer" : {
"type" : "object" ,
"properties" : {
"id" : { "type" : "string" },
"name" : { "type" : "string" },
"tier" : { "type" : "string" }
}
},
"items" : {
"type" : "array" ,
"items" : {
"type" : "object" ,
"properties" : {
"product_id" : { "type" : "string" },
"quantity" : { "type" : "integer" },
"price" : { "type" : "number" }
}
}
}
}
}
}
}
Best Practices
Generate UUIDs for event IDs to ensure uniqueness: import uuid
event_id = str (uuid.uuid4())
Add contextual information that might be useful for analysis: content = {
"action" : "delete_file" ,
"file" : "/data/report.pdf" ,
"reason" : "User requested deletion" ,
"user_id" : "user-123" ,
"ip_address" : "192.168.1.1"
}
Include constraints, formats, and descriptions: schema = {
"type" : "object" ,
"properties" : {
"email" : {
"type" : "string" ,
"format" : "email" ,
"description" : "User's email address"
},
"age" : {
"type" : "integer" ,
"minimum" : 0 ,
"maximum" : 150
},
"score" : {
"type" : "number" ,
"minimum" : 0 ,
"maximum" : 100 ,
"multipleOf" : 0.1
}
},
"required" : [ "email" ],
"additionalProperties" : false
}
Log errors as events for debugging: try :
# Some operation
result = risky_operation()
except Exception as e:
log_event(
trace_id = trace_id,
event_type = "error" ,
content = json.dumps({
"error" : str (e),
"error_type" : e. __class__ . __name__ ,
"context" : {
"operation" : "risky_operation" ,
"input" : input_data
}
}),
schema = error_schema
)
Validation
Fabraix validates all events against their schemas. Common validation errors:
Schema Mismatch : Content doesn’t match schema structure{
"error" : "Content validation failed" ,
"details" : "Required property 'user_id' missing"
}
Invalid JSON : Content or schema is not valid JSON{
"error" : "Invalid JSON in content field" ,
"details" : "Unexpected token at position 45"
}
Type Mismatch : Wrong data type for a field{
"error" : "Type validation failed" ,
"details" : "Expected string for 'age', got number"
}
Next Steps
Now that you understand the Event data model: