If you’re using a coding agent without linters, type checkers, or test suites wired in, you’re probably doing a lot of manual babysitting. Checking output, pointing out issues, asking for fixes. You are the feedback loop — and that’s the least efficient version of it.

These tools have been around forever. What’s changed is the context: when an agent can call them directly, they stop being things you run at the end and become continuous, automated course-correction.

What is agentic backpressure?

The term comes from systems engineering. Backpressure is how a system signals that it’s being pushed too hard — a way to slow things down before they break. Dan Banay’s post applies the concept to agentic coding: your dev tools push back on the agent whenever it drifts. A type error, a failing test, a lint violation — these are all immediate, deterministic signals that say “fix this before moving on.”

Wire them up as automated checks — pre-commit hooks, CI steps, Claude Code hooks — and the agent gets reliable feedback without you being in the loop.

Why deterministic matters

LLMs are non-deterministic by nature. That’s fine for generating code — but for validating code, you want the opposite: tools that give you the same answer every time.

A linter doesn’t have opinions that change between runs. ruff will format your code the same way either way. These binary pass/fail signals are exactly what a coding agent needs to stay on the rails.

And it doesn’t stop at linters and test suites. Any deterministic check works. Validate a CSV against a schema. Check that an API response matches a spec. Verify that a generated config file is valid YAML. These are all just scripts that return pass or fail — and writing them has become essentially free. You can ask the same agent to write the validator before it starts the actual work.

Every validator you add is one less thing you need to catch manually. Stack enough of them, and the agent can run autonomously for much longer stretches.

Context efficiency is the multiplier

Dex from HumanLayer pointed out something that I think is underappreciated: it’s not enough to have feedback loops. You need them to be context-efficient.

A typical pytest run with 50 passing tests might dump 200+ lines into the agent’s context. Collection info, individual test results, timing data, warnings. That’s easily 2,000 tokens, all saying “everything is fine.”

Compare that to: âś“ pytest. Four tokens. Same information.

This matters because the context window is the agent’s working memory. Every token you waste on noise is a token that can’t be used for reasoning about the actual task. Over a long session, this compounds hard. Verbose output leads to more frequent context compaction, which means the agent loses earlier task context sooner, which means it starts repeating itself or forgetting what it was doing.

The pattern is simple: swallow output on success, surface only failures. And when you do surface failures, strip them down to the actionable bits — the test name, the assertion error, the relevant line. Not the full traceback with 40 frames of pytest internals.

Introducing hush

I really liked the shell script Dex shared in his post and wanted something like it that I could use across all my projects without copy-pasting. So I turned the idea into hush — a small CLI tool written in Go. Run a command, suppress output on success, surface it on failure. Exit codes pass through unchanged so your agent (or CI) can still detect failures normally.

go install github.com/alfranz/hush/cmd/hush@latest

Wrap any command by prefixing it with hush:

hush "pytest -x"

On success: âś“ pytest. That’s it — a 50-test run that normally dumps ~1,000 tokens becomes 4. On failure, you get the full output so the agent can fix the problem.

Run multiple checks with batch. On first failure it stops (or use --continue to run them all):

hush batch "ruff check ." "ty check src/" "pytest -x"

All pass:

âś“ ruff
âś“ ty
âś“ pytest
âś“ 3/3 checks passed

One fails with --continue:

âś“ ruff
âś— ty
  src/auth.py:42: error: Argument of type "str" is not assignable to parameter "user_id" of type "int"
âś“ pytest
âś— 2/3 checks passed

It works across any language and any tool — hush wraps commands at the shell level. It also supports --tail and --grep flags to trim noisy failure output, and project-level config via .hush.yaml. See the README for the full details.

Wiring it into your agent

The easiest integration is through Claude Code hooks. Set up a hook that runs hush all after file changes, and your agent gets automatic, context-efficient feedback on every edit. You can also just alias your test commands in your CLAUDE.md instructions to use hush — the agent will pick it up.

The compounding effect

Each check that passes quietly saves tokens. Each check that fails with minimal output means faster course correction. Less context compaction. Over a long session, this adds up.

If you’re spending time manually telling your coding agent that tests are failing or that it introduced a type error, you’re the backpressure. And you’re the most expensive, slowest, least reliable version of it. Wire up the tools. Make them quiet when things pass and let the agents run.