Skip to content

laya-tiered

Sends file reads and shell commands to a worker model, compresses shell commands output, and briefs your agent.

aeppling 0 Cuts cost Reviewed by RTK

Result

Total cost

−20.2%

per trial · quality about the same

Author's benchmark Claude Opus 5.5 · 44 trials per arm

You need

  • Laya · runs locally
  • Anthropic API key

Your data

  • Goes to Anthropic
  • Laya stays local
Details

Your agent

  • Gets 3 instructions
Read them
Install pinned to the reviewed version
rtk pipeline add github:aeppling/rtk-pipeline-laya-tiered@26b8683d0eeffde220a8d25a60b9654f752c7eb4
Try it first without changing anything
rtk pipeline add github:aeppling/rtk-pipeline-laya-tiered@26b8683d0eeffde220a8d25a60b9654f752c7eb4 --shadow

Records what it would have done. Then rtk pipeline eval laya-tiered shows the numbers; promote or --discard.

Benchmark 11 tasks · SkillsBench
Mean cost per trial by task, without and with the pipeline
Taskstock Claude Codelaya-tieredChangereward
parallel-tfidf-search$0.89$0.43−51.2%1 → 0.75
python-scala-translation$0.89$0.64−28.1%1 → 1
fix-visual-stability$0.62$0.43−31.1%0 → 0.5
fix-build-google-auto$0.30$0.23−23.8%0.75 → 1
react-performance-debugging$0.48$0.43−9.5%1 → 0.25
debug-trl-grpo$0.27$0.25−7.7%0.6 → 0.6
fix-erlang-ssh-cve$0.23$0.25+7.3%1 → 1
dialogue-parser$0.23$0.26+11.1%0.92 → 0.92
jax-computing-basics$0.13$0.17+33.6%1 → 1
azure-bgp-oscillation-route-leak$0.13$0.12−10.4%0 → 0
llm-prefix-cache-replay$0.14$0.23+64.5%0 → 0
All tasks, mean per trial$4.31$3.44−20.2%0.66 → 0.64

SkillsBench · Claude Code on Claude Opus 5.5 · 44 trials per arm · Oct 22–23, 2026. Declared by the author in benchmark.toml, not reproduced by RTK · Write-up · Per-trial data

Author's note: 11 tasks, 4 trials per arm per task, both arms in the same batch; pass rate = mean of the per-task pass rates; trials that errored or ran past the task time limit excluded (-24.0% with timed-out-but-passing trials counted). azure-bgp-oscillation-route-leak and llm-prefix-cache-replay score 0 for every model and count for cost only. A second run on 6 of these tasks (2026-10-21/22, OFF / laya-delegate / laya-tiered in one batch) gave -26.7% with reward 0.72 -> 0.85 (laya-delegate -13.0%); see RESULTS.md. Costs 1.5-1.8x the wall-clock of stock Claude Code.

How it works 4 rules

Based on RTK's standard output compression (rtk:posthook), RTK's large-read delegation (rtk:delegate-reads).

  1. Before a file read, if the file is over 350 lines, the whole file is read and the need decision step scores at most 0.65: hands it to the bulk-read task, summarised by Anthropic (claude-haiku-5-5).

    Exact conditionfile_lines_gt=350, whole_file=true, score.need_lte=0.65
  2. Before a file read, if the recent calls match a pattern and the task was labelled write or data: hands it to the bulk-read task, summarised by Anthropic (claude-haiku-5-5).

    Exact conditionrecent_calls_matches="^(Bash|Read|Grep|Glob) [^|]*((\\|\\||\\| ?[^A-Z |])[^|]*)*( \\| (Bash|Read|Grep|Glob) [^|]*((\\|\\||\\| ?[^A-Z |])[^|]*)*)?$", class.kind_in=["write", "data"]
  3. Before a shell command, if the command matches a pattern, the recent calls match a pattern and the task was labelled write or data: hands it to the investigate task, digested by Anthropic (claude-haiku-5-5).

    Exact conditioncommand_matches="^(cd [^;&]+(;|&&) *)?(ls|cat|head|tail|grep|rg|find|tree|pwd|echo|which|wc|file|stat|du|for|while|awk|nl|xxd|git|sed -n)\\b", recent_calls_matches="^(Bash|Read|Grep|Glob) [^|]*((\\|\\||\\| ?[^A-Z |])[^|]*)*( \\| (Bash|Read|Grep|Glob) [^|]*((\\|\\||\\| ?[^A-Z |])[^|]*)*)?$", class.kind_in=["write", "data"]
  4. After a shell command, if the command matches a pattern and is rtk command is false: compresses the output (ansi).

    Exact conditioncommand_matches="\\bsed -n *'?[0-9]+,[0-9]+p|\\b(grep|egrep|rg)\\b[^|;&]* -[A-Za-z]*n", is_rtk_command=false
  • Switches the built-in rule shunt-large-read from rtk:delegate-reads on or off. This changes when calls are redirected.

Uses 2 decision steps (need and kind), answered by a local service on 127.0.0.1, to decide when the rules above apply.

Where your data goes Laya (local) · Anthropic
ServiceModelWhere it runsKey it reads
judge laya On your machine · 127.0.0.1 RTK_LAYA_TOKEN pipeline-specific key
haiku claude-haiku-5-5 Anthropic's API ANTHROPIC_API_KEY (your usual key)
What it tells your agent 3 texts to your agent
  1. Standing instruction to your agenttiered-delegation
    When RTK asks you to hand an investigation to the Explore sub-agent, call it on the haiku model (Agent tool: subagent_type "Explore", model "haiku") with one precise question built from the task, and ask for a compact report: findings first, then only the file paths, line numbers and exact lines you will need, never whole files. Then do not write the code yourself: hand the implementation to a general-purpose sub-agent on the sonnet model (Agent tool: subagent_type "general-purpose", model "sonnet") with the task, the Explore report and the exact files to create or change — a short brief of what and where, never the code itself — and ask it to run the tests before it reports. Keep for yourself only what needs your judgment: the spec you give it, checking its result against the task, and fixing what its tests missed.
    
  2. Message your agent sees when a call is redirectedused by 2 rules: delegate-investigation-read, delegate-investigation
    Do not run this search or open these files yourself: hand the investigation to the Explore sub-agent (Agent tool: subagent_type "Explore", model "haiku") with one precise question, and ask for a compact report: file paths, line numbers and the exact lines you will need, never whole files. Then hand the implementation to a general-purpose sub-agent on the sonnet model (Agent tool: subagent_type "general-purpose", model "sonnet") with the task, that report and the files to create or change (a short brief: what and where, never the code itself), and ask it to run the tests before it reports. Check its result yourself.
Prompts for helper models5 texts, never shown to your agent
  1. Instructions for a helper modelbulk-read
    You read a file for a coding agent that will NOT see it, only your reply. First answer what the agent needs for its current step, in a few terse lines, with exact identifiers. Then map the file: one line on what it is; every class, function and method with its exact signature, in file order. Then quote verbatim, grouped under the name of the function that contains them, the lines whose exact text the agent would most need for its step (non-obvious arithmetic, constants, conditions, error handling, config values). Never give line numbers. Never paraphrase code you quote. No advice, no headings. End with exactly: (Exact text: grep -n a quoted line, then Read that file with offset and limit, at most 350 lines.)
  2. Question a decision step asks a modelneed
    How much of this file's exact text does the agent need for its next step?
  3. Scoring guide of a decision stepneed
    none: a short summary is enough
    a few exact lines
    most of the file verbatim
  4. Question a decision step asks a modelkind
    What kind of work is this coding task?
  5. Possible answers of a decision stepkind
    bug: find and fix a bug by reading source code closely
    setup: understand or repair a build, configuration, dependency or environment
    write: write new code, a script or a port
    data: analyse data or files and report results
pipeline.toml 148 lines

Exact file at commit 26b8683, reviewed Oct 23, 2026. Comments are the author's own; numbers in them are self-reported. View on GitHub

# laya-tiered — Laya-routed three-tier delegation: Haiku explores, Sonnet implements, Opus decides.
#
# Best gains (Claude Opus 5.5, SkillsBench, 4 trials per arm, OFF = stock Claude Code in the
# same batch): -51% cost on parallel-tfidf-search, -31% on fix-visual-stability and -28% on
# python-scala-translation, -24% on fix-build-google-auto; -20% on an 11-task suite (reward 0.66 -> 0.64)
# and -27% on a 6-task suite (reward 0.72 -> 0.85) where laya-delegate, in the same batch, is -13%.
# Costs 1.5-1.8x the wall-clock of stock Claude Code; saves nothing on tasks under ~$0.25.
#
# PREREQUISITE: Laya running locally. The routing decisions come from Laya
# (@receptron/laya, a small local classifier; Node 20+, ~1.7 GB model download
# on first start), served at http://127.0.0.1:41733/v1/systemone (rtk's
# classifier wire format), with RTK_LAYA_TOKEN exported. Without it, every
# Laya-gated rule stays silent and only RTK's output filtering applies.
# Sub-agents run on Haiku and Sonnet through Claude Code's Agent tool, so the
# session must be allowed to use those models.
#
# What it does
# - Laya labels the task: bug / setup / write / data.
# - On write and data tasks, RTK refuses the agent's first looking command or
#   file read and asks it to (1) hand the investigation to the Explore sub-agent
#   on Haiku, with a compact report (paths, line numbers, exact lines), then
#   (2) hand the implementation to a general-purpose sub-agent on Sonnet with a
#   short brief, and to run the tests before reporting. The main agent keeps the
#   brief, the review of the result and whatever the tests missed.
# - Bug and setup tasks are left alone.
# - Ranged reads (sed -n a,bp / grep -n) are never capped by RTK.
# - Whole-file reads over 350 lines that need little exact text are answered by
#   a Haiku summary (needs an Anthropic API key; skipped on subscription logins).
# - Everything else is standard RTK output filtering.
#
# Benchmark B — SkillsBench, Claude Opus 5.5, 11 tasks, 4 trials per arm, 2026-10-22/23,
# OFF (stock Claude Code) in the same batch. Mean cost per trial, trials that errored or
# ran past the task time limit excluded (see RESULTS.md; the last two tasks score 0 for
# every model and count for cost only):
#
#   task                                 OFF   tiered  change   pass rate
#   parallel-tfidf-search             $0.885   $0.432   -51%   1.00 -> 0.75
#   python-scala-translation          $0.891   $0.641   -28%   1.00 -> 1.00
#   fix-visual-stability              $0.620   $0.427   -31%   0.00 -> 0.50
#   fix-build-google-auto             $0.298   $0.227   -24%   0.75 -> 1.00
#   react-performance-debugging       $0.476   $0.431    -9%   1.00 -> 0.25
#   debug-trl-grpo                    $0.274   $0.253    -8%   0.60 -> 0.60
#   fix-erlang-ssh-cve                $0.233   $0.250    +7%   1.00 -> 1.00
#   dialogue-parser                   $0.234   $0.260   +11%   0.92 -> 0.92
#   jax-computing-basics              $0.125   $0.167   +34%   1.00 -> 1.00
#   azure-bgp-oscillation-route-leak  $0.134   $0.120   -11%   0.00 -> 0.00
#   llm-prefix-cache-replay           $0.141   $0.232   +65%   0.00 -> 0.00
#   total                            $4.312   $3.440  -20.2%   0.66 -> 0.64
#
# Benchmark A — same suite, 6 tasks (tfidf, python-scala, visual, google-auto, erlang, trl),
# 2026-10-21/22, three arms in one
# batch: OFF $3.423, laya-delegate $2.979 (-13.0%), laya-tiered $2.509 (-26.7%);
# reward 0.72 -> 0.81 -> 0.85.
#
# Sub-agent hand-offs in the tiered arm of benchmark B: 26 to Haiku (investigation),
# 27 to Sonnet (implementation) over 42 trials. Where it loses: short tasks
# (+3 to +9 cents each) and react-performance-debugging, where the Sonnet implementer
# missed a fetch reordering stock Opus found (pass rate 1.00 -> 0.25). Per-trial rows:
# results.tsv.

schema_version = 1

[pipeline]
name    = "laya-tiered"
extends = ["rtk:posthook", "rtk:delegate-reads"]

[upstream.judge]
provider     = "laya"
model        = "laya"
base_url     = "http://127.0.0.1:41733/v1/systemone"
api_key_env  = "RTK_LAYA_TOKEN"
timeout_secs = 60

[upstream.haiku]
provider     = "anthropic"
model        = "claude-haiku-5-5"
timeout_secs = 90

[classifier.need]
upstream     = "judge"
question     = "score"
instructions = "How much of this file's exact text does the agent need for its next step?"
rubric       = ["none: a short summary is enough", "a few exact lines", "most of the file verbatim"]
input_chars  = 2000

[classifier.kind]
upstream     = "judge"
question     = "choice"
instructions = "What kind of work is this coding task?"
input_chars  = 2000
min_confidence = 0.0

[classifier.kind.labels]
bug   = "find and fix a bug by reading source code closely"
setup = "understand or repair a build, configuration, dependency or environment"
write = "write new code, a script or a port"
data  = "analyse data or files and report results"

[task.investigate]
kind         = "digest"
upstream     = "haiku"
temperature  = 0
context      = true

[task.bulk-read]
kind         = "summarize"
upstream     = "haiku"
temperature  = 0
context      = true
instructions = "You read a file for a coding agent that will NOT see it, only your reply. First answer what the agent needs for its current step, in a few terse lines, with exact identifiers. Then map the file: one line on what it is; every class, function and method with its exact signature, in file order. Then quote verbatim, grouped under the name of the function that contains them, the lines whose exact text the agent would most need for its step (non-obvious arithmetic, constants, conditions, error handling, config values). Never give line numbers. Never paraphrase code you quote. No advice, no headings. End with exactly: (Exact text: grep -n a quoted line, then Read that file with offset and limit, at most 350 lines.)"

[override.shunt-large-read]
enabled = false

[[hook.before_tool.read]]
name   = "answer-big-reads"
when   = { file_lines_gt = 350, whole_file = true, "score.need_lte" = 0.65 }
action = "route"
task   = "bulk-read"
mode   = "answer"

[[directive]]
name = "tiered-delegation"
text = """
When RTK asks you to hand an investigation to the Explore sub-agent, call it on the haiku model (Agent tool: subagent_type "Explore", model "haiku") with one precise question built from the task, and ask for a compact report: findings first, then only the file paths, line numbers and exact lines you will need, never whole files. Then do not write the code yourself: hand the implementation to a general-purpose sub-agent on the sonnet model (Agent tool: subagent_type "general-purpose", model "sonnet") with the task, the Explore report and the exact files to create or change — a short brief of what and where, never the code itself — and ask it to run the tests before it reports. Keep for yourself only what needs your judgment: the spec you give it, checking its result against the task, and fixing what its tests missed.
"""

[[hook.before_tool.shell]]
name    = "delegate-investigation"
when    = { command_matches = "^(cd [^;&]+(;|&&) *)?(ls|cat|head|tail|grep|rg|find|tree|pwd|echo|which|wc|file|stat|du|for|while|awk|nl|xxd|git|sed -n)\\b", recent_calls_matches = "^(Bash|Read|Grep|Glob) [^|]*((\\|\\||\\| ?[^A-Z |])[^|]*)*( \\| (Bash|Read|Grep|Glob) [^|]*((\\|\\||\\| ?[^A-Z |])[^|]*)*)?$", "class.kind_in" = ["write", "data"] }
action  = "route"
task    = "investigate"
mode    = "suggest"
message = "Do not run this search or open these files yourself: hand the investigation to the Explore sub-agent (Agent tool: subagent_type \"Explore\", model \"haiku\") with one precise question, and ask for a compact report: file paths, line numbers and the exact lines you will need, never whole files. Then hand the implementation to a general-purpose sub-agent on the sonnet model (Agent tool: subagent_type \"general-purpose\", model \"sonnet\") with the task, that report and the files to create or change (a short brief: what and where, never the code itself), and ask it to run the tests before it reports. Check its result yourself."

[[hook.before_tool.read]]
name    = "delegate-investigation-read"
when    = { recent_calls_matches = "^(Bash|Read|Grep|Glob) [^|]*((\\|\\||\\| ?[^A-Z |])[^|]*)*( \\| (Bash|Read|Grep|Glob) [^|]*((\\|\\||\\| ?[^A-Z |])[^|]*)*)?$", "class.kind_in" = ["write", "data"] }
action  = "route"
task    = "bulk-read"
mode    = "suggest"
message = "Do not run this search or open these files yourself: hand the investigation to the Explore sub-agent (Agent tool: subagent_type \"Explore\", model \"haiku\") with one precise question, and ask for a compact report: file paths, line numbers and the exact lines you will need, never whole files. Then hand the implementation to a general-purpose sub-agent on the sonnet model (Agent tool: subagent_type \"general-purpose\", model \"sonnet\") with the task, that report and the files to create or change (a short brief: what and where, never the code itself), and ask it to run the tests before it reports. Check its result yourself."

[[hook.after_tool.shell]]
name = "keep-ranged-reads"
when = { command_matches = "\\bsed -n *'?[0-9]+,[0-9]+p|\\b(grep|egrep|rg)\\b[^|;&]* -[A-Za-z]*n", is_rtk_command = false }
use  = ["ansi"]
For authors: README badge
[![Reviewed RTK pipeline](https://www.rtk-ai.app/pipelines/badge.svg)](https://www.rtk-ai.app/pipelines/aeppling/rtk-pipeline-laya-tiered/)