Systems languages expose a different class of agent failure. In
JavaScript, a bad agent change breaks behavior; in Go and Rust, it can
break invariants, ignored errors, leaked goroutines, panics on request
paths. The config rules that matter are correspondingly sharper.
Go: the boring rules are the load-bearing ones
gofmt and vet are gates, not suggestions.
go vet ./..andgofmt -l .(empty output) must pass before any
claim of done. Formatting debates end at gofmt.
Errors carry context, always.
Wrap errors with
fmt.Errorf("..: %w", err). Check with
errors.Is/errors.Asat boundaries. An ignored error
(_ = doThing()) needs a comment justifying it, or it is a bug.
Agent-written Go has a signature tell: silent _ discards. This one
rule eliminates most of them.
Context discipline.
context.Contextis the first parameter of every function doing
I/O, and it is never stored in structs.
Bounded concurrency.
Every
go func()has an owner that can stop it, context
cancellation, WaitGroup, or channel close. Unbounded goroutine spawn
on request paths is a production incident in waiting.
Test style. Table-driven tests in the same package, httptest for
handlers, standard library assertions. Say it explicitly, or the agent
imports testify and splits your dependency philosophy.
Rust: the compiler is your ally, the panic is your enemy
The check order is a procedure.
After edits:
cargo check→cargo clippy --all-targets -- -D→
warningscargo test. Fix in that order. Read the full compiler
diagnostic before changing signatures.
Agents that skip to rewriting code on borrow-checker errors produce
worse architectures. Teaching them the ladder, check, read, fix , is
the single highest-value Rust rule.
No unwrap in production paths.
unwrap()/expect()are allowed in tests and in genuinely
infallible cases, each with a comment proving infallibility.
Recovery-eligible errors never abort the process.
Spawned tasks have lifecycles.
Every
tokio::spawngets a lifecycle comment: who joins it, aborts
it, or owns its shutdown. Detached tasks need a reason.
Error-type convention. Pick one and state it:
thiserrorfor library error types,anyhow::Resultinside
binaries. No mixed ad-hocBox<dyn Error>returns in new code.
The blocking trap.
No blocking calls (
std::fs,reqwest::blocking, heavy CPU loops)
on the async runtime. Usespawn_blockingor async equivalents.
What both share
- State the toolchain pin (Go version, Rust edition) as fact.
- Command tables with exact invocations, agents copy them literally.
- The regression-test rule: every bug fix lands with the test that fails without it.
- Keep the always-on file lean; the language server already enforces half your style rules, and the agent config should spend its budget on what the compiler cannot see.
Kits for both
Go and Rust+Tokio are two of the twelve stack kits in AgentConfig
Studio, each ships the four config formats (AGENTS.md baseline,
CLAUDE.md, scoped Cursor rules, Copilot digest) generated from one
source of truth, with the Next.js kit free (MIT) as the reference
example.
If you'd rather not assemble this by hand: AgentConfig Studio on Gumroad ships this as version-pinned, validator-tested kits for 12 stacks. The complete Next.js/TypeScript kit is free (MIT) if you want to inspect the structure first.