Skip to content

codenamev/ruby_llm-ups

Repository files navigation

RubyLLM::Ups

Connect your RubyLLM-powered agents to ups.dev status pages.

After each LLM response, the gem sends a lightweight heartbeat to ups.dev — model, provider, response time, tool count. No message content is ever sent. Status degradation and incidents are reported by you, when you decide they matter.

Installation

gem "ruby_llm-ups"

Quick Start

1. Configure

RubyLLM::Ups.configure do |c|
  c.api_key = "ups_live_abc123_xyz789"
  c.status_page_id = "my-page-slug"  # your status page slug or numeric ID
end

In Rails, credentials are auto-loaded — no initializer needed if you set:

# config/credentials.yml.enc
ups:
  api_key: ups_live_abc123_xyz789
  status_page_id: my-page-slug

2. Include Monitored in your base agent

class ApplicationAgent < RubyLLM::Agent
  include RubyLLM::Ups::Monitored
end

That's it. Every agent that inherits from ApplicationAgent gets its own component on ups.dev, auto-created by name. ResearchAgent becomes "Research Agent", DataProcessor becomes "Data Processor Agent".

class ResearchAgent < ApplicationAgent
  model "claude-sonnet-4-20250514"
  tools SearchTool, SummarizeTool
end

agent = ResearchAgent.new    # → "Research Agent" component created on ups.dev
agent.ask("Hello")           # → heartbeat: operational + metadata

Override the default name with ups_component:

class MyAgent < ApplicationAgent
  ups_component "Customer Support Bot"
end

What gets reported

Every successful LLM response sends:

{
  model: "claude-sonnet-4-20250514",   # which model handled the request
  provider: "anthropic",                # the LLM provider
  last_response_time_ms: 1230,          # end-to-end response time
  tool_count: 3                         # number of tools available
}

Failed LLM calls report nothing — the monitor only fires on successful responses. You decide when a failure is worth reporting (see below).

Reporting failures

Status degradation

Use report_status when you detect a problem — partial failures, elevated error rates, slow responses:

RubyLLM::Ups.report_status(:degraded_performance,
  component_id: component_id,
  agent_metadata: {
    failed_step: "summarization",
    error: "Provider timeout"
  }
)

Incidents

Create incidents for failures your users should know about:

RubyLLM::Ups.create_incident(
  title: "Processing pipeline down",
  impact: :major,
  status: :investigating,
  description: "Failed at enrichment stage: API rate limit exceeded"
)

Pipeline pattern

A common pattern for multi-stage agent pipelines:

class Pipeline
  def call
    stages.each { |stage| run_stage(stage) }
    ups_report_operational
  rescue => e
    ups_create_incident(e)
    raise
  end

  def run_stage(stage)
    stage.call
  rescue => e
    if optional_stage?(stage)
      ups_report_degraded(stage, e)  # partial failure — degraded, not down
    else
      raise                          # critical failure — will create incident
    end
  end

  private

  def pipeline_component_id
    @pipeline_component_id ||= begin
      component = RubyLLM::Ups.component_registry.find_or_create("My Pipeline")
      component["id"]
    end
  end

  def ups_report_operational
    RubyLLM::Ups.report_status(:operational, component_id: pipeline_component_id)
  rescue => e
    Rails.logger.warn("[ups.dev] #{e.message}")
  end

  def ups_report_degraded(stage, error)
    RubyLLM::Ups.report_status(:degraded_performance,
      component_id: pipeline_component_id,
      agent_metadata: { failed_stage: stage.name, error: error.message }
    )
  rescue => e
    Rails.logger.warn("[ups.dev] #{e.message}")
  end

  def ups_create_incident(error)
    RubyLLM::Ups.create_incident(
      title: "Pipeline failed",
      impact: :major,
      status: :investigating,
      description: error.message
    )
  rescue => e
    Rails.logger.warn("[ups.dev] #{e.message}")
  end
end

Key points:

  • Use component_registry.find_or_create to get a named component for non-agent things
  • Always rescue ups.dev calls — monitoring failures should never break your app
  • report_status(:operational) after success resets a previously degraded component

Incident lifecycle

# Open
incident = RubyLLM::Ups.create_incident(
  title: "Agent responding slowly",
  impact: :minor,               # :none, :minor, :major, :critical
  status: :investigating        # :investigating, :identified, :monitoring, :resolved
)

# Update
RubyLLM::Ups.update_incident(incident["incident"]["id"],
  status: :identified,
  update_message: "Root cause: Anthropic API degradation"
)

# Resolve
RubyLLM::Ups.resolve_incident(incident["incident"]["id"])

Configuration

Option Default Description
api_key required Your ups.dev API key
status_page_id required Status page slug or numeric ID
component_id Default component for monitor and report_status (optional with Monitored)
base_url https://ups.dev API base URL
request_timeout 30 HTTP timeout in seconds
on_error stderr Error handler proc
async true Send heartbeats in a background thread
flush_interval 5 Seconds between async flushes
circuit_breaker_threshold 5 Consecutive failures before opening circuit
circuit_breaker_timeout 60 Seconds to keep circuit open before retrying

Error handling

Monitoring errors never interrupt your LLM workflows. Route them somewhere useful:

RubyLLM::Ups.configure do |c|
  c.on_error = ->(e) { Rails.logger.warn("[ups.dev] #{e.message}") }
end

Manual monitoring

If you don't want Monitored, call monitor() directly:

RubyLLM::Ups.configure do |c|
  c.api_key = "..."
  c.status_page_id = "..."
  c.component_id = "my-agent-id"
end

chat = RubyLLM.chat(model: "claude-sonnet-4-20250514")
RubyLLM::Ups.monitor(chat)
chat.ask("Hello")  # → heartbeat sent

Direct client access

client = RubyLLM::Ups.client

client.list_components
client.create_component(name: "New Agent", component_type: "agent")
client.update_component("comp-id", status: :operational, agent_metadata: { model: "gpt-4" })

License

MIT

About

ups.dev status page integration for RubyLLM — automatic agent heartbeats, status reporting, and incident management

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages