robot_lab-audit

A RobotLab extension gem that writes a structured execution audit log to SQLite. Every network run, robot invocation, and tool call is recorded as a row — timestamps, inputs, outputs, errors, and duration — so you can query what happened after the fact.

Plugs into RobotLab's Hook system. Zero changes to your robots or networks; opt in by calling RobotLab::Audit.enable.

Installation

Add to your Gemfile:

gem "robot_lab-audit"

Or install directly:

gem install robot_lab-audit

Usage

require "robot_lab"
require "robot_lab/audit"

RobotLab::Audit.enable(db_path: "~/.robot_lab/audit.db")

# All network runs and robot runs from here on are logged automatically.
network = RobotLab.create_network(...)
network.run(message: "do something")

The database file and any missing parent directories are created automatically.

What gets logged

Table One row per Key columns
network_runs Network#run call run_id, network_name, input, result, error_*, started_at, finished_at, duration_ms
audit_events Robot#run or Tool#call run_id, event_type, robot_name, tool_name, input, output, error_*, started_at, finished_at, duration_ms

event_type is "robot_run" or "tool_call". All input/output values are JSON. Timestamps are ISO 8601 with millisecond precision.

All events within a single Network#run share the same run_id, so you can reconstruct the full execution trace for any network run.

Standalone Robot#run calls (outside a network) are also recorded; their run_id column will be nil.

Querying the log

EventLog provides three convenience methods:

log = RobotLab::Audit::Hook.event_log

log.network_runs(limit: 100)       # recent network runs, newest first
log.events_for("some-run-id")      # all events for one run, ordered by time
log.recent_errors(limit: 50)       # events where error_class is not null

Each method returns an array of hashes keyed by column name.

You can also query the SQLite database directly with any SQL tool:

sqlite3 ~/.robot_lab/audit.db \
  "SELECT event_type, robot_name, tool_name, duration_ms, error_class
   FROM audit_events
   WHERE run_id = 'some-run-id'
   ORDER BY started_at;"

Scoping to a robot or network

RobotLab::Audit.enable registers the hook globally. To limit logging to a specific robot or network, register the hook directly on that object instead:

RobotLab::Audit::Hook.event_log = RobotLab::Audit::EventLog.new(db_path: "audit.db")

robot.on(RobotLab::Audit::Hook)
# or
network.on(RobotLab::Audit::Hook)

Schema

CREATE TABLE network_runs (
  id            INTEGER PRIMARY KEY AUTOINCREMENT,
  run_id        TEXT    NOT NULL UNIQUE,
  network_name  TEXT,
  input         TEXT,
  result        TEXT,
  error_class   TEXT,
  error_message TEXT,
  started_at    TEXT    NOT NULL,
  finished_at   TEXT,
  duration_ms   REAL
);

CREATE TABLE audit_events (
  id            INTEGER PRIMARY KEY AUTOINCREMENT,
  run_id        TEXT,
  event_type    TEXT NOT NULL,
  robot_name    TEXT,
  tool_name     TEXT,
  input         TEXT,
  output        TEXT,
  error_class   TEXT,
  error_message TEXT,
  started_at    TEXT NOT NULL,
  finished_at   TEXT,
  duration_ms   REAL
);

Development

bundle install
bundle exec rake test       # run tests
bundle exec rake            # default: test
bin/console                 # IRB with gem loaded

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/MadBomber/robot_lab-audit.

License

MIT. See LICENSE.txt.