Data Schema

Pydantic models defining the trace, interaction, and baseline data structures. All models are in spooled/models.py.

Trace

The parent record for an agent execution run.

class Trace(BaseModel):
    run_id: str                           # UUID
    agent_id: str
    timestamp: datetime                   # UTC start time
    status: TraceStatus                   # RUNNING | SUCCESS | FAILURE
    environment: Dict[str, Optional[str]] # OS, Python version
    tags: List[str]                       # User-defined tags
    chain_hash: Optional[str]             # SHA-256 of final interaction
    fingerprint_hash: Optional[str]       # Structural hash for baseline lookup
    session_id: Optional[str]             # Multi-agent session correlation
    parent_run_id: Optional[str]          # Parent trace for spawned agents
    depth: int                            # Nesting depth (0=root, 1+=child)

Interaction

A single step in the agent's execution.

class Interaction(BaseModel):
    interaction_id: str
    run_id: str
    sequence: int                         # 0-indexed order
    interaction_type: InteractionType     # LLM_CALL | TOOL_CALL | HTTP_REQUEST | OTHER
    timestamp: datetime
    input: Dict[str, Any]                 # Prompt, function args, URL
    output: Optional[Dict[str, Any]]      # Response, result
    error: Optional[str]                  # Error message if failed
    metadata: Dict[str, Any]              # latency_ms, tokens, status_code
    parent_interaction_id: Optional[str]  # Lineage tracking
    prev_hash: Optional[str]             # SHA-256 of previous interaction (hash chain)
    payload_hash: Optional[str]          # SHA-256 of this interaction's payload
    parallel_group: Optional[str]        # Group ID for concurrent interactions

TraceStatus

class TraceStatus(str, Enum):
    RUNNING = "RUNNING"
    SUCCESS = "SUCCESS"
    FAILURE = "FAILURE"

InteractionType

class InteractionType(str, Enum):
    LLM_CALL = "LLM_CALL"
    TOOL_CALL = "TOOL_CALL"
    HTTP_REQUEST = "HTTP_REQUEST"
    OTHER = "OTHER"

AgentBaseline

Container for all known behavioral patterns of an agent.

class AgentBaseline(BaseModel):
    agent_id: str
    updated_at: datetime
    intents: Dict[str, RunStatistics]  # key: fingerprint_hash

RunStatistics

Intent-scoped statistics from the rolling baseline window.

class RunStatistics(BaseModel):
    avg_latency: float                          # ms
    std_dev_latency: float                      # ms
    avg_tokens: float
    error_rate: float                           # 0.01.0
    sample_count: int                           # Runs in sample
    fingerprint: Dict[str, Any]                 # Behavioral fingerprint
    fingerprint_hash: Optional[str]             # SHA-256 intent ID
    structural_fingerprint_hash: Optional[str]  # IO-schema hash (rename-resilient)
    accepted_fingerprints: List[str]            # Variant acceptance list
    accepted_variants: List[AcceptedVariant]    # Provenance records
    similarity_trend: List[SimilarityTrendPoint]
    step_count: int
    tool_call_counts: Dict[str, int]            # tool_name -> count
    token_totals: Dict[str, float]              # prompt, completion, total
    latency_bounds: Dict[str, float]            # min, p5, p50, p95, max, avg (ms)
    runs: List[Dict]                            # Rolling window entries
    component_avg_latencies: Dict[str, float]   # Per-component latency
    decision_distributions: Dict[str, Dict[str, int]]   # field -> {value -> count}
    output_schema_snapshots: Dict[str, List[str]]       # tool -> [field names]
    score_statistics: Dict[str, Dict[str, float]]       # Numeric field stats

SpooledScore

class SpooledScore(BaseModel):
    score: int              # 0100
    grade: str              # A, B, C, D, F
    confidence: str         # high, medium, low
    components: SpooledScoreComponents  # structural, signal, metric, trend

SimilarityTrendPoint

class SimilarityTrendPoint(BaseModel):
    timestamp: str                    # ISO 8601
    intent_id: str                    # Fingerprint hash
    similarity_score: float           # 0.01.0
    fingerprint_status: str           # match, variant, accepted_variant
    dominant_reason: Optional[str]    # Drift reason code
    spooled_score: Optional[int]      # Spooled Score at comparison

AcceptedVariant

class AcceptedVariant(BaseModel):
    fingerprint_hash: str
    accepted_at: str            # ISO timestamp
    reason: Optional[str]       # e.g., "prompt update"
    accepted_by: Optional[str]  # user, cli, GitHub Actions

AttestationRecord (Pro/Team)

class AttestationRecord(BaseModel):
    attestation_id: str
    org_id: str
    agent_id: str
    run_id: Optional[str]
    timestamp: str                          # ISO 8601
    fingerprint_hash: str
    structural_fingerprint_hash: Optional[str]
    chain_hash: Optional[str]
    drift_score: Optional[float]
    spooled_score: Optional[int]
    spooled_grade: Optional[str]
    metrics: Dict[str, Any]
    signature: Optional[str]                # Base64 KMS signature
    signing_key_id: Optional[str]           # KMS key ARN
    signing_algorithm: str                  # RSASSA_PKCS1_V1_5_SHA_256
    digest: Optional[str]                   # SHA-256 of canonical payload
    status: str                             # "signed" or "revoked"

Storage formats

TypeFormatLocation
TracesJSONL (append-only).spooled/traces/<agent_id>-<run_id>.jsonl
BaselinesJSON.spooled/traces/baselines/<agent_id>.json or baselines/<agent_id>.json
CI HistoryJSONL.spooled/ci-history/<agent_id>.jsonl
AttestationsJSONBackend (Pro/Team)

Fingerprint status values

StatusDescription
matchFingerprint exactly matches a baseline intent
accepted_variantMatches an accepted fingerprint in the intent's acceptance list
variantSimilar (≥75% similarity) but not exact match
newStructurally different from all baseline intents
no_baselineNo baseline exists yet (cold start)
structural_matchMatches via IO-schema hash (rename-resilient)