Why agent-friendly is a real language design goal
"Designed for LLMs" sounds like marketing. It is not. Here is the concrete list of language-design choices that change when the modal author of code is a stochastic process.
There is a real risk that “agent-friendly programming language” reads, in 2026, the same way “blockchain-enabled” read in 2018: a marketing prefix that means nothing in particular. So this post is the concrete version of what we mean. Agent-friendly is not a vibe. It is a list of design choices that change the cost of generating, compiling, and reviewing code when the modal author is an LLM and the reviewer is a human under time pressure.
Some of these choices are unusual; some are old wisdom that current popular languages did not adopt. None of them are about the agent being “smarter” than a human. They are about which kinds of errors the agent reliably makes, and where the language can put the safety net.
The producer is stochastic. The reviewer is stochastic. The compiler is the deterministic step.
That sentence is the thesis. If you grant it, the rest of this post is downstream.
In the human era of programming, the compiler was the rubber stamp at the end of a careful human process. A senior C programmer wrote each line on purpose; the compiler caught the typos. In the agent era, the agent generates a thousand lines that are individually plausible and collectively might be wrong in a way that takes a human ninety minutes to find. The reviewer cannot inspect a thousand lines in fifteen minutes. The agent cannot promise its own correctness.
The compiler is the only step in the loop that always says the same thing about the same input. So the language design question becomes: how much of the auditing job can we move onto the compiler? Which checks can we make structural rather than aspirational? Which bug classes can we delete instead of patch?
Choice 1: Unambiguous grammar
A grammar that has context-dependent parsing — C’s “is this a declaration or an expression?” being the canonical example — costs an agent tokens at generation time and humans confusion at review time. fastC has no context-dependent parsing. Every token sequence has exactly one parse. An agent can generate syntactically valid fastC from the grammar rules alone, without needing a type checker in the generation loop.
This sounds like a small thing. It is not. The Rust agent benchmarks we ran show first-compile failures clustering around macro-heavy code where the type checker is part of macro expansion. Agents do worse on grammars that are non-context-free because they cannot reliably keep track of which mode they are in at token N+1. fastC keeps the grammar simple.
Choice 2: Explicit over implicit, everywhere
let x: i32 = 10; looks more verbose than int x = 10. It is. The verbosity is the point. The agent knows what type x is from the line itself; the reviewer knows from the line itself. There is no inference cascade where the type of x depends on the type of something three calls deep. Type inference is a wonderful tool for human ergonomics; it is a tax on agent reliability.
The same logic applies to cast(i32, x) for narrowing conversions. C promotes silently. Rust promotes through as (which silently narrows). fastC requires you to spell cast(i32, x) and the compiler refuses any other path. The agent that wants to narrow knows it has to call out the narrowing; the reviewer reading the diff sees the cast and stops to think.
This is the source of the “single canonical style” property. fastc fmt enforces one style with no options. There are no debates because there is no configuration. An agent generates fastC, runs fastc fmt, and the output matches every other team’s fastC.
Choice 3: Structured diagnostics, not prose
When the compiler errors out, what does the agent get back? In current toolchains, a paragraph of English. Maybe a span. Maybe a hint. Agents do okay at parsing it; the parsing is lossy and the iteration loop is slow.
fastC ships every diagnostic as structured JSON via --output-format=json. A unique error code (E0042), a span (file, line, column, length), a machine-readable category, a fix-it hint with the suggested replacement text. The agent gets a typed object. It can apply the fix-it directly. The iteration loop tightens by an order of magnitude.
The deeper version of this is fastc-mcp, a native MCP server that exposes the build’s typed artifacts — caps.json, discharge.json, structured diagnostics — to Claude Code, Cursor, and Codex over Model Context Protocol. The agent stops text-parsing cargo check output. It queries the project’s capability graph and contract discharge report as resources, with schemas.
Choice 4: The signature is the operating manual
A fastC function signature, with the full annotation set, tells you:
- which memory regions are touched (
@mem) - which I/O capabilities the function needs (
@caps) - what must hold on entry (
@requires) - what is guaranteed on exit (
@ensures) - whether the function can panic (
@panics) - whether the function is pure, effectful, or I/O-doing (
@purity) - the complexity bound (
@complexity)
The agent reading a fastC signature does not need to read the body. The compiler will reject a body that does not satisfy the signature. The reviewer reviewing what the agent wrote does not need to read the body either — they review the signature, and they trust the compiler.
This is the part that changes the economics of code review. In the human era, reviewing a 500-line C diff is a 90-minute job because every line matters. In the agent era, reviewing a 500-line fastC diff is a 15-minute job because what matters is the 30 public signatures the diff added, and the compiler proved the bodies conform.
It is the cheap-talk-versus-costly-signal distinction from economics, applied to type systems. A comment that says “this function requires divisor != 0” is cheap talk; an annotation that the compiler enforces is a costly signal. Agents (and humans) reasoning over the codebase should treat annotations as load-bearing and comments as flavor. fastC’s design pushes the load-bearing information into annotations.
Choice 5: One curated answer per domain
A 150K-crate ecosystem is a search problem for an agent. Which logging crate is the current idiomatic answer? log? tracing? slog? env_logger? The agent does research, gets it half right, picks a deprecated one, ships code that compiles but uses a 2019-era API. We see this constantly.
fastC’s fastc-core launch set is opinionated: one cli, one log, one json, one toml, one http. The canonical idiom for each is documented in an AGENTS.md file next to the source. The agent generating code reaches for the named module and there is no choice to make. The post-1.7 split into vendor packages (fastc-core/cli, fastc-core/http) changes packaging, not surface. The five modules of the launch set will keep their final shape.
This is the same property that makes Go popular for agent-generated code despite Go’s binary size — the standard library has one canonical answer for most things, and that turns out to matter more than the language’s expressiveness.
Choice 6: Make the dangerous things impossible, not just discouraged
C makes system("rm -rf $foo") easy. The lint says don’t. The agent’s training data includes both the lint and millions of examples of the pattern. The lint loses.
fastC makes the pattern impossible to write in a function that does not declare CapProcSpawn in its signature. The compiler rejects the call. The agent that wants to do something dangerous has to carry the capability through the function signature, which the reviewer cannot miss. The dangerous thing is now visible from outside the function.
The same logic applies to network I/O (CapNetConnect), file writes (CapFsWrite), reading the environment (CapEnvRead), and so on. The capability set is finite and named. A function whose signature declares no capabilities is structurally pure with respect to I/O. Not because we trust the agent. Because the compiler refuses the call.
What this is not
Agent-friendly does not mean “the language is small enough that small models can generate it.” Token efficiency is real and we measure it, but the wedge is correctness, not generation cost. A model that gets the syntax right and the semantics wrong is worse than no model.
Agent-friendly does not mean “no humans involved.” Every line of fastC is still reviewed by a human before merge. The point of the design is that the review is cheaper, faster, and structurally focused on the parts the compiler does not handle — logic correctness, performance characteristics, architectural fit.
Agent-friendly does not mean “more annotations.” Java is heavily annotated; Java is not agent-friendly because the annotations do not interact with each other and do not change the compile-time guarantees in interesting ways. fastC’s annotation set is small, fixed, and each annotation is a compile-time obligation.
Why this needed a new language
The fair objection is that you can have a strict policy on Rust — no build.rs, no proc macros, no async, a curated dep list, comments-as-contracts. Why a new language?
Because policies do not survive contact with a million lines of generated code. The single-team discipline that can hold the policy line cannot keep holding it once the agent is generating five PRs a day across forty repositories. The language has to enforce what the team was hoping the policy would enforce. fastC is what that enforcement looks like as a language design: capabilities in the type system, contracts in the type system, no executable build steps, fixed annotation set, structured diagnostics, MCP-native protocol surface.
The shape of the bet is that those properties together cost the agent very little at generation time and save the reviewer a great deal at review time. The cross-language benchmarks in the README are the early evidence: matched or higher first-compile success across four open-weight models, zero silently-wrong outputs on the safety wedge, binary sizes in the C / Zig class. We will keep publishing the numbers.
If you want the long-form rationale, docs/MANIFESTO.md is the place. The version above is the version where we explain it without the marketing words.
Comments? Issues? Disagreements? Open an issue at github.com/Skelf-Research/fastc/issues.