Talal Ahmed
Back to home

How I Think About Graph, Loop, and Harness Engineering

So lately there are some terms that we are hearing on the internet like graph engineering, loop engineering, and harness engineering.

So when you study about them, it was never really some completely new stuff that suddenly appeared.

They are more like patterns for how we should design systems where LLMs are doing multi-step work, especially agentic and multi-agent systems.

Let's look at a coding agent example. These three concepts actually describe different layers of the same system.

Take a simple task:

"Fix the authentication bug in this repository and open a PR."

A coding agent has to solve much more than just "generate some code."

1. Graph engineering

Graph engineering is about the control flow and state topology of the agent system.

You might have something like:

User Task
   ↓
Planner
   ↓
Repository Analysis
   ↓
Coding Agent
   ↓
Test Runner
   ↓
Reviewer
   ↓
PR

But the graph isn't necessarily linear.

For example:

                 ┌→ Research Agent ──┐
                 │                   │
Planner ─────────┼→ Coding Agent ────┼→ Reviewer
                 │                   │
                 └→ Test Agent ──────┘
                         ↑
                         │
                    Tests fail

Now you're dealing with things like:

  • state propagation
  • branching
  • retries
  • conditional routing
  • agent-to-agent communication
  • tool invocation
  • failure paths
  • termination conditions

The graph answers:

"What components exist, and how does control move between them?"


2. Loop engineering

Now zoom into the coding agent itself.

A coding agent isn't really:

prompt → LLM → code

It's closer to:

Observe
   ↓
Reason
   ↓
Act
   ↓
Observe environment
   ↓
Evaluate
   ↓
Update state
   ↓
Act again

For example:

Inspect auth.py
      ↓
Form hypothesis
      ↓
Modify authentication logic
      ↓
Run pytest
      ↓
Test fails
      ↓
Read stack trace
      ↓
Update hypothesis
      ↓
Modify code
      ↓
Run pytest
      ↓
Tests pass

The important part is the feedback loop.

The agent isn't simply generating a solution.

It's interacting with an environment and using the result of its actions to update its next decision.

This introduces engineering questions like:

  • How much context should each iteration receive?
  • What should trigger another iteration?
  • How do we detect that we're stuck?
  • When should we change strategies?
  • How do we prevent infinite loops?
  • Should failed tests be fed back verbatim or summarized?
  • When should the agent ask for human intervention?

The loop answers:

"How does the agent behave over multiple interaction cycles?"


3. Harness engineering

Then there's the environment in which the agent operates.

This is where things get interesting.

A coding agent might have access to:

Filesystem
Terminal
Git
Repository search
Compiler
Test runner
Documentation
Issue tracker
Package manager
Static analyzer

But simply giving it tools isn't enough.

The harness can also provide:

Sandboxing
Permission boundaries
Context management
Checkpoints
Automatic test execution
Diff inspection
Failure classification
Environment reset
Token/context optimization
Evaluation

For example, instead of making the agent manually run tests and interpret 20,000 lines of output, the harness could execute the test suite and return:

143 tests passed
2 tests failed

Failure:
test_expired_jwt

Relevant traceback:
...

The model gets a much cleaner feedback signal.

So the harness answers:

"What environment does the agent operate in, and what feedback does that environment expose?"


The interesting part

These aren't three isolated concepts.

Graph, loop, and harness engineering as layers of the same coding-agent system

A real coding-agent system can use all three at the same time, but at different levels.

For example, at the system level, we might have a graph:

User Task
    ↓
Planner
    ↓
Coder
    ↓
Tester
    ↓
Reviewer
    ↓
PR

This is where graph engineering comes in.

The graph defines the overall workflow, the agents involved, how state moves between them, and what happens when something fails.

Now zoom into the Coder.

The Coder itself might run a loop:

Inspect code
    ↓
Form hypothesis
    ↓
Edit code
    ↓
Run tests
    ↓
Observe failure
    ↓
Update hypothesis
    ↓
Edit again
    ↓
Run tests
    ↓
...

That's loop engineering.

The loop controls how the agent continuously reasons, acts, observes feedback, and decides what to do next.

But how does the Coder actually inspect files, modify code, run tests, or look at git diffs?

Through the harness.

                 Coding Agent
                      │
        ┌─────────────┼─────────────┐
        ↓             ↓             ↓
   File system     Terminal        Git
        │             │             │
        ↓             ↓             ↓
      Files         Tests          Diff
        │             │             │
        └─────────────┼─────────────┘
                      ↓
                  Feedback
                      ↓
                 Agent Loop

So the harness provides the environment and interfaces through which the agent can actually interact with the repository.

You can therefore think about the whole system like this:

                 ┌──────────────────────┐
                 │        GRAPH         │
                 │                      │
                 │ Planner → Coder →    │
                 │ Tester → Reviewer    │
                 └──────────┬───────────┘
                            │
                            ↓
                    ┌───────────────┐
                    │     AGENT     │
                    │               │
                    │ Observe       │
                    │ → Reason      │
                    │ → Act         │
                    │ → Observe     │
                    │ → Repeat      │
                    └───────┬───────┘
                            │
                            ↓
                    ┌───────────────┐
                    │    HARNESS    │
                    │               │
                    │ Repo          │
                    │ Terminal      │
                    │ Tests         │
                    │ Git           │
                    │ Search        │
                    │ Evaluators    │
                    └───────────────┘

And underneath all of this is the foundation model.

This is why I think agent engineering is becoming less about prompt engineering and more about systems engineering.

The model is only one component.

You can take the same model and get dramatically different results depending on:

  • how you structure the graph
  • how you design the interaction loop
  • what tools the harness exposes
  • how failures are fed back
  • how state is maintained
  • how success is evaluated

So when we say we're "building a coding agent", we're really building a system around a model.

Graph engineering determines the structure.

Loop engineering determines the behavior.

Harness engineering determines the environment.

Back to home