Factory.ai

Using Linters to Direct Agents

September 5, 2025 - 7 minutes read -

Share

Engineering

Agent Native Development

Agents write the code; linters write the law. We’re moving from “developers writing code with AI” to “developers orchestrating agents that build software.” The old guardrails (code review, conventions, tribal memory) aren’t enough. Agents need clear rules they can concretely verify. They need lint rules, not suggestions.

Cover image

Linters can encode your architecture, boundaries, and ergonomics directly into the code generation loop, exactly where LLM agents operate. When you do this, Agent‑Native Development switches from “back‑and‑forth with a robot intern” to “fast, deterministic collaboration with a compiler‑like partner.” Agents learn to self‑heal by obeying lint rules. You get consistent code, fewer human iterations, and a codebase that scales with your team and your agents.

New categories of lint rules for agents

The most effective agent-focused linters setups cover the following categories:

  • Grep-ability (Consistent formatting): Prefer named exports instead of default exports. Use consistent error types and define explicit DTOs to make code easier to search.
  • Glob-ability (Code organization): Keep the file structure predictable so agents can reliably place, find, and refactor code.
  • Architectural Boundaries: Avoid cross-layer imports. Use domain-specific allowlists or denylists. Enforce clear module boundaries. For example, feature folders should not access internal parts of the application layer.
  • Security and Privacy: Block plain text secrets in code. Require validation for all input schemas. Prevent the use of functions like eval or new Function.
  • Testability and Coverage: Place tests near the code they cover. Disallow network calls in unit tests. Ensure consistent use of asynchronous patterns.
  • Observability: Use structured logging for clarity. Include metadata with errors. Follow consistent naming conventions for telemetry data.
  • Documentation Signals: Add module-level docstrings or TSDoc comments for public APIs. Link to architectural decision records when making exceptions to rules.

How linters power Agent‑Native Development

Linters power Agent‑Native Development

Linters turn human intent into machine-enforced guarantees that allow agents to plan, generate, and self-correct without waiting on humans. The flow is simple. Humans define standards in AGENTS.md, which explains the “why” and provides examples. Those guidelines are then encoded as lint rules with clear severity, autofix, and waiver policies. The same rules run on save, pre-commit, CI, PR bots, and inside agent toolchains. Achieving “lint green” becomes the definition of "Done".

Linters enforce:

  • Searchability: code is easy to find for agents and humans (deterministic names, surfaces, and paths).
  • Glob‑ability / code structure: predictable file organization that supports safe, scripted change.
  • Grep‑ability / consistent formatting: reliable text search and indexing across the repo.
  • Testing discipline: presence of colocated unit tests and patterns that make tests meaningful.

Supporting pieces:

  • Formatters (e.g., Prettier) provide the baseline consistency that makes grep easier
  • AGENTS.md guide agent behavior; linters provide precise, automatic feedback that agents use to self‑heal until clean.

This results in agents that generate code, get automatic feedback from linters, and self‑learn/iterate until clean. Then “lint passing” becomes a proxy for “conforms to architecture and best practices.” Linting is the executable spec that ties human intent to agent output, ensuring consistent, navigable code at scale.

Human feedback is the new bottleneck

LLMs scaffold features in minutes where a decade ago, the bottleneck was typing speed and library knowledge. The constraint is how quickly we can turn human conventions into machine‑checkable rules so agents can run without waiting on feedback. Pre-specify your standards as lint rules and wire them into the loop so that agents get automatic feedback, self-correct, and need fewer human interventions.

Does the agent meet your standards?

  • Can the agent place files deterministically, with the right names, layers, and error semantics?
  • Can it wire imports the way your org expects?
  • Does it follow your error‑handling conventions?
  • Will it include required wrappers (auth, tracing, other middleware)?
  • Can it refactor at scale without breaking contracts?

Quality now hinges on how well your standards are codified and how reliably agents can obey them. Linters, once “style cops,” become the authoritative, executable spec for “how we build here,” bridging human intent and agent execution.

Linters to drive mass refactor migrations

Linters act as a migration engine. By encoding the “new way” as failing rules and the “old way” as detectable patterns with autofix, you gain a repo-wide detector, an execution plan, and a guardrail that ensures the change stays in place. This turns one-off rewrites into a continuous, agent-native process that finds every instance, fixes it safely, and prevents regressions.

Examples

  • Upgrade React to hooks, forbidding class component patterns and enforcing functional components with hooks.
  • Migrate from Moment.js to date‑fns, replacing legacy date formatting/parsing and removing the heavy dependency.
  • Prepare for Node 22 by banning deprecated Node 18 syntax/APIs and requiring modern equivalents.

How to do it

  • Define rules that forbid legacy patterns and require target APIs/structures; start as warnings to tune, then promote to errors.
  • Run the rules to surface all violations and prioritize by risk/owners.
  • Use agents with autofixes/codemods to batch the changes and open PRs verified by lint/tests.
  • Keep rules on the hot path (pre‑commit, CI, PR bots, agent toolchains) and iterate until false positives are gone.

How linters play with AGENTS.md guidelines

AGENTS.md explains intent, patterns, and examples in human language so agents know what to aim for.

But guidance alone suffers the following failure modes:

  • Ambiguity: natural language includes edge cases, so agents may believe they complied when they actually did not.
  • No guarantees: advice does not cause builds to fail, allowing drift to accumulate quietly.
  • Limited reach: prose can’t verify cross‑file imports, architectural boundaries, or error semantics.

Linters turn that intent into a compiler‑like contract with:

  • Validation: AST/type‑aware checks catch structural and architectural violations (module boundaries, import policies, error taxonomy, file placement).
  • On‑path enforcement: runs in local dev, pre‑commit, CI, PR bots, and inside the agent toolchain.
  • Automatic feedback: precise messages and autofixes let agents self‑correct until green.

In summary: Use both, but treat them differently:

  • AGENTS.md = the “why” and the examples. It maps each guideline to a RuleID and links to rule docs/ADRs.
  • Linting = the “how” and the guarantee. It encodes the rule, blocks violations, and provides machine feedback.

Code search-ability: make code easy to find, index, and refactor

Grep‑friendly code turns your repo into a reliable database for both humans and agents. It enables precise search, safe scripted refactors, and better retrieval for LLM context windows.

  • Deterministic placement: Agents can predict file locations from names.
  • Precise search: Named exports and absolute imports let agents and scripts locate definitions and usages without ambiguity.
  • Safer refactors: Consistent filenames and exports enable codemods and large‑scale rewrites with low blast radius.
  • Better retrieval: Vector and keyword search both improve when code has predictable shapes and identifiers.

If you adopt only one category, adopt this one

Example practices for a typescript codebase:

Named exports and imports

  • Why: ripgrep can precisely locate export const Foo and all import { Foo } from ...
  • Rule: ban default exports and enforce named imports

Absolute import paths

  • Why: tooling and agents can reason about provenance and there are fewer brittle ../../.. hops
  • Rule: ban relative imports across package boundaries and enforce @app/feature/... aliases

Filename and file‑organization conventions

  • Why: predictable locations let agents place, find, and refactor files deterministically
  • Rules:
    • enums live in enums.ts with only exports
    • types live in types.ts and can import from enums
    • index.ts re‑exports stable module surface
    • Unit tests colocated as .test.ts

These constraints make the codebase scriptable. Agents can combine ripgrep‑style queries with deterministic write locations to execute large, safe refactors, exactly how senior engineers batch‑edit at scale.

Code organization example:

// src/users/enums.ts
export enum UserRole {
  Admin = 'admin',
  Manager = 'manager',
  Member = 'member',
}
 
// src/users/types.ts
export type User = {
  id: string;
  role: UserRole;
  email: string;
};
 
// src/users/helper.ts
import { UserRole } from '@/users/enums';
import { User } from '@/users/types';
 
export function canManage(user: User): boolean {
	return user.role === UserRole.Admin || user.role === UserRole.Manager
}

Because it uses named exports, absolute imports, and deterministic file organization (enums.ts, types.ts, helper.ts), tools like ripgrep and agents can precisely find definitions/usages and perform safe, large‑scale refactors.

The lint development cycle

The lint development cycle

A tight, repeatable cycle that turns human insight into machine‑enforced policy and uses agents to erase drift at scale.

  • Observe drift: Spot a recurring anti‑pattern in review, logs, or metrics.
  • Codify the rule: Prompt an LLM to draft an ESLint rule (severity, autofix, tests, docs) that encodes the standard.
  • Surface violations: Run the rule across the repo to list precise locations and counts; triage by risk.
  • Remediate at scale: Spawn parallel agents to apply autofixes/codemods, batch PRs, and verify with tests and lint.
  • Prevent regressions: Put the rule on the hot path (pre‑commit, CI, PR bots, agent toolchains). Time‑box waivers and track compliance.

The result is that every observed issue becomes an executable constraint, agents clean up today’s debt, and the codebase self‑heals against future drift.

How we lint at Factory

At Factory, linting is our first response, not an afterthought: when a bug or drift shows up in a review, test, or incident, we immediately codify it as a rule, wire it into local dev, pre‑commit, CI, PR bots, and our agent toolchains, and treat “lint green” as the merge gate. This turns every lesson into an executable constraint that agents obey by default and humans can’t accidentally bypass. Concretely, we maintain dozens of rules such as:

  • Enforce a one-to-one mapping between logic files and colocated unit tests
  • Require proper error handling along with a consistent error taxonomy
  • Apply strict syntax and organization standards such as named exports, absolute imports, deterministic file placement, module boundaries, and no cyclic dependencies
  • Verify that middleware like authentication, tracing, and logging is correctly bootstrapped wherever it is needed
  • And much more beyond these points

The result is a codebase that self‑heals: new issues become rules, agents mass‑fix violations, and the guardrails prevent the same problem from landing twice.

The payoff

When guidelines become lint-enforced law, agent-native development stops being just a promise and begins to compound. Each rule you codify reduces review overhead, eliminates a class of regressions, and turns drift into an auto-fixed diff. Every lint-green merge makes the repo more searchable, easier to refactor, and more teachable. Each iteration transforms tribal knowledge into an executable specification that agents follow by default.

Over weeks, this results in smoother pull requests. Over quarters, it leads to faster lead times, safer large-scale changes, and fewer outages. Over years, it locks in architectural integrity while your teams can focus more on design, domain, and product. The end state is a self-healing codebase where consistency scales with both headcount and agent horsepower. Every new standard you encode continues to pay dividends indefinitely.

start building

Ready to build the software of the future?

Start building

Arrow Right Icon