Setup & Generators
Set up the admin AI copilot for your Rails app.
Installation
Add to your Gemfile:
gem "ask-rails-harness"
Run:
bundle install
rails generate ask_rails_harness:install
The generator creates:
| File | Purpose |
|---|---|
config/initializers/ask_rails_harness.rb | Provider and agent configuration |
db/migrate/*_create_ask_sessions.rb | Session persistence table |
db/migrate/*_create_ask_audit_logs.rb | Audit log table (tool call recording) |
app/tools/ | Directory for custom tools (with .keep) |
Configuration
# config/initializers/ask_rails_harness.rb
Ask::Rails::Harness.configure do |config|
config.default_model = ENV.fetch("ASK_DEFAULT_MODEL", "gpt-4o")
config.max_turns = ENV.fetch("ASK_MAX_TURNS", 25).to_i
end
Available options
| Option | Default | Description |
|---|---|---|
default_model | "gpt-4o" (or ASK_DEFAULT_MODEL env) | LLM model for agent sessions |
max_turns | 25 (or ASK_MAX_TURNS env) | Max think-call-execute cycles per session |
tool_concurrency | 5 | Number of tools the agent can run in parallel |
system_prompt | nil (built-in default) | Custom system prompt for the agent |
persistence_adapter | nil (in-memory) | A Persistence instance for saving sessions |
current_user | nil | A proc returning a hash of user context attached to every audit log entry |
max_session_age | nil | Auto-delete sessions older than this many seconds (e.g. 7.days) |
max_sessions | nil | Max sessions to keep (deletes oldest when exceeded) |
Session Cleanup
Ask::Rails::Harness.configure do |config|
# Keep at most 1000 sessions, delete sessions older than 7 days
config.max_session_age = 7 * 24 * 3600
config.max_sessions = 1000
end
Cleanup runs automatically when agent_session is called. You can also run it manually:
rails ask_rails_harness:cleanup
Or from Ruby:
Ask::Rails::Harness.cleanup!
Per-Environment Permissions
Control access modes and command allowlists per Rails environment:
Ask::Rails::Harness.configure do |config|
# Production is read-only with strict command restrictions
config.environment :production do |env|
env.mode = :read_only
env.allowed_commands = [/^rails routes/, /^rails log/]
env.denied_commands = [/rm/, /dropdb/, /curl/]
end
# Staging asks before changes
config.environment :staging do |env|
env.mode = :ask_before_changes
env.allowed_commands = [/^rails /, /^git status/]
end
# Development stays unrestricted (default)
config.environment :development do |env|
env.mode = :full_access
end
end
Available modes:
| Mode | Effect |
|---|---|
:full_access | All tools allowed, no approval needed |
:read_only | Write/edit/bash/destroy tools blocked |
:ask_before_changes | Write/edit/bash/destroy require approval |
When a mode is set, agent_session automatically creates a Permissions extension that enforces the mode at the agent loop level. The command allowlist rules apply additionally to the RunCommand tool.
If no environment config matches Rails.env, the global allowed_commands and denied_commands are used as fallback.
Audit Log
Every tool call is automatically recorded in the ask_audit_logs table with:
- Intent — which tool was called and with what params (sensitive keys like
password,token,api_keyare redacted) - Outcome — success/error/rejected status and duration
- User context — who initiated the call (if
current_useris configured)
The audit log is append-only and never stores full result data — only metadata (row counts, exit statuses, file sizes).
Subscribe to audit events in your app:
ActiveSupport::Notifications.subscribe("audit_log.ask_rails_harness") do |event|
if event.payload[:tool_name] == "RunCommand" && event.payload[:status] == "error"
SlackNotifier.notify("Agent command failed: #{event.payload[:error_message]}")
end
end
Provider configuration
Set your API key in Rails credentials:
rails credentials:edit
openai:
api_key: sk-your-key-here
Or use environment variables:
export OPENAI_API_KEY="sk-your-key-here"
Customizing providers
Ask::Rails::Harness.configure do |config|
config.default_model = "claude-sonnet-4"
end
Quick Start
session = Ask::Rails::Harness.agent_session
response = session.run("What models do we have?")
The session comes pre-configured with the default model and all Rails-aware tools.
Components
When you install ask-rails-harness, these components are activated:
| Component | Purpose |
|---|---|
| Railtie | Configures providers, discovers tools and service gems on boot |
| Session Factory | Ask::Rails::Harness.agent_session creates a pre-configured agent session |
| Service Discovery | Auto-discovers installed ask-* service gems |
| Rails Tools | Database, filesystem, and code navigation tools |
| Persistence | ActiveRecord adapter for session save/load/resume |
| Generators | Migration, initializer, and tool scaffolding |
Service Discovery
ask-rails-harness automatically discovers installed service gems. If you add ask-github to your Gemfile, the agent knows how to interact with GitHub without additional configuration.