Why Control Theory Is the Secret Sauce Behind Harness Engineering for AI Agents
The article explains how applying control‑theoretic concepts such as set points, sensors, controllers, actuators and feedback loops transforms AI‑driven coding agents into reliable, self‑correcting systems, illustrating the shift from prompt and context engineering to a full harness engineering practice.
Introduction
Harness Engineering is the practice of building a structured execution environment – a “harness” – that guides AI coding agents toward stable, correct outcomes. The harness typically consists of architecture documentation, an AGENTS.md instruction file, automated tests, custom linters, CI/CD pipelines, observability stacks, and permission models. By externalising architectural rules and quality criteria, the system can repeatedly verify and correct the agent’s work.
Evolution from Prompt to Context to Harness
Prompt Engineering
In 2023 engineers focused on crafting prompts (role, examples, format) to obtain usable code from large language models. Over‑detailed step‑by‑step prompts began to limit model capability as models grew more powerful.
Context Engineering
With larger context windows, tools such as Cursor let agents retrieve files, run searches, and invoke IDE actions via shortcuts ( @, cmd + k, cmd + l). The core challenge is providing exactly the information the model needs at a given moment—neither too little (causing guesses) nor too much (causing noise).
Harness Engineering
When agents can plan, execute multi‑step operations, run tests, read error messages, and apply fixes autonomously, prompts and context become components of a larger closed‑loop system. OpenAI’s internal practices include:
Observability stacks that expose logs, traces, and metrics for agents to decide when a task is complete.
Rich product context so agents behave like new team members.
Encoding architectural constraints and engineering taste via custom linters and structural tests.
The focus shifts from “getting a prettier single answer” to “ensuring the system converges over many iterations.”
Why Control Theory?
Designing a harness is fundamentally a control problem: engineers define a goal (set point), observe the system state (sensors), compute deviation, decide on corrective actions (controller), apply them (actuator), and feed the result back. This closed‑loop view explains how autonomous agents can be guided toward a desired state despite disturbances.
Feedback Control Pattern
A classic feedback controller repeatedly reconciles a desired state with the actual state. Kubernetes exemplifies this pattern:
for {
desired := getDesiredState() // read YAML‑declared target
actual := getActualState() // observe current cluster state
diff := compare(desired, actual)
if diff != empty {
reconcile(diff) // create/delete/update resources
}
wait(syncPeriod) // pause before next iteration
}Before declarative systems, engineers performed imperative actions (SSH, manual restarts). The control‑theoretic view shows how a declarative loop turns ad‑hoc commands into a self‑correcting system.
Mapping Control Theory to Harness Engineering
Set Point (What Is “Correct”?)
The set point is an explicit definition of the desired codebase state—layering rules, naming conventions, dependency directions, performance benchmarks—encoded in AGENTS.md, architecture docs, or golden rule files. Without a machine‑readable definition, agents will repeat the same mistakes.
Sensor (Perceiving Deviation)
Traditional sensors already exist:
Compilers for syntax correctness.
Test suites for behavioral correctness.
Linters for style and basic architectural checks.
Harness Engineering extends sensors in two ways:
Custom linters and structural tests cover more mechanically verifiable properties (e.g., UI layer must not import Service layer).
Semantic sensors powered by LLMs evaluate design‑principle compliance, detect “AI‑generated junk,” or assess code‑style consistency.
Controller (Deciding How to Correct)
The controller combines deterministic orchestration rules (CI conditions, retry limits, approval gates) with LLM‑driven semantic reasoning. Deterministic rules narrow the decision space; the LLM provides the nuanced “how‑to‑fix” guidance.
Actuator (Applying the Control Signal)
Actuators are the interfaces agents can invoke: file editors, shells, browsers, test commands, Git, CI/CD APIs, and monitoring queries. They turn the controller’s decision into concrete actions such as code edits, test runs, or log retrieval.
Feedback Loop (Self‑Correction)
The loop repeatedly feeds sensor data back to the controller, enabling continuous convergence. Typical layers:
Short loop (seconds‑to‑minutes): lint, formatting, type checks, unit tests.
Mid loop (minutes‑to‑hours): integration tests, end‑to‑end validation, architectural checks, PR reviews.
Long loop (days‑weeks): production metrics, user feedback, incident post‑mortems, rule updates.
Each layer corrects deviations at an appropriate timescale, preventing over‑fitting to any single signal.
Practical Guidance
Define Clear Goals Break tasks into explicit acceptance criteria. Example for a “cancel order” endpoint:
POST /api/orders/{id}/cancel allowed only for orders in PENDING_PAYMENT or PAID_PENDING_REVIEW states.
Return 404 if order does not exist, 409 if state disallows cancellation, 401/403 for unauthenticated/unauthorized requests.
Write audit record to order_events with cancel_reason, cancelled_by, cancelled_at.
Do not modify existing order, payment, or query APIs.
Provide unit and integration tests covering success, duplicate, unauthorized, and concurrent cancellation scenarios.
If a DB migration is required, include migration script, rollback plan, and impact analysis.
Any test failure, state‑machine violation, or missing audit log prevents task completion.
Strengthen Sensors Expose to agents:
Test results (unit, integration, end‑to‑end).
Runtime signals (logs, metrics, tracing).
UI state (DOM snapshots, browser actions).
Environment state (filesystem, config files, dependencies, process list).
Design Actionable Error Signals Good feedback combines the error description with a concrete remediation step, e.g.:
HTTP Handler layer must not depend on repository package. Move data‑access logic to the service layer, refer to docs/architecture/layers.md, then run <code>golangci-lint run</code> and <code>go test ./...</code> to verify.Limit Actuators Implement a tiered permission model:
Low‑risk actions (read‑only files, log inspection) are allowed by default.
Medium‑risk actions (code edits, test execution) run in sandboxed environments with directory and network restrictions.
High‑risk actions (production DB access, main‑branch pushes, credential changes) require explicit human approval or are prohibited.
Treat the Codebase as a Memory System Persist goals and constraints in AGENTS.md , documentation, and Architecture Decision Records (ADRs). Keep these artifacts synchronized with the code so agents can retrieve the “why” behind decisions, not just the “what.”
Introduce Multi‑Layer Feedback Loops Combine short, mid, and long loops as described above to ensure rapid local correction while allowing slower, higher‑level governance to evolve the harness itself.
Conclusion
Viewing Harness Engineering through control theory clarifies the engineer’s role: define clear targets, provide comprehensive observations, compute deviations, apply bounded corrective actions, and close the feedback loop. Engineers become designers of the harness that steers autonomous agents toward reliable, self‑correcting software development.
“A good Harness Engineer is both the designer of the harness and the helmsman steering the system.”
DevOps in Software Development
Exploring how to boost efficiency in development, turning a cost center into a value center that grows with the business. We share agile and DevOps insights for collective learning and improvement.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
