Class: RubyLLM::Agents::Tenant

Inherits:
ActiveRecord::Base
  • Object
show all
Includes:
Budgetable, Incrementable, Resettable, Trackable
Defined in:
app/models/ruby_llm/agents/tenant.rb,
app/models/ruby_llm/agents/tenant/trackable.rb,
app/models/ruby_llm/agents/tenant/budgetable.rb,
app/models/ruby_llm/agents/tenant/resettable.rb,
app/models/ruby_llm/agents/tenant/incrementable.rb

Overview

Central model for tenant management in multi-tenant LLM applications.

Encapsulates all tenant-related functionality:

  • Budget limits and enforcement (via Budgetable concern)

  • Usage tracking: cost, tokens, executions (via Trackable concern)

Examples:

Creating a tenant

Tenant.create!(
  tenant_id: "acme_corp",
  name: "Acme Corporation",
  daily_limit: 100.0,
  enforcement: "hard"
)

Linking to user’s model

Tenant.create!(
  tenant_id: organization.id.to_s,
  tenant_record: organization,
  daily_limit: 100.0
)

Finding a tenant

tenant = Tenant.for(organization)
tenant = Tenant.for("acme_corp")

See Also:

Defined Under Namespace

Modules: Budgetable, Incrementable, Resettable, Trackable

Constant Summary

Constants included from Budgetable

Budgetable::ENFORCEMENT_MODES

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Incrementable

#record_execution!

Methods included from Resettable

#ensure_daily_reset!, #ensure_monthly_reset!, #refresh_counters!

Methods included from Trackable

#cost, #cost_last_month, #cost_last_week, #cost_this_month, #cost_this_week, #cost_today, #cost_yesterday, #errors_this_month, #errors_today, #execution_count, #executions_last_month, #executions_this_month, #executions_this_week, #executions_today, #executions_yesterday, #failed_executions, #recent_executions, #success_rate_today, #tokens, #tokens_last_month, #tokens_this_month, #tokens_this_week, #tokens_today, #tokens_yesterday, #usage_by_agent, #usage_by_day, #usage_by_model, #usage_summary

Methods included from Budgetable

#budget_status, #budgets_enabled?, #check_budget!, #effective_daily_execution_limit, #effective_daily_limit, #effective_daily_token_limit, #effective_enforcement, #effective_monthly_execution_limit, #effective_monthly_limit, #effective_monthly_token_limit, #effective_per_agent_daily, #effective_per_agent_monthly, #hard_enforcement?, #remaining_budget, #soft_enforcement?, #to_budget_config, #within_budget?, #within_daily_cost_budget?, #within_daily_execution_budget?, #within_daily_token_budget?, #within_monthly_cost_budget?, #within_monthly_execution_budget?, #within_monthly_token_budget?

Class Method Details

.for(tenant) ⇒ Tenant? Also known as: for_tenant

Find tenant for given record or ID

Supports multiple lookup strategies:

  1. ActiveRecord model - looks up by polymorphic association first, then tenant_id

  2. Object with llm_tenant_id - looks up by tenant_id

  3. String - looks up by tenant_id

Examples:

Find by model

Tenant.for(organization)

Find by string ID

Tenant.for("acme_corp")

Parameters:

  • tenant (String, ActiveRecord::Base, Object)

    Tenant ID, model, or object with llm_tenant_id

Returns:

  • (Tenant, nil)

    The tenant record or nil if not found



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'app/models/ruby_llm/agents/tenant.rb', line 111

def self.for(tenant)
  return nil if tenant.blank?

  if tenant.is_a?(::ActiveRecord::Base)
    # ActiveRecord model - try polymorphic first, then tenant_id
    find_by(tenant_record: tenant) ||
      find_by(tenant_id: tenant.try(:llm_tenant_id) || tenant.id.to_s)
  elsif tenant.respond_to?(:llm_tenant_id)
    # Object with llm_tenant_id method
    find_by(tenant_id: tenant.llm_tenant_id)
  else
    # String tenant_id
    find_by(tenant_id: tenant.to_s)
  end
end

.for!(tenant_id, **attributes) ⇒ Tenant Also known as: for_tenant!

Find or create tenant

Examples:

Tenant.for!("acme_corp", name: "Acme Corporation")

Parameters:

  • tenant_id (String)

    Unique tenant identifier

  • attributes (Hash)

    Additional attributes for creation

Returns:



136
137
138
139
140
# File 'app/models/ruby_llm/agents/tenant.rb', line 136

def self.for!(tenant_id, **attributes)
  find_or_create_by!(tenant_id: tenant_id.to_s) do |tenant|
    tenant.assign_attributes(attributes)
  end
end

.top_by_spend(limit: 5) ⇒ Array<Hash>?

Returns top tenants by monthly spend for dashboard display

Ensures counter resets are current before returning data.

Parameters:

  • limit (Integer) (defaults to: 5)

    Max tenants to return

Returns:

  • (Array<Hash>, nil)

    Tenant spend data or nil if none



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'app/models/ruby_llm/agents/tenant.rb', line 62

def self.top_by_spend(limit: 5)
  return nil unless table_exists?

  tenants = active
    .where("monthly_cost_spent > 0 OR monthly_executions_count > 0")
    .order(monthly_cost_spent: :desc)
    .limit(limit)

  return nil if tenants.empty?

  tenants.map do |tenant|
    tenant.ensure_daily_reset!
    tenant.ensure_monthly_reset!

    monthly_limit = tenant.effective_monthly_limit
    daily_limit = tenant.effective_daily_limit

    {
      id: tenant.id,
      tenant_id: tenant.tenant_id,
      name: tenant.display_name,
      enforcement: tenant.effective_enforcement,
      monthly_spend: tenant.monthly_cost_spent,
      monthly_limit: monthly_limit,
      monthly_percentage: (monthly_limit.to_f > 0) ? (tenant.monthly_cost_spent / monthly_limit * 100).round(1) : 0,
      daily_spend: tenant.daily_cost_spent,
      daily_limit: daily_limit,
      daily_percentage: (daily_limit.to_f > 0) ? (tenant.daily_cost_spent / daily_limit * 100).round(1) : 0,
      monthly_executions: tenant.monthly_executions_count
    }
  end
end

Instance Method Details

#activate!Boolean

Activate the tenant

Returns:

  • (Boolean)


179
180
181
# File 'app/models/ruby_llm/agents/tenant.rb', line 179

def activate!
  update!(active: true)
end

#active?Boolean

Check if tenant is active

Returns:

  • (Boolean)


165
166
167
# File 'app/models/ruby_llm/agents/tenant.rb', line 165

def active?
  active != false
end

#deactivate!Boolean

Deactivate the tenant

Returns:

  • (Boolean)


172
173
174
# File 'app/models/ruby_llm/agents/tenant.rb', line 172

def deactivate!
  update!(active: false)
end

#display_nameString

Display name (name or tenant_id fallback)

Returns:

  • (String)


151
152
153
# File 'app/models/ruby_llm/agents/tenant.rb', line 151

def display_name
  name.presence || tenant_id
end

#linked?Boolean

Check if tenant is linked to a user model

Returns:

  • (Boolean)


158
159
160
# File 'app/models/ruby_llm/agents/tenant.rb', line 158

def linked?
  tenant_record.present?
end