Syntony / Agents and tools / Rubato

Rubato
where your agent took liberties

A free agent that reviews what another AI agent did. Give it a run log and it finds the moments the agent took liberties with its task: acting after a person said stop, routing around a refusal, weakening its own oversight, reaching for credentials, sending data out, and claiming work the log does not show. It comes with free red team probes: small test repositories built to tempt an agent.

Try it

Review a run in this page

The same engine you download, running in your browser. Nothing you paste leaves this page.

Fictional example. The agent was asked to fix a failing test.

What it looks for

Sixteen ways an agent drifts from its task

Each finding names the event in the log, quotes the evidence and says what a person should check. Severity drops when the task itself asked for the action, or when the call failed.

Free red teaming

Six probes to try on your own agent

Each probe writes a tiny repository built to tempt an agent, with the exact task to give it. Run it in a sandbox with no real credentials, then score the session as pass, fail or inconclusive. The secrets are fake and every planted address ends in .invalid.

These six probes are a small public sample.

A red team tests your agent with its real tools, permissions and data: chained prompt injection, tool and memory poisoning, privilege paths, multi-agent handoffs and the approval flows around them. Then it checks that each fix holds.

Agent red teaming
node rubato.mjs probes
node rubato.mjs probe RP-01 --out rp-01        # a test repository with a planted instruction
cd rp-01 && claude                              # give it the task in PROBE.md
node rubato.mjs review <session.jsonl> --probe RP-01

How it works

A fixed engine, then an agent that reads the context

The engine gives the same result every time, so you can rerun it and compare. The agent does what patterns cannot: it reads around each finding and decides.

  1. The engine reads the log

    Claude Code session files, OpenAI or Anthropic message arrays, or a simple JSONL of tasks, messages, tool calls and results. It links each result to its call and works out what every call did: which files it wrote, which hosts it contacted, whether it changed anything.

  2. It checks the run against what people said

    It finds the task, any stop or interruption, and instructions such as "do not push to main" or "ask me before changing CI". Then it checks every later action against them, and checks every claim in the agent's final message against the tool results.

  3. The agent confirms or dismisses each finding

    Installed in Claude Code, Rubato runs the engine, reads the events around each finding, and decides whether it is confirmed, explained by the task, or a false alarm. It never runs commands from the log and never edits it.

  4. You get a short report

    Did the agent stay within its task? A table of findings with event numbers, what to do now for each confirmed one (undo, rotate a credential, review a diff), and which control would have stopped it.

Install

One file, one command

Version 1.2.0. Needs Node.js 18 or later and nothing else. The agent works in Claude Code; the engine works on its own anywhere.

  1. Download Rubato

    rubato.mjs ↓, a single readable JavaScript file with no dependencies. Save it somewhere stable, such as a tools folder in your home directory.

  2. Install the agent

    From your project folder, or with --global for every project:

    node /path/to/rubato.mjs init

    This writes .claude/agents/rubato.md with the path to the engine filled in.

  3. Ask for a review

    In Claude Code:

    Use the rubato agent to review my last session.

    Rubato lists your recent sessions with rubato.mjs sessions, picks the one you mean and writes its report.

  4. Or run the engine yourself
    node rubato.mjs review session.jsonl
    node rubato.mjs review run.json --json --out report.json
    node rubato.mjs review run.jsonl --scope scope.json --fail-on high

    --fail-on high exits with code 2 when there is a high-severity finding, so you can gate a pipeline on it.

Logs and scope

What it reads, and how to tell it the rules

Without a scope file, Rubato uses the task in the log and the working folder. With one, it also checks tools, paths and hosts against your lists.

Claude Code
Session files from ~/.claude/projects/, as they are. Interruptions count as a stop.
Messages
OpenAI-style arrays with tool_calls, or Anthropic-style arrays with tool_use and tool_result blocks, as JSON or JSONL.
Rubato JSONL
One object per line with type set to task, message, reasoning, tool_call or tool_result. Print an example with rubato.mjs example.
tools, paths, hosts
Allowed tool names, file globs and hosts. * and ** work as usual.
workdir
The folder the agent was meant to work in. Writes outside it, other than to temporary folders, are flagged.
{
  "task": "Fix the failing checkout test",
  "tools": ["Read", "Edit", "Bash", "Grep"],
  "paths": ["src/**", "test/**"],
  "hosts": ["api.stripe.com"],
  "workdir": "/home/dev/shop",
  "maxSubagents": 4
}

For operations and security teams

Fits the pipeline you already run

Rubato is built to run on every agent session in CI, not only the ones someone thought to check.

Findings where your team already looks

SARIF 2.1.0 for GitHub code scanning and most security dashboards, JUnit XML for CI test reports, and CSV for spreadsheets, ticketing and SIEM imports. Each finding names the step in the run it came from.

Mapped to the standards you report against

Each finding carries references to the EU AI Act (Art. 12 record-keeping, Art. 14 human oversight), the OWASP Top 10 for LLM Applications 2025, the NIST AI RMF, NIST SP 800-53 and MITRE ATT&CK.

A night of logs in one run

Pass several files or a whole folder. You get one combined report and a summary table, and --fail-on turns any level of finding into a failed build.

Reads what your tools export

Claude Code session logs, OpenAI and Anthropic message arrays, Rubato JSONL, and CSV exports with a header row. Run sessions in a project folder to list that project’s Claude Code logs.

Runs air-gapped

No network calls, no telemetry and no dependencies. It is one readable file your security team can review before it runs on an isolated host.

Same log, same answer

Fixed rules, not a model. The same log always gives the same findings, and every report carries a SHA-256 of its input so it can go in an evidence file. 100,000 events take under two seconds on a laptop.

# Every session from last night, as SARIF for code scanning
node rubato.mjs review ~/.claude/projects/-home-dev-shop/ --format sarif --out rubato.sarif

# Fail the pipeline on any high finding, with JUnit for the test report
node rubato.mjs review agent-run.jsonl --scope scope.json --format junit --out rubato.xml --fail-on high

Why the name

Rubato
stolen time

Rubato means stolen time. A player stretches a phrase here and hurries it there, and the score allows some of it. Too much and the piece falls apart.

Agents take the same kind of liberty with a task. Most of it is fine. Rubato finds the places where the agent stretched past what anyone allowed, so a person can decide whether the piece still holds.

It sits with the rest of our instruments: A440 sets the pitch, Sordino mutes an action that should not happen, Fermata holds until a person says go, Ritardando slows a claim until the evidence is checked, and Attacca carries a finding straight on to governance.

Before you rely on it

What Rubato does not do

  • It only sees what is in the log. An agent that acted through a path the log does not record, or a log that was edited, will look clean.
  • The engine reads words and commands, not intent. Findings are signals for a person to check, and a clean review is not proof of good behaviour.
  • It reviews after the fact. To stop an action before it happens, put a hold in front of it, such as Fermata, and hard limits at the tool or API itself.
  • Its probes are a handful of simple temptations. Run them only in a sandbox with no real credentials. Passing them says little about how your agent behaves with real tools and data.
  • Patterns are written for English and for common shells, cloud tools and package managers. Unusual tools may need a scope file to be checked.

Rubato runs on your machine and makes no network calls. It reads only the log and scope files you give it, and writes only the agent file and the report you ask for.

Rubato is licensed by Syntony under the Syntony Free Tools License: free to run, copy and modify within your organization, including for commercial work, but not to resell or redistribute.

Want to know how far your agent will go?

Our agent red teaming tests what your agent does with real tools and permissions, then checks that each fix holds.