On a Thursday evening a backend engineer closed a laptop that still held one unfinished agent session. The session had been rewriting a Flyway migration that referenced a staging password kept inside a local dotenv file. Office Wi-Fi had already dropped twice, and each reconnect added seconds to every remote tool call in the loop. The engineer needed a placement rule that treated latency, secret residency, and offline survival as measured inputs rather than slogans.
The cost that prompts never print
Agent loops look inexpensive in screenshots because those screenshots omit the network path under every tool call. Each departing tool call pays a round-trip tax, and that tax multiplies by retrieve-edit-test cycles inside a single job. A local editor call against an SSD often finishes within a few milliseconds of issuing the syscall. A remote tool call waits on DNS, TLS, queueing, and every other tenant currently sharing that path.
The interesting decision is not cloud versus laptop as a brand preference or a conference talking point. The interesting decision is whether the next N round trips carry secrets, and whether the host remains reachable when N is only halfway complete. This article proposes a two-axis placement method, a fail-closed scanner, and a tiny estimator that teams can run before any tokens leave the machine. The method is a proposal with labeled, unexecuted examples, not a claim about production benchmarks from a named fleet.
Two axes that actually change the answer
Axis one is secret surface, meaning dotenv files, SSH private keys, customer extracts, and paths that .gitignore already treats as radioactive. Axis two is round-trip tax, meaning measured RTT multiplied by expected tool-call cardinality, plus a boolean for an impending network partition. A borrowed CPU wins when axis one is empty and axis two is large, especially if the laptop is thermally limited or about to sleep. A local process wins whenever axis one is non-empty, or when the job must continue through a partition without waiting for a human.
These axes stay independent on purpose so a fast network cannot launder a secret, and a clean working tree cannot hide a five-second tool tax. Prior coverage on this account discussed gates, routers, and resume behavior; this write-up measures the loop itself. Teams that already classify jobs can still misplace them if they never multiply cardinality by RTT. The scanner below exists to make that multiplication boring and repeatable.
Artifact: a fail-closed surface scan and a tax estimate
The artifact is a small Python module plus a one-shot shell probe, both intended for a laptop working copy. It classifies paths as SECRET or PUBLIC, refuses to recommend remote placement when any SECRET path is in the working set, and prints a tax estimate of cardinality * rtt_ms. The constants are placeholders for local measurement, not vendor claims, and the remote probe should target an endpoint the team already owns. Treat the output as a decision aid, then apply the table in the next section before moving bytes.
Step 1 — Freeze the working set
List the files the agent may read or write, including dotenv files, fixture dumps, and generated snapshots that tests will open. Capture that list to a lockfile so later steps cannot silently expand the surface after the scan. A command such as git ls-files -co --exclude-standard > /tmp/agent-set.txt is enough for many repositories. Append extra untracked secrets by hand when the repository .gitignore is the only thing hiding them from git.
Step 2 — Probe round-trip time on the path that would actually be used
Measure RTT against the host that would run remote tool calls, not against a random public anycast address. A single ping is a weak proxy for TLS and application queueing on a shared runner. Follow it with a short HTTPS HEAD when the team already has a harmless endpoint. Record rtt_ms as the median of a handful of probes rather than the luckiest single sample. If the probe fails outright, treat the network as partitioned and keep the entire job local.
# Proposed probe; replace the host with one the team already operates.
ping -c 5 -q agent-runner.example.internal | tee /tmp/agent-rtt.txt
curl -sS -o /dev/null -D - -X HEAD https://agent-runner.example.internal/health
Step 3 — Estimate cardinality before the model starts proposing edits
Count the retrieve, patch, test, and lint steps the job is likely to issue, then write that integer beside rtt_ms. A migration rewrite that runs unit tests after every patch can easily exceed a dozen tool calls. Multiply the two numbers and call the product loop_tax_ms, which is the quantity screenshots never show. If loop_tax_ms is large and the secret surface is empty, a borrowed CPU becomes interesting.
Step 4 — Run the fail-closed scanner
Save the following module as tool_loop_tax.py and run it against the lockfile from step 1. The script is a proposal, not a certified data-loss preventer, and it defaults to LOCAL whenever classification is uncertain. Extend the secret patterns to match the repository rather than copying this starter list forever. Print the recommendation next to loop_tax_ms so a human can override it with context the scanner cannot see.
#!/usr/bin/env python3
"""Proposed fail-closed placement helper. Unexecuted example; tune markers locally."""
from __future__ import annotations
import sys
from pathlib import Path
SECRET_MARKERS = (".env", "id_rsa", "id_ed25519", ".pem", ".p12")
SECRET_WORDS = ("secret", "credential", "password", "token")
def classify(path: str) -> str:
posix = Path(path).as_posix().lower()
name = Path(path).name.lower()
if any(marker in posix for marker in SECRET_MARKERS):
return "SECRET"
if any(word in name for word in SECRET_WORDS):
return "SECRET"
if "customers/" in posix and posix.endswith((".csv", ".sql", ".dump")):
return "SECRET"
return "PUBLIC"
def recommend(paths: list[str], rtt_ms: float, cardinality: int, partitioned: bool) -> str:
secret_hits = [p for p in paths if classify(p) == "SECRET"]
loop_tax_ms = rtt_ms * cardinality
if secret_hits or partitioned:
return "LOCAL"
if loop_tax_ms >= 800 and rtt_ms >= 40:
return "REMOTE_PUBLIC_ONLY"
return "LOCAL"
def main() -> int:
if len(sys.argv) < 4:
print(
"usage: tool_loop_tax.py SET.txt RTT_MS CARDINALITY [--partitioned]",
file=sys.stderr,
)
return 2
paths = [
ln.strip()
for ln in Path(sys.argv[1]).read_text().splitlines()
if ln.strip()
]
rtt_ms = float(sys.argv[2])
cardinality = int(sys.argv[3])
partitioned = "--partitioned" in sys.argv[4:]
decision = recommend(paths, rtt_ms, cardinality, partitioned)
secrets = [p for p in paths if classify(p) == "SECRET"]
print(f"files={len(paths)} secrets={len(secrets)} tax_ms={rtt_ms * cardinality:.1f}")
print(f"decision={decision}")
for p in secrets:
print(f"SECRET {p}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
Step 5 — Apply the placement table, not the slogan
| Working set | Network | loop_tax_ms |
Host state | Placement |
|---|---|---|---|---|
Any SECRET path |
Any | Any | Any | Stay local; do not copy the tree |
| Public only | Partitioned or flaky | Any | Awake | Stay local; freeze rather than retry forever |
| Public only | Stable | High | Hot, sleepy, or RAM-poor | Borrow a server for compile and test only |
| Public only | Stable | Low | Cool and awake | Stay local; the tax is not worth the hop |
The table is the artifact teams should paste into a runbook, because it survives a change of model vendor. Remote placement in this table never includes dotenv files, private keys, or customer extracts, even when the remote option is free. Local placement still needs a wall-clock budget on a fanless laptop, but that budget is a separate control. When the table says REMOTE_PUBLIC_ONLY, copy a scaffold without secrets, not the entire home directory.
When a free server is the honest win
There is a narrow band where local-first discipline and borrowed CPUs cooperate instead of competing for the same job. Public compile jobs, documentation lint, and schema-free formatting can leave the laptop after a clean scan. That departure is reasonable only when loop tax is dominated by remote-friendly CPU work. That split is useful precisely because it is boring, repeatable, and easy to reverse when the probe fails.
Disclosure: This article was prepared as part of MonkeyCode's product outreach. MonkeyCode offers free model access and a free server option that can absorb public compile and test slices without moving the keyring. The laptop keeps the dotenv file, the SSH agent, and the customer dump that never should have been in the repo. The free server receives a tarball of public fixtures, a test command, and a hard timeout.
If the server is busy or the network partitions, the job remains restartable locally because the secret surface never left disk. The win is not unlimited capacity; the win is a second residency for work that was never sensitive. Teams should still fail closed to the laptop when the scanner is uncertain, the probe is quiet, or the working set cannot be named. Free access is an overflow valve for public cycles, not a reason to copy a home directory onto shared disks.
Limitations
The scanner does not parse file contents, so a secret pasted into notes.md will be classified as public unless a pattern matches the path. The RTT probe undercounts TLS session setup, proxy hops, and cold starts on a shared runner. That undercount means loop_tax_ms is a floor rather than a trustworthy forecast of wall time. Cardinality is a human estimate and will be wrong when the model opens a larger repair loop than the operator expected.
None of the numbers in this article are production benchmarks, vendor quotas, or promises about hardware. Free model access and a free server option can disappear, throttle, or change without notice, so placement rules must fail closed to local execution. Teams in regulated environments still need a legal review before any path leaves the building, regardless of how empty the scanner looks. The example hostnames are placeholders and must be replaced with infrastructure the team already controls and monitors.
Do not treat a green PUBLIC label as a substitute for .gitignore, secret scanning in CI, or least-privilege credentials. Path markers miss clipboard pastes, decrypted mounts, and editor swap files that never entered the lockfile. A median ping also ignores queue delay after many tenants pile onto the same free runner. Those gaps are why the default recommendation remains LOCAL whenever a check is incomplete.
Who should not use this approach
Operators who cannot describe the working set should not ship work off the laptop on the basis of this table. Teams that mix customer PII into fixture files as a matter of habit will get a false PUBLIC reading unless they extend the patterns. People hunting for guaranteed latency, reserved GPUs, or a durable SLA will not find those guarantees in a free shared option. If the job cannot be restarted from a secret-free scaffold, keep the entire loop local and shorten the cardinality instead.
Local-first placement is a control plane for residency, not a claim that on-device models beat every remote model on quality. Quality comparison belongs in an evaluation harness with frozen prompts and graded fixtures, which this article does not provide. The method also refuses remote placement during a partition, which will frustrate anyone whose only available compute lives across the network. That refusal is intentional and favors a stalled local job over a half-copied tree.
A runbook close
Measure the working set, measure the path, multiply by cardinality, and only then decide whether a borrowed CPU is allowed to see the tree. Keep the keyring on the laptop, and keep the recommendation fail-closed when the scanner is uncertain or the probe does not return. Readers who already keep keyrings offline can park only the public compile slice on that free server and compare the measured tax. Publish the lockfile and the printed decision beside the pull request so reviewers can see the residency choice.
Top comments (1)
The loop tax being invisible in screenshots is why so many agent demos end at the laptop. A loop is only as local as its slowest remote call, and every hop is latency, auth surface, and a place to leak the staging password all at once. Treating placement as a measured decision instead of a slogan is the part most agent writeups skip. What did the measurement change - did anything actually move off the laptop, or did it just get a babysitter?