DEV Community

Riley Li
Riley Li

Posted on

Pick Agent Compute by Blast Radius, Not by the Price Tag

Shared free compute is honest for agent work only when every tool is read-only, replayable, and free of secrets. If your loop can mutate state, leak a credential, or poison an eval set, sticker price is the wrong axis. I treat blast radius as the first filter, and only then do I ask whether a free model lane even fits. Does a weekend prototype that barely prints logs still deserve that same blast-radius filter before it ships?

The assumption almost every agent tutorial smuggles in

Most agent tutorials quietly assume the runtime is a private laptop that nobody else can inspect. Tools inherit that fantasy: they read local files, they retry network calls, and they treat environment variables as a private diary. What happens when that same loop lands on a shared free box or a host that actually holds secrets? The model did not get dumber; the blast radius of its tools just became a different product.

I keep a four-band map for this, because free versus paid is too coarse to be a real decision. Band 0 is pure reasoning with no tools at all, which is rarer than README files admit. Band 1 is read-only fixtures, golden traces, and local diffs that never leave the process. Can you honestly put your current demo into Band 1 without lying about the shell tool?

Band 2 is outbound reads against public docs or a throwaway sandbox, still with no mounted secrets. Band 3 is anything that can write, pay, deploy, or see credentials, and that band never belongs on shared free compute. Is Band 3 rare in agent demos, or do we just rename the dangerous tools until the demo recording looks harmless?

A five-step filter to run before picking a lane

Here is the workflow I use as a checklist, not as a score that pretends to be science. Label this a proposal if you have not wired it to your own job queue yet. Each step produces an artifact you can diff, which is the entire point of a gate. If a step has no artifact, I treat the inventory as incomplete and I fail closed.

1. Inventory every tool the agent may call, including retries

Write the tool list down before you pick a vendor, a container, or a vague free endpoint. Include implicit tools: shell, file write, browser, SQL, and whatever the framework injects when the model panics. If a retry can double a POST, count that POST twice in the blast-radius story. Would you accept a security review that omitted the retry path because the happy path looked read-only?

# Proposal: dump the tool names your agent harness registered.
python -c "from my_agent import tools; print('\n'.join(sorted(t.name for t in tools)))"
Enter fullscreen mode Exit fullscreen mode

2. Tag each tool with the worst thing it can do

I use four tags only, because extra categories become a junk drawer by the next refactor. think means no I/O, and read_local means fixtures plus traces that never leave the disk. read_network means unauthenticated or explicitly public GETs, and mutate_or_secret means writes, credentials, payments, or deploys. Ask yourself one rude question here: if this tool lies, what still moves in the real world?

3. Promote the job to the maximum tag, not the average tag

A loop with nine read-only tools and one gh token is still a Band 3 job. Averages hide the landmine, which is why the gate uses maximum tag rather than a friendly mean. I refuse to mostly put Band 3 work on a shared free server just because the prompt looks academic. Does a single mutating tool feel like an exception, or does it rewrite the whole isolation story?

4. Match the band to an isolation lane

  • Band 0 and Band 1 can use shared free compute, a paid API worker, or a self-hosted box.
  • Band 2 belongs on a paid API or a locked-down sandbox, with allowlisted hosts and no .env file.
  • Band 3 belongs on self-hosted or a dedicated account, with secrets injected at run time and an audit log you control.

Disclosure: This article was prepared as part of MonkeyCode's product outreach. When a job really sits in Band 0 or Band 1, MonkeyCode's free model access and free server option are one honest place to iterate. I do not treat that free lane as a production control plane, and I do not invent capacity, model names, or quotas here. If your tools need isolation, skip the shared option and move to self-hosted without bargaining on the tags.

5. Fail closed when the inventory is incomplete

Missing tool metadata is not a reason to default to free; it is a reason to refuse a shared runtime. Would you mount an undocumented binary on a box that other tenants can reach on purpose? Then do not do it with an agent loop whose tool list you have not actually printed. Fail closed, then fill the inventory, then run the gate again with a real spec.

Artifact: a blast-radius gate you can run in CI

The following script is a concrete gate, not a benchmark and not a vendor bake-off. It reads a JSON job spec, computes the maximum band, and exits non-zero when Band 3 work targets shared_free. Copy it, then point it at your own specs; I am not claiming production metrics from a script you have not run. If you change the allow-map, keep Band 3 off shared free compute or the whole filter is theater.

#!/usr/bin/env python3
"""blast_radius_gate.py — fail CI when the runtime is too shared for the tools."""

from __future__ import annotations

import json
import sys
from pathlib import Path
from typing import Literal

Band = Literal[0, 1, 2, 3]
Lane = Literal["shared_free", "paid_api", "self_hosted"]

TAG_TO_BAND = {
    "think": 0,
    "read_local": 1,
    "read_network": 2,
    "mutate_or_secret": 3,
}

ALLOWED_LANES: dict[Band, set[Lane]] = {
    0: {"shared_free", "paid_api", "self_hosted"},
    1: {"shared_free", "paid_api", "self_hosted"},
    2: {"paid_api", "self_hosted"},
    3: {"self_hosted"},
}


def band_for_tools(tools: list[dict]) -> Band:
    if not tools:
        return 0
    bands = [TAG_TO_BAND[t["tag"]] for t in tools]
    return max(bands)  # type: ignore[return-value]


def evaluate(spec: dict) -> tuple[bool, str]:
    lane: Lane = spec["lane"]
    tools = spec.get("tools")
    if tools is None:
        return False, "incomplete inventory; fail closed (no shared runtime)"
    band = band_for_tools(tools)
    allowed = ALLOWED_LANES[band]
    if lane not in allowed:
        return False, f"band {band} job cannot use lane {lane}; allowed={sorted(allowed)}"
    return True, f"ok: band {band} on {lane}"


def main(argv: list[str]) -> int:
    if len(argv) != 2:
        print("usage: blast_radius_gate.py <job-spec.json>", file=sys.stderr)
        return 2
    spec = json.loads(Path(argv[1]).read_text(encoding="utf-8"))
    ok, message = evaluate(spec)
    print(message)
    return 0 if ok else 1


if __name__ == "__main__":
    raise SystemExit(main(sys.argv))
Enter fullscreen mode Exit fullscreen mode

A Band 1 spec that is allowed on shared free compute looks like the JSON below. Notice there is no shell, no ticket writer, and no environment dump. The emit_markdown tool is tagged think because it only formats memory. If that function later writes a file, you must retag it before the next run.

{
  "name": "summarize-golden-traces",
  "lane": "shared_free",
  "tools": [
    {"name": "read_fixture", "tag": "read_local"},
    {"name": "emit_markdown", "tag": "think"}
  ]
}
Enter fullscreen mode Exit fullscreen mode

A Band 3 spec that must not go there looks like this next block. The runbook reader is harmless, but jira_create mutates a real tracker. Maximum tag wins, so the whole job is Band 3. Parking it on shared_free is a gate failure, not a style choice.

{
  "name": "open-incident-ticket",
  "lane": "shared_free",
  "tools": [
    {"name": "read_runbook", "tag": "read_local"},
    {"name": "jira_create", "tag": "mutate_or_secret"}
  ]
}
Enter fullscreen mode Exit fullscreen mode

Run the gate like this, and keep the commands in your PR checklist. The second command should print a refusal and exit 1. If it does not, your copy of the gate is not the one above. Want a tiny unit check without standing up a framework?

python3 blast_radius_gate.py jobs/summarize.json
python3 blast_radius_gate.py jobs/incident.json; echo "exit=$?"
Enter fullscreen mode Exit fullscreen mode
# test_blast_radius_gate.py — proposal tests, not a published benchmark
from blast_radius_gate import evaluate

def test_band3_rejected_on_shared_free():
    spec = {
        "lane": "shared_free",
        "tools": [{"name": "ship", "tag": "mutate_or_secret"}],
    }
    ok, msg = evaluate(spec)
    assert ok is False
    assert "band 3" in msg

def test_missing_tools_fail_closed():
    ok, msg = evaluate({"lane": "shared_free"})
    assert ok is False
    assert "incomplete" in msg
Enter fullscreen mode Exit fullscreen mode
python3 -m pytest test_blast_radius_gate.py -q
Enter fullscreen mode Exit fullscreen mode

Decision table I keep next to the job YAML

Job signal Band Shared free models/server Paid API worker Self-hosted
Read-only fixtures, no secrets 1 Fit Fit Fit, usually overkill
Public HTTP GET, allowlisted hosts 2 Not fit Fit if egress is pinned Fit
Writes, tickets, deploys, payments 3 Not fit Risky unless dedicated Default
Incomplete tool inventory n/a Not fit Not fit Only with a human review
Need replay you can hash 1–2 Only if traces stay local Fit if you store receipts Fit
Tenant-adjacent data 3 Not fit Check the contract Default

Notice the table never says faster or cheaper, because those adjectives need measurements you actually ran. I am not inventing latency, token ceilings, or vendor rankings in this guide. The only claim is fitness against blast radius, which you can falsify by listing one tool I missed. If a row does not match your compliance policy, the policy wins and the table is just a draft.

What this filter will not do for you

This approach will not pick a model, will not estimate latency, and will not prove a vendor is safe. It also will not save a Band 3 agent that you dressed up as Band 1 by renaming shell to research. If you are under HIPAA, PCI, or an employer policy that forbids shared runtimes, skip the free lane entirely. Do not bargain with the checklist when the policy already answered the lane question for you.

Anyone whose tools can spend money, change customer data, or see production secrets should not use shared free compute. Anyone who needs a legally durable audit log should not use it either, even for a so-called dry run. Also skip this guide if you cannot list the tools, because a decision without inventory is only a vibe. Is that a smaller audience than the internet's agent demos imply, or did the demos skip the dangerous tools on camera?

I still like free shared compute for throwaway summarizers, prompt diffs, and golden traces that never included secrets. That door should stay narrow, because one new tool can move a job from Band 1 to Band 3 overnight. If a tool appears in the loop tomorrow, re-run the gate before you congratulate the agent for being done. Price can still matter later, but only after the blast radius says the lane is allowed to exist.

Top comments (1)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.