Class: AgentRequestJob

Inherits:
ApplicationJob show all
Defined in:
app/jobs/agent_request_job.rb

Overview

Executes an LLM agent loop as a background job with retry logic for transient failures (network errors, rate limits, server errors).

Supports two modes:

**Bounce Back (content provided):** Persists the user event and verifies LLM delivery inside a single transaction. If the first API call fails, the transaction rolls back (event never existed) and a Events::BounceBack is emitted so clients can restore the text to the input field.

**Standard (no content):** Processes already-persisted events (e.g. after pending message promotion). Uses ActiveJob retry/discard for error handling.

Examples:

Bounce Back — event-driven via AgentDispatcher

AgentRequestJob.perform_later(session.id, content: "hello")

Standard — pending message processing

AgentRequestJob.perform_later(session.id)

Constant Summary collapse

AUTH_REQUIRED_ACTION =

ActionCable action signaling clients to prompt for an API token.

"authentication_required"

Instance Method Summary collapse

Instance Method Details

#perform(session_id, content: nil) ⇒ Object

Parameters:

  • session_id (Integer)

    ID of the session to process

  • content (String, nil) (defaults to: nil)

    user message text (triggers Bounce Back when present)



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'app/jobs/agent_request_job.rb', line 51

def perform(session_id, content: nil)
  session = Session.find(session_id)

  # Atomic: only one job processes a session at a time.
  return unless claim_processing(session_id)

  run_analytical_brain_blocking(session)

  agent_loop = AgentLoop.new(session: session)

  if content
    deliver_with_bounce_back(session, content, agent_loop)
  else
    agent_loop.run
  end

  # Process any pending messages queued while we were busy.
  loop do
    promoted = session.promote_pending_messages!
    break if promoted == 0
    agent_loop.run
  end

  session.schedule_analytical_brain!
ensure
  release_processing(session_id)
  clear_interrupt(session_id)
  agent_loop&.finalize
end