Agent config for Go and Rust: rules that keep systems languages honest

go dev.to

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 ./.. and gofmt -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.As at 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.Context is 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 checkcargo clippy --all-targets -- -D
warnings
cargo 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::spawn gets 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:

thiserror for library error types, anyhow::Result inside
binaries. No mixed ad-hoc Box<dyn Error> returns in new code.

The blocking trap.

No blocking calls (std::fs, reqwest::blocking, heavy CPU loops)
on the async runtime. Use spawn_blocking or 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.

Source: dev.to

arrow_back Back to Tutorials