📑 Table of Contents

Harness Engineering: Prepping TypeScript for AI Agents

📅 · 📁 Tutorials · 👁 7 views · ⏱️ 7 min read
💡 A growing discipline called 'harness engineering' focuses on making codebases AI-agent-friendly, starting with TypeScript.

The Rise of Harness Engineering

Vibe coding is no longer a novelty — it is becoming a genuine development workflow. But teams adopting AI coding agents like Anthropic's Claude Code, Cursor, and GitHub Copilot Workspace are discovering a hard truth: the quality of AI-generated code depends heavily on the quality of the codebase it operates in.

This realization is giving rise to a new discipline that practitioners are calling 'harness engineering' — the deliberate practice of structuring codebases so that coding agents can produce reliable, maintainable output instead of what developers derisively call 'AI slop.'

At its core, harness engineering borrows the concept of affordances from design theory. An affordance describes the possible actions an actor can take in relation to an object. When the actor is a coding agent and the object is a TypeScript codebase, affordances determine whether the agent writes coherent, idiomatic code — or generates expensive technical debt.

Why TypeScript Is Ground Zero

TypeScript has emerged as the ideal proving ground for harness engineering for several reasons. Its static type system provides coding agents with rich contextual signals. Interfaces, type aliases, generics, and discriminated unions all act as guardrails that constrain what an agent can reasonably produce.

When a function signature declares it accepts a UserProfile and returns a Result<Order, ValidationError>, an AI agent has dramatically less room to hallucinate incorrect behavior compared to a loosely typed JavaScript equivalent. The type system effectively narrows the search space of valid outputs.

Beyond types, TypeScript's ecosystem — including ESLint, Prettier, and tsconfig's strict mode — provides automated feedback loops that agents can use to self-correct. Teams reporting success with coding agents almost universally enable strict: true in their TypeScript configurations.

Key Principles of Harness Engineering

1. Explicit Over Implicit

Coding agents thrive on explicitness. This means favoring named types over inline type literals, exporting clear interfaces for module boundaries, and avoiding any or unknown without wrapper utilities. Every implicit decision a human developer makes from experience is a potential failure point for an agent.

2. Convention Files and Agent Instructions

Leading teams now maintain dedicated instruction files — such as CLAUDE.md for Claude Code or .cursorrules for Cursor — that codify project conventions. These files describe architectural patterns, naming conventions, preferred libraries, and anti-patterns to avoid. They function as a 'system prompt' for the codebase itself.

3. Small, Composable Modules

Agents perform better when files are short, focused, and follow single-responsibility principles. A 2,000-line service file overwhelms context windows and increases the probability of incoherent edits. Breaking code into composable modules of 100–300 lines gives agents manageable units of work.

4. Rich Test Harnesses

The 'harness' in harness engineering is not metaphorical. Comprehensive test suites — especially integration tests with clear arrange-act-assert patterns — give agents a concrete way to validate their own output. Teams report that agents paired with strong test coverage produce substantially fewer regressions.

5. Type-Driven Domain Modeling

Using TypeScript's type system to model domain concepts explicitly — through branded types, discriminated unions, and exhaustive pattern matching — provides agents with a map of business logic. When the type system encodes that an Order can only transition from 'pending' to 'confirmed' to 'shipped,' the agent is far less likely to generate invalid state transitions.

Practical Steps for Teams

Teams looking to adopt harness engineering practices can start with a focused checklist:

  • Enable strict: true in tsconfig.json and resolve all resulting errors
  • Ban any via ESLint rules (@typescript-eslint/no-explicit-any)
  • Create a conventions file (e.g., CLAUDE.md) describing architecture, patterns, and constraints
  • Refactor large files into focused modules under 300 lines
  • Add barrel exports (index.ts) that expose clean public APIs per module
  • Write integration tests for critical paths with descriptive test names
  • Use Zod or similar runtime validation at system boundaries to complement static types
  • Document 'why' in comments, not just 'what' — agents benefit from intent signals

The Cost of Ignoring Affordances

Teams that deploy coding agents into poorly structured codebases consistently report negative outcomes: generated code that compiles but violates architectural boundaries, functions that duplicate existing utilities, and subtle bugs from misunderstood context. The cleanup cost often exceeds the time saved by the agent.

Conversely, teams that invest in harness engineering report that agents like Claude Code can handle multi-file refactors, implement new features from issue descriptions, and even propose architectural improvements — all with minimal human correction.

The Bigger Picture

Harness engineering represents a philosophical shift in how developers think about code quality. Historically, clean code practices served human readability. Now they serve a dual audience: human maintainers and AI agents. The good news is that these goals are almost perfectly aligned — code that is explicit, well-typed, modular, and well-tested is better for everyone.

As coding agents grow more capable throughout 2025, the competitive advantage will increasingly belong to teams whose codebases are ready to harness them effectively. TypeScript, with its expressive type system and rich tooling ecosystem, is where that advantage is most accessible today.

The era of 'just let the AI figure it out' is already ending. The era of engineering for AI collaboration has begun.