cd /news/ai-agents/spotify-portal-shunt-cut-claude-code… Β· home β€Ί topics β€Ί ai-agents β€Ί article
[ARTICLE Β· art-134307] src=gist.github.com β†— pub= topic=ai-agents verified=true sentiment=↑ positive

Spotify Portal shunt: cut Claude Code tokens 90% via bulk-reader + code-writer AiKA modes (extracted from tweet + Spotify Engineering)

Spotify Engineering cut Claude Code token usage by roughly 90% on a Java monorepo by routing bulk file reading and boilerplate code generation to a cheap model such as Gemini 2.5 Flash while keeping reasoning on frontier models like Claude Opus and Sonnet. The setup, built on Spotify's Portal AiKA Modes, relies on a blocking PreToolUse hook that hard-blocks reads over 350 lines rather than relying on written routing instructions, which the team found were ignored. Spotify's takeaway: "Written rules are a suggestion. A block is not.

by read6 min views11 publishedSep 6, 2026

Original: Spotify's Claude Code setup (@undefinedKi tweet) + Spotify Engineering, Sep 3 2026. Generalized below for GitHub Copilot, Kiro, and Codex (OpenAI Codex CLI).

Route grunt I/O to cheap model, keep reasoning on frontier, enforce with a hard block (>350 lines), not prompt instructions.

Spotify: Claude Opus/Sonnet + Gemini 2.5 Flash via Portal AiKA Modes β†’ ~90% token savings on Java monorepo. Same pattern works anywhere if you add 3 layers: 1) Blocking interceptor 2) Cheap-worker scripts/MCP 3) Redirect instructions.

Use any cheap/fast model: gemini-2.5-flash / claude-haiku / gpt-4o-mini / gpt-4.1-nano / ollama/qwen2.5-coder. Temp 0.2.

1. bulk-reader β€” reads N files, returns bullets. Frontier never sees full files.

You are a precise code analyst. Read the provided files and answer the question concisely.
Output structured bullets only. No greetings, no prose. Lead every bullet with exact name/type/line.
Use nested bullets for details. Skip anything not asked.

2. code-writer β€” generates boilerplate from spec + reference, writes to disk.

You generate code files based on a spec and reference files. Match existing patterns, conventions, naming, style exactly.
Output only the code β€” no explanations, no markdown fences unless asked.
If ambiguous, choose what matches reference.

Spotify's Portal AiKA Modes implement these as name: bulk-reader / code-writer with model: gemini-2.5-flash. You can replace with a direct API call β€” see self-hosted script below.

Invocation contract (tool-agnostic):

bulk-read --question "What does this service do?" --paths src/A.java src/B.java
code-write --spec "Write tests for UserService" --reference tests/OrderTest.java --target tests/UserTest.java
Layer Purpose Claude Code (Spotify) Generalized
1. Hook / Enforcement Hard block, not suggestion PreToolUse hooks:check-file-size (>SHUNT_MIN_LINES=350 ) +check-bash-read (cat/head/tail) See per-tool below
2. Scripts / MCP Call cheap model, handle XML/fences, report tokens bulk-read /code-write bash wrappers overportal CLI Same scripts, but call curl to cheap model OR Portal CLI OR MCP server
3. Skills / Instructions Tell agent when/how to redirect /bulk-reader skill (md) + block message copilot-instructions.md /.kiro/steering/ /AGENTS.md β€” butalways paired with Layer 1

Lesson from Spotify: "Written rules are a suggestion. A block is not." CLAUDE.md routing was ignored until they added blocking hooks.

  1. Editing β€” summaries lack reliable line numbers β†’ keep targetedread(offset,limit) on frontier.
  2. Reasoning/debugging/architecture/thread-safety β€” cheap model missed subtle bug frontier caught in seconds.
  3. Small files β€” delegation overhead 10–30s + 30s cap; threshold exists for this reason.

Replace Portal with 20 lines of bash. Works for all tools:

#!/usr/bin/env bash
set -euo pipefail
QUESTION="$1"; shift
FILES=("$@")
PAYLOAD=""
for f in "${FILES[@]}"; do
  PAYLOAD+="<file path=\"$f\">$(cat "$f")</file>\n"
done
curl -s https://api.openai.com/v1/chat/completions \
  -H "Authorization: Bearer $CHEAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<EOF | jq -r '.choices[0].message.content'
{
  "model": "gpt-4o-mini",
  "temperature": 0.2,
  "messages": [
    {"role":"system","content":"You are a precise code analyst. Output structured bullets only. No prose. Lead every bullet with exact name/type/line."},
    {"role":"user","content":"Question: $QUESTION\n\nFiles:\n$PAYLOAD"}
  ]
}
EOF

Expose same as MCP tool bulk_read(question, paths) and code_write(spec, reference, target) β€” then every agent can call it.

Copilot has no PreToolUse hooks, so enforcement must be via MCP + custom tool descriptions.

Option A β€” MCP Router (recommended):

// .vscode/mcp.json
{
  "servers": {
    "cheap-worker": {
      "command": "node",
      "args": ["./mcp-cheap-worker/index.js"],
      "env": { "CHEAP_MODEL": "gpt-4o-mini" }
    }
  }
}
  • MCP exposes bulk_read (reads filesserver-side , returns summary) andcode_write (writes file, returns path only).
  • In .github/copilot-instructions.md :
## Routing (MANDATORY)
- NEVER read files >350 lines directly. Call `bulk_read` instead.
- For boilerplate/tests from a reference, call `code_write` β€” do not generate in context.
- Targeted reads with offset/limit are allowed for edits.
  • Hard block: MCPbulk_read is theonly tool that has file access; revoke Copilot'sreadFile for large files via extensioncopilot-tool-filter or workspacesettings.json :
{ "github.copilot.chat.toolRestrictions": { "readFile": { "maxLines": 350 } } }

(Copilot CLI gh copilot similarly: use GH_COPILOT_TOOL_POLICY to deny large reads)

Option B β€” Custom Chat Mode: Create .github/chatmodes/research.mode.md that only has bulk_read tool enabled, and .github/chatmodes/build.mode.md for code-write. Encourage /research What does X do? β†’ auto-routes.

Kiro has hooks β€” closest 1:1 mapping to Claude.

// .kiro/hooks/bulk-reader.json
{
  "preToolUse": [
    {
      "tool": "fs_read",
      "check": "file.lines > 350 && !args.offset",
      "block": true,
      "message": "File >350 lines: use `bulk-read --question <q> --paths <files>` (cheap worker). For edits use offset/limit."
    },
    {
      "tool": "bash",
      "match": "^(cat|head|tail|less|more)\\s+",
      "blockIf": "targetFile.lines > 350"
    }
  ]
}
  • Add steering: .kiro/steering/routing.md with same mandatory routing text + examples.
  • Scripts identical: Kiro executes bulk-read bash script which can call Portal CLIor direct API. Kiro's ephemeral runtime similar to AiKA.
  • Threshold configurable via KIRO_SHUNT_MIN_LINES=500 env.

Codex uses AGENTS.md + config.toml + MCP.

[mcp_servers.cheap-worker]
command = "node"
args = ["./mcp-cheap-worker/index.js"]

[tools]
deny = ["read_file({\"lines\" > 350})"]
php
<!-- AGENTS.md -->
## Model Routing (ENFORCED)
- Files >350 lines MUST use `bulk_read` MCP tool, not `read_file`.
- Boilerplate/tests MUST use `code_write` with a reference file.
- Direct generation without reference is forbidden.
  • Codex respects tool description strongly β€” makebulk_read description:MANDATORY for files >350 lines. Reads files server-side and returns concise bullets. Use instead of read_file.
  • CLI wrapper fallback: codex --mcp cheap-worker + shell aliasread = bulk-read forcat .
Scenario Frontier Cheap Worker Method
Q&A across 5 files sees summary (200 tokens) reads full files bulk-read
Generate test copying 20 examples never sees output reads 1 reference + writes code-write --target
Edit/fix bug targeted read(offset,limit) not used direct
Debug/architecture/thread-safety full context not used direct
  • Start 350 lines (~10k tokens). Measure: ifp50 delegation latency > time saved , raise to500 . Spotify usesSHUNT_MIN_LINES env.
  • Temperature 0.2 for both workers;0.0 for code-writer if you want deterministic scaffolding.
  • Always require --reference for code-write β€” without it, cheap model hallucinates patterns.
claude plugin marketplace add spotify/portal-ai-plugins
claude plugin install portal@portal && claude plugin install shunt@portal
/portal:setup

git clone https://github.com/your-org/mcp-cheap-worker
npm i && cheap-worker --setup  # sets CHEAP_API_KEY, model

Generalized 2026-09-06 from Spotify's Claude-specific implementation. Principle is portable: cheap model + hard block + XML-wrapped delegation.

── more in #ai-agents 4 stories Β· sorted by recency
── more on @spotify 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/spotify-portal-shunt…] indexed:0 read:6min 2026-09-06 Β· β€”