Module: ActionAgent

Defined in:
lib/action_agent.rb,
lib/action_agent.rb,
lib/action_agent/engine.rb,
lib/action_agent/version.rb,
app/models/action_agent/agent.rb,
lib/action_agent/compatibility.rb,
app/models/action_agent/api_key.rb,
app/models/action_agent/agent_run.rb,
app/models/action_agent/evaluation.rb,
app/models/action_agent/sandbox_run.rb,
app/models/action_agent/agent_memory.rb,
app/models/action_agent/provider_key.rb,
app/jobs/action_agent/application_job.rb,
app/jobs/action_agent/sandbox_run_job.rb,
app/models/action_agent/agent_context.rb,
app/models/action_agent/agent_message.rb,
app/models/action_agent/agent_version.rb,
app/models/action_agent/model_pricing.rb,
app/services/action_agent/mcp_catalog.rb,
app/models/action_agent/agent_template.rb,
app/models/action_agent/evaluation_run.rb,
app/models/action_agent/sandbox_session.rb,
app/models/action_agent/telemetry_trace.rb,
app/services/action_agent/agent_toolbox.rb,
app/models/action_agent/agent_generation.rb,
app/models/action_agent/recording_action.rb,
app/models/concerns/action_agent/ownable.rb,
app/services/action_agent/tool_discovery.rb,
app/jobs/action_agent/agent_execution_job.rb,
app/jobs/action_agent/sandbox_cleanup_job.rb,
app/jobs/action_agent/trace_retention_job.rb,
app/models/action_agent/session_recording.rb,
app/queries/action_agent/agent_executions.rb,
app/services/action_agent/agent_registrar.rb,
app/services/action_agent/agent_scorecard.rb,
app/models/action_agent/agent_memory_entry.rb,
app/models/action_agent/application_record.rb,
app/models/action_agent/recording_snapshot.rb,
app/jobs/action_agent/sandbox_provision_job.rb,
app/models/action_agent/sandbox_instance_tier.rb,
lib/generators/action_agent/install_generator.rb,
app/controllers/action_agent/traces_controller.rb,
app/models/concerns/action_agent/adapter_aware.rb,
app/services/action_agent/mock_sandbox_backend.rb,
app/services/action_agent/sandbox_orchestrator.rb,
app/controllers/action_agent/api/mcp_controller.rb,
app/services/action_agent/playwright_mcp_client.rb,
app/controllers/action_agent/api/base_controller.rb,
app/serializers/action_agent/interaction_preview.rb,
app/controllers/action_agent/api/tools_controller.rb,
app/controllers/action_agent/dashboard_controller.rb,
app/services/action_agent/agent_execution_service.rb,
app/controllers/action_agent/api/agents_controller.rb,
app/controllers/action_agent/api/traces_controller.rb,
app/jobs/action_agent/process_telemetry_traces_job.rb,
app/services/action_agent/mcp_recording_middleware.rb,
app/controllers/action_agent/api/metrics_controller.rb,
app/controllers/action_agent/application_controller.rb,
app/models/concerns/action_agent/session_recordable.rb,
app/services/action_agent/evaluation_runner_service.rb,
app/services/action_agent/session_recording_service.rb,
app/controllers/action_agent/api/api_keys_controller.rb,
app/controllers/action_agent/api/analytics_controller.rb,
app/controllers/action_agent/api/sandboxes_controller.rb,
app/controllers/action_agent/api/templates_controller.rb,
app/serializers/action_agent/agent_message_serializer.rb,
app/controllers/action_agent/api/agent_runs_controller.rb,
app/controllers/action_agent/api/evaluations_controller.rb,
app/controllers/action_agent/api/mcp_servers_controller.rb,
app/serializers/action_agent/telemetry_trace_serializer.rb,
app/controllers/action_agent/api/interactions_controller.rb,
app/controllers/action_agent/api/provider_keys_controller.rb,
app/controllers/action_agent/api/trace_reports_controller.rb,
app/serializers/action_agent/trace_interaction_serializer.rb,
app/controllers/action_agent/api/instance_tiers_controller.rb,
app/controllers/action_agent/api/provider_models_controller.rb,
app/controllers/action_agent/api/session_recordings_controller.rb

Overview

Transitional aliases for the names this engine shipped under when it lived inside the activeagent gem (<= 1.1.0).

Three of these matter for more than tidiness:

* ActiveAgent::ProcessTelemetryTracesJob — Active Job serializes the class
name into the queue payload, so a job enqueued before the upgrade is
dequeued after it and must still resolve to something.
* ActiveAgent::TelemetryTrace — apps subclass it (the activeagents.ai
platform does) and it is referenced from initializers.
* ActiveAgent::Dashboard — every existing initializer calls
ActiveAgent::Dashboard.configure.

Each warns once through the deprecator and forwards to the new constant. Remove in the next major.

Defined Under Namespace

Modules: AdapterAware, Api, Compatibility, InteractionPreview, Ownable, SessionRecordable Classes: Agent, AgentContext, AgentExecutionJob, AgentExecutionService, AgentExecutions, AgentGeneration, AgentMemory, AgentMemoryEntry, AgentMessage, AgentMessageSerializer, AgentRegistrar, AgentRun, AgentScorecard, AgentTemplate, AgentToolbox, AgentVersion, ApiKey, ApplicationController, ApplicationJob, ApplicationRecord, DashboardController, Engine, Evaluation, EvaluationRun, EvaluationRunnerService, InstallGenerator, McpCatalog, McpRecordingMiddleware, MockSandboxBackend, ModelPricing, PlaywrightMcpClient, ProcessTelemetryTracesJob, ProviderKey, RecordingAction, RecordingSnapshot, SandboxCleanupJob, SandboxInstanceTier, SandboxOrchestrator, SandboxProvisionJob, SandboxRun, SandboxRunJob, SandboxSession, SessionRecording, SessionRecordingService, TelemetryTrace, TelemetryTraceSerializer, ToolDiscovery, TraceInteractionSerializer, TraceRetentionJob, TracesController

Constant Summary collapse

VERSION =
"1.2.2"

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.account_classString?

Class name for the Account model (multi-tenant mode)

Returns:

  • (String, nil)


121
122
123
# File 'lib/action_agent.rb', line 121

def 
  @account_class
end

.agent_polymorphic_nameString?

Value stored in polymorphic *_type columns for dashboard agents (agent_memories.memorable_type, agent_contexts.contextable_type). Unset means the class name. A host app whose existing rows were written under its own constant sets its name here.

Returns:

  • (String, nil)


270
271
272
# File 'lib/action_agent.rb', line 270

def agent_polymorphic_name
  @agent_polymorphic_name
end

.agent_scope_resolverProc?

The agents an owner can reach. Defaults to the ones that owner owns. A host app where those differ — the platform's agents belong to users while its API keys belong to accounts — supplies its own scope.

Returns:

  • (Proc, nil)


160
161
162
# File 'lib/action_agent.rb', line 160

def agent_scope_resolver
  @agent_scope_resolver
end

.authentication_methodProc?

Authentication method to call on controllers

Returns:

  • (Proc, nil)

    A proc that receives the controller instance



113
114
115
# File 'lib/action_agent.rb', line 113

def authentication_method
  @authentication_method
end

.base_controller_classString

Deprecated.

Never consumed — dashboard controllers inherit ActionController::Base. Retained as a no-op so existing initializers that set it keep booting; remove in the next major.

Returns:

  • (String)


197
198
199
# File 'lib/action_agent.rb', line 197

def base_controller_class
  @base_controller_class
end

.current_account_methodSymbol?

Method to call on controller to get current account (multi-tenant mode). Only usable when the host app has mixed that method into the engine's controllers; otherwise use current_account_resolver.

Returns:

  • (Symbol, nil)


131
132
133
# File 'lib/action_agent.rb', line 131

def 
  @current_account_method
end

.current_account_resolverProc?

Resolves the current tenant from the controller. See current_user_resolver.

Returns:

  • (Proc, nil)


148
149
150
# File 'lib/action_agent.rb', line 148

def 
  @current_account_resolver
end

.current_user_methodSymbol?

Method to call on controller to get current user. Same caveat as current_account_method — see current_user_resolver.

Returns:

  • (Symbol, nil)


136
137
138
# File 'lib/action_agent.rb', line 136

def current_user_method
  @current_user_method
end

.current_user_resolverProc?

Resolves the signed-in user from the controller. Preferred over current_user_method: the engine's controllers are their own base class, so a host app's current_user helper is not on them unless the app deliberately put it there.

Returns:

  • (Proc, nil)


143
144
145
# File 'lib/action_agent.rb', line 143

def current_user_resolver
  @current_user_resolver
end

.encrypt_credentialsBoolean

Whether API keys and provider credentials are encrypted at rest with Active Record Encryption. On by default, which requires the host app to have run rails db:encryption:init. Turning it off stores those secrets in plain text — a deliberate downgrade, never a default.

Returns:

  • (Boolean)


263
264
265
# File 'lib/action_agent.rb', line 263

def encrypt_credentials
  @encrypt_credentials
end

.execution_enabledBoolean

Whether the dashboard may execute agents against real providers. Disable to run the dashboard as a read-only observability surface.

Returns:

  • (Boolean)


229
230
231
# File 'lib/action_agent.rb', line 229

def execution_enabled
  @execution_enabled
end

.ingest_api_keyString?

Bearer token required by the ingest API in single-tenant mode. When unset the local ingest endpoint accepts unauthenticated posts, so set it whenever the mount is reachable beyond your own machine. (Multi-tenant mode authenticates per-account keys instead.)

Returns:

  • (String, nil)


191
192
193
# File 'lib/action_agent.rb', line 191

def ingest_api_key
  @ingest_api_key
end

.layoutString?

Custom layout for the dashboard

Returns:

  • (String, nil)


172
173
174
# File 'lib/action_agent.rb', line 172

def layout
  @layout
end

.multi_tenantBoolean

Enable multi-tenant mode (requires account association)

Returns:

  • (Boolean)


117
118
119
# File 'lib/action_agent.rb', line 117

def multi_tenant
  @multi_tenant
end

.provider_credentials_resolverProc?

Resolves LLM provider credentials for a run. Receives (owner, provider_name) and returns a Hash merged into the agent's generation options (e.g. { access_token: "sk-..." } or { host: "http://localhost:11434&quot; }), or nil to fall back to the host app's config/active_agent.yml.

Unset means config/active_agent.yml is the only source, which is what a self-hosted install wants.

Returns:

  • (Proc, nil)


218
219
220
# File 'lib/action_agent.rb', line 218

def provider_credentials_resolver
  @provider_credentials_resolver
end

.quota_checkerProc?

Called before each run/trace-ingest to enforce host-app limits. Receives (owner, kind) where kind is :execution or :trace_ingest, and returns nil to allow, or to deny: a message String, or a Hash merged into the response so the app can surface its own usage numbers. Denials surface as HTTP 402 (execution) / 429 (ingest).

Unset means unlimited, which is what a self-hosted install wants.

Returns:

  • (Proc, nil)


207
208
209
# File 'lib/action_agent.rb', line 207

def quota_checker
  @quota_checker
end

.sandbox_backendsHash{String => String}

Extra sandbox backends contributed by the host app, as { "cloud_run" => "CloudRunService" }. The engine ships :mock and :local (Docker); cloud backends live in the app that operates them.

Returns:

  • (Hash{String => String})


224
225
226
# File 'lib/action_agent.rb', line 224

def sandbox_backends
  @sandbox_backends
end

.sandbox_limitsHash?

Custom sandbox limits (overrides defaults)

Returns:

  • (Hash, nil)


180
181
182
# File 'lib/action_agent.rb', line 180

def sandbox_limits
  @sandbox_limits
end

.sandbox_serviceSymbol

Sandbox service type (:local, :cloud_run, :kubernetes)

Returns:

  • (Symbol)


176
177
178
# File 'lib/action_agent.rb', line 176

def sandbox_service
  @sandbox_service
end

.storage_serviceObject?

Storage service for screenshots/snapshots

Returns:

  • (Object, nil)

    Object responding to #signed_url_for and #fetch_snapshot



184
185
186
# File 'lib/action_agent.rb', line 184

def storage_service
  @storage_service
end

.table_name_prefixObject



19
20
21
22
# File 'lib/action_agent.rb', line 19

def table_name_prefix
  global = defined?(::ActiveRecord::Base) ? ::ActiveRecord::Base.table_name_prefix : ""
  "#{global}#{@table_name_prefix ||= "active_agent_"}"
end

.tenant_resolverProc?

The tenant whose telemetry relates to owner. Traces belong to accounts while agents may belong to users, so the two are not always the same record and a host app says how to get from one to the other.

Returns:

  • (Proc, nil)


154
155
156
# File 'lib/action_agent.rb', line 154

def tenant_resolver
  @tenant_resolver
end

.trace_model_classString?

Custom trace model class (for host app overrides)

Returns:

  • (String, nil)


164
165
166
# File 'lib/action_agent.rb', line 164

def trace_model_class
  @trace_model_class
end

.trace_owner_resolverProc?

Maps an ingested trace to the owner that its newly observed agents belong to. Defaults to the trace's account in multi-tenant mode and to nobody in single-tenant mode. A host app whose agents hang off a different record (the platform's hang off the account's owning user) supplies its own mapping.

Returns:

  • (Proc, nil)


249
250
251
# File 'lib/action_agent.rb', line 249

def trace_owner_resolver
  @trace_owner_resolver
end

.trace_retentionActiveSupport::Duration, ...

How long telemetry traces are kept before TraceRetentionJob prunes them. A Duration applies to every trace; a callable receives each owner and returns that owner's window (nil keeps everything). Unset means nothing is ever deleted.

Returns:

  • (ActiveSupport::Duration, Proc, nil)


256
257
258
# File 'lib/action_agent.rb', line 256

def trace_retention
  @trace_retention
end

.upgrade_urlString?

Where the dashboard's upgrade CTAs should send people. Unset in a self-hosted install, where there is nothing to upgrade, and the CTAs say so instead of linking nowhere.

Returns:

  • (String, nil)


235
236
237
# File 'lib/action_agent.rb', line 235

def upgrade_url
  @upgrade_url
end

.usage_recorderProc?

Called after the dashboard performs a metered action, as (owner, kind) — the counterpart to quota_checker, for host apps that track usage against a plan. Unset means nothing is counted.

Returns:

  • (Proc, nil)


241
242
243
# File 'lib/action_agent.rb', line 241

def usage_recorder
  @usage_recorder
end

.use_inertiaBoolean

Enable React/Inertia frontend instead of ERB

Returns:

  • (Boolean)


168
169
170
# File 'lib/action_agent.rb', line 168

def use_inertia
  @use_inertia
end

.user_classString?

Class name for the User model

Returns:

  • (String, nil)


125
126
127
# File 'lib/action_agent.rb', line 125

def user_class
  @user_class
end

Class Method Details

.agent_modelClass

Returns the agent model class to use.

Returns:

  • (Class)

    The agent model class



348
349
350
# File 'lib/action_agent.rb', line 348

def agent_model
  ActionAgent::Agent
end

.agents_for(owner) ⇒ ActiveRecord::Relation

The agents owner can reach.

Returns:

  • (ActiveRecord::Relation)


339
340
341
342
343
# File 'lib/action_agent.rb', line 339

def agents_for(owner)
  return agent_model.for_owner(owner) if agent_scope_resolver.nil?

  agent_scope_resolver.call(owner) || agent_model.none
end

.configure {|config| ... } ⇒ Object

Configures the dashboard.

Yields:

  • (config)

    Configuration block



365
366
367
# File 'lib/action_agent.rb', line 365

def configure
  yield self
end

.deprecatorObject

Deprecation warnings for this gem, routed through Rails' machinery so a host app can silence or escalate them like any other.



107
108
109
# File 'lib/action_agent.rb', line 107

def deprecator
  @deprecator ||= ActiveSupport::Deprecation.new("2.0", "ActionAgent")
end

.execution_enabled?Boolean

Returns whether agent execution is permitted.

Returns:

  • (Boolean)


282
283
284
# File 'lib/action_agent.rb', line 282

def execution_enabled?
  @execution_enabled != false
end

.multi_tenant?Boolean

Returns whether multi-tenant mode is enabled.

Returns:

  • (Boolean)


275
276
277
# File 'lib/action_agent.rb', line 275

def multi_tenant?
  @multi_tenant == true
end

.owner_classClass?

Returns the configured owner class: the Account in multi-tenant mode, the User otherwise. Nil when the host app configured neither, which is the single-user self-hosted case.

Returns:

  • (Class, nil)


357
358
359
360
# File 'lib/action_agent.rb', line 357

def owner_class
  name = multi_tenant? ?  : user_class
  name&.safe_constantize
end

.provider_credentials(owner, provider) ⇒ Hash

Provider options for owner, or {} when the host app has none and config/active_agent.yml should be used as-is.

Returns:

  • (Hash)


308
309
310
311
312
313
314
315
# File 'lib/action_agent.rb', line 308

def provider_credentials(owner, provider)
  return {} if provider_credentials_resolver.nil?

  provider_credentials_resolver.call(owner, provider) || {}
rescue StandardError => e
  Rails.logger.warn("[ActionAgent] provider credential lookup failed: #{e.message}")
  {}
end

.quota_denial(owner, kind) ⇒ String, ...

Asks the host app whether owner may perform kind.

Returns:

  • (String, Hash, nil)

    denial message or payload, nil when allowed



298
299
300
301
302
# File 'lib/action_agent.rb', line 298

def quota_denial(owner, kind)
  return nil if quota_checker.nil?

  quota_checker.call(owner, kind)
end

.record_usage(owner, kind) ⇒ Object

Tells the host app that owner performed kind. Never raises: a bookkeeping failure must not fail the action that was already taken.



288
289
290
291
292
293
# File 'lib/action_agent.rb', line 288

def record_usage(owner, kind)
  usage_recorder&.call(owner, kind)
rescue StandardError => e
  Rails.logger.warn("[ActionAgent] usage recording failed: #{e.message}")
  nil
end

.reset!Object

Reset configuration to defaults



370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
# File 'lib/action_agent.rb', line 370

def reset!
  @authentication_method = nil
  @multi_tenant = false
  @account_class = nil
  @user_class = nil
  @current_account_method = nil
  @current_user_method = nil
  @current_user_resolver = nil
  @current_account_resolver = nil
  @agent_scope_resolver = nil
  @tenant_resolver = nil
  @trace_model_class = nil
  @use_inertia = false
  @layout = nil
  @sandbox_service = :local
  @sandbox_limits = nil
  @storage_service = nil
  @ingest_api_key = nil
  @base_controller_class = "ActionController::Base" # deprecated no-op
  @quota_checker = nil
  @provider_credentials_resolver = nil
  @sandbox_backends = {}
  @execution_enabled = true
  @table_name_prefix = "active_agent_"
  @agent_polymorphic_name = nil
  @encrypt_credentials = true
  @trace_retention = nil
  @trace_owner_resolver = nil
  @usage_recorder = nil
  @upgrade_url = nil
end

.solid_agent_auto_context_keywordObject

Which keyword the installed solid_agent uses to switch has_context's auto-context off: contextable: up to 0.1, contextual: from 0.2. The gemspec floor admits both, and passing the wrong one raises an ArgumentError deep inside a run rather than at boot — so AgentExecutionService asks rather than assumes.

Covered by test/integration/solid_agent, which runs this engine against solid_agent's main branch as well as the released gem.



32
33
34
35
36
37
38
39
40
41
# File 'lib/action_agent.rb', line 32

def solid_agent_auto_context_keyword
  @solid_agent_auto_context_keyword ||= begin
    keywords = ::SolidAgent::HasContext::ClassMethods
      .instance_method(:has_context).parameters
      .select { |type, _| [ :key, :keyreq ].include?(type) }
      .map(&:last)

    keywords.include?(:contextual) ? :contextual : :contextable
  end
end

.tenant_for(owner) ⇒ Object

The tenant owner belongs to. Identity unless the host app says otherwise, which is right for every single-tenant install.



330
331
332
333
334
# File 'lib/action_agent.rb', line 330

def tenant_for(owner)
  return owner if tenant_resolver.nil?

  tenant_resolver.call(owner)
end

.trace_modelClass

Returns the trace model class to use.

Returns:

  • (Class)

    The trace model class



320
321
322
323
324
325
326
# File 'lib/action_agent.rb', line 320

def trace_model
  if trace_model_class
    trace_model_class.constantize
  else
    ActionAgent::TelemetryTrace
  end
end