中文 EN
← Back to Home

Building a Harness from Scratch: ~300 Lines of Python

Harness POC Cover
In the previous article, we discussed the theory of Agent = Model + Harness. In this article, we'll build one from scratch.

Goal

Build a minimal but usable Agent Harness in one afternoon, validating the following concepts:

Final product: 7 Python modules, ~300 lines of core code, supporting both CLI and programmatic usage.

github.com/greasebig/harness-poc

Architecture

harness/
├── agent.py       # Core Agent Loop — the heartbeat of the entire system
├── context.py     # AGENTS.md auto-discovery & system prompt construction
├── memory.py      # MEMORY.md cross-session persistent memory
├── permissions.py # Path whitelist + dangerous command interception
├── hooks.py       # PreToolUse / PostToolUse lifecycle
├── providers.py   # Anthropic + OpenAI + extensible
└── tools.py       # read_file, write_file, list_dir, shell

Core: Agent Loop

The soul of the entire system in just 30 lines:

while not done:
    response = self.provider.chat(self.messages, self.tools.schemas())

    if response.stop_reason == "tool_use":
        for tc in response.tool_calls:
            # Permission check → Hook → Execute → Result
            result = self._execute_tool(tc.name, tc.input)
            self.messages.append({
                "role": "user",
                "content": [{
                    "type": "tool_result",
                    "tool_use_id": tc.id,
                    "content": result,
                }],
            })
    else:
        final_text = response.text
        done = True

The model decides "what to do." The Harness handles "how to do it" — permission validation, hook triggers, result formatting. Interlocked, never stopping.

Five Design Decisions

1. Context ≤ 60 Lines

def _load_agents_md(self) -> str:
    # ...
    if len(lines) > 60:
        lines = lines[:57] + ["# ... (truncated for focus)"]
    return "\n".join(lines)

Give the Agent a map, not an encyclopedia. AGENTS.md files exceeding 60 lines are automatically truncated.

2. Every Tool Call Goes Through Permission Check

def _execute_tool(self, name, params):
    if not self.perm.allow(name, params):
        return "[BLOCKED] Permission denied."
    self.hooks.fire("pre_tool", name=name, params=params)
    result = self.tools.execute(name, params)
    self.hooks.fire("post_tool", name=name, params=params, result=result)
    return result

Permission → Hook → Execute → Hook. No shortcuts.

3. Memory is Explicit

The Agent must actively use the [MEMORY: ...] tag to write to long-term memory. Non-intrusive, doesn't pollute context.

# Agent writes in response:
# I notice this project uses pytest. [MEMORY: This project uses pytest for testing]

# Harness auto-extracts and writes to MEMORY.md:
# - [2026-05-24 20:30] This project uses pytest for testing

4. Providers are Plugins

Adding a new provider takes just 30 lines of code:

class MyProvider(BaseProvider):
    default_model = "my-model"
    def chat(self, messages, tools):
        # Your API call here
        return ProviderResponse(text=..., tool_calls=..., ...)

PROVIDERS["my_provider"] = MyProvider

5. Hooks are Optional

Without registering hooks, the system runs normally. With hooks, you gain logging, auditing, and verification capabilities.

agent.hooks.register("pre_tool", lambda **kw: print(f"🔧 {kw['name']}"))
agent.hooks.register("post_tool", lambda **kw: print(f"✅ done"))

Demo

$ python -m harness "List files and create hello.txt"

[harness] 🤖 anthropic/claude-sonnet-4-5-20250514 — 4 tools loaded
[harness] 💾 Saved 1 memory entries to MEMORY.md

Here's what I did:
1. Listed files: AGENTS.md, README.md, harness/, examples/
2. Created hello.txt with "Hello from harness!"

Three Examples

ExampleDemonstrates
01_basic_task.pyBasic task: list files + write file
02_hooks.pyHook system: log every tool call
03_memory.pyCross-session memory: Agent remembers and recalls

Why Build This POC?

The previous article cited LangChain's experimental data: the same model, with Harness optimization, achieved a 26% accuracy improvement.

This POC is the runnable version of that experiment. It proves:

  1. Harness isn't complex — core logic is only 300 lines of Python
  2. Harness is extensible — new providers, new tools, new hooks are all plug-and-play
  3. Harness compounds — every time the Agent makes a mistake, you add a rule, and it becomes more reliable

Next steps:

Fork it, break it, build on it.

github.com/greasebig/harness-poc