DB - llm_calls

abstract

Audit log of every LLM API call — provider, model, token counts, cost, and duration — enabling usage analytics and cost tracking per account and pipeline step.

Table Info

PropertyValue
Table Namellm_calls
SQLAlchemy Modelbackend/db/models.py :: LLMCall
Pydantic Schemabackend/api/routes/llm_usage.py
Migration Filealembic/versions/
TimescaleDB HypertableNo
Partition Column

Columns

ColumnSQLAlchemy TypeNullableDefaultDescription
idIntegerNoautoPrimary key
pipeline_step_idInteger FKYesnullFK → pipeline_steps.id (SET NULL on delete, indexed)
account_idInteger FKYesnullFK → accounts.id (SET NULL on delete)
providerString(50)NoLLM provider: anthropic, openai, gemini, etc.
modelString(100)NoModel ID used (e.g., claude-opus-4-7)
roleString(50)NoCaller role (e.g., indicator_agent, vision, execution)
input_tokensIntegerYesnullPrompt token count
output_tokensIntegerYesnullCompletion token count
total_tokensIntegerYesnullTotal tokens (input + output)
cost_usdFloatYesnullEstimated cost in USD
duration_msIntegerNo0LLM API call wall-clock time
created_atDateTime(timezone=True)Nodatetime.now(UTC)Call timestamp

Constraints & Indexes

NameTypeColumnsPurpose
pk_llm_callsPRIMARY KEYidRow uniqueness
idx_llm_calls_stepINDEXpipeline_step_idJoin to pipeline step
fk_llm_calls_stepFOREIGN KEYpipeline_step_id → pipeline_steps.id SET NULLPreserve logs when step deleted
fk_llm_calls_accountFOREIGN KEYaccount_id → accounts.id SET NULLPreserve logs when account deleted

Entity Relationships

SQLAlchemy Model (reference snapshot)

class LLMCall(Base):
    __tablename__ = "llm_calls"
 
    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    pipeline_step_id: Mapped[int | None] = mapped_column(
        Integer, ForeignKey("pipeline_steps.id", ondelete="SET NULL"), nullable=True, index=True
    )
    account_id: Mapped[int | None] = mapped_column(
        Integer, ForeignKey("accounts.id", ondelete="SET NULL"), nullable=True
    )
    provider: Mapped[str] = mapped_column(String(50), nullable=False)
    model: Mapped[str] = mapped_column(String(100), nullable=False)
    role: Mapped[str] = mapped_column(String(50), nullable=False)
    input_tokens: Mapped[int | None] = mapped_column(Integer, nullable=True)
    output_tokens: Mapped[int | None] = mapped_column(Integer, nullable=True)
    total_tokens: Mapped[int | None] = mapped_column(Integer, nullable=True)
    cost_usd: Mapped[float | None] = mapped_column(Float, nullable=True)
    duration_ms: Mapped[int] = mapped_column(Integer, default=0)
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(UTC))

Service Layer

LayerFilePurpose
Routerbackend/api/routes/llm_usage.pyToken usage summary + per-model breakdown
Routerbackend/api/routes/llm_analytics.pyCost analytics, model performance
RoleLink
API EndpointAPI-GET-v1-LLM-Usage
API EndpointAPI-GET-v1-LLM-Analytics
Frontend PagePage - LLM Usage
Related TableDB - pipeline_steps