This article systematically reviews AI Agent architecture and engineering practices, covering control flow, context engineering, tool design, memory, multi-agent organization, evaluation, tracing, and security. It is based on the OpenClaw implementation and emphasizes the critical role of Harness (testing and validation infrastructure) for system stability.

X AI KOLs News

Summary

This article systematically reviews AI Agent architecture and engineering practices, covering control flow, context engineering, tool design, memory, multi-agent organization, evaluation, tracing, and security. It is based on the OpenClaw implementation and emphasizes the critical role of Harness (testing and validation infrastructure) for system stability.

https://t.co/x9eqpjrSuS
Original Article
View Cached Full Text

Cached at: 05/21/26, 04:14 PM

What You Don’t Know About Agents: Principles, Architecture, and Engineering Practice

0. Too Long; Didn’t Read

After finishing “What You Don’t Know About Claude Code: Architecture, Governance, and Engineering Practice,” I realized my understanding of Agent internals was still shallow. Combined with our team’s growing experience applying Agents in production — but lacking a systematic write-up — I went back through the literature, open-source implementations, and my own code, then compiled this article.

This article focuses on the parts of Agent architecture that most affect engineering outcomes: control flow, context engineering, tool design, memory, multi-agent organization, evaluation, tracing, and safety. Finally, it ties all these design principles together by walking through OpenClaw’s implementation.

A few findings surprised me. Expensive models don’t always bring the improvements you’d expect; harness and test quality have a much bigger impact on success rates. When debugging agent behavior, check tool definitions first — most tool selection errors come from imprecise descriptions. Also, problems in the evaluation system are often harder to spot than agent problems themselves. Tinkering endlessly with agent code may not yield visible results. This article should provide answers to these questions.

1. How the Agent Loop Works

The core logic of an Agent Loop can be abstracted to fewer than 20 lines of code:

# Minimal agent loop
while True:
    # 1. Perceive: get current state
    # 2. Decide: LLM generates next action (tool call or final text)
    # 3. Act: execute the action (e.g., run a tool)
    # 4. Feedback: collect result and append to context

The corresponding control flow is: Perceive → Decide → Act → Feedback, looping until the model returns plain text:

[Perceive] -> [Decide] -> [Act] -> [Feedback] -> loop

I’ve looked at many Agent implementations and official SDKs — the structure is mostly the same, and the loop itself is remarkably stable. From a minimal implementation all the way up to supporting sub-agents, context compression, and Skills loading, the main loop barely changes. New capabilities are usually added outside the loop, not inside it.

New capabilities are typically added in only three ways:

  • Extending the tool set and handlers
  • Adjusting the system prompt structure
  • Externalizing state to files or databases

The loop body should never become a giant state machine. The model handles reasoning; external systems handle state and boundaries. Once that division is clear, the core loop logic rarely needs frequent changes.

Workflow vs. Agent: What’s the Difference?

Anthropic makes a direct distinction: if the execution path is hardcoded, it’s a Workflow; if the LLM dynamically decides the next step, it’s an Agent. The core difference is who controls the flow. In practice, many products labeled “Agent” are closer to Workflows. Neither is inherently better — the key is finding the right solution for the task.

Visualized, it’s clearer:

Workflow: Code decides each step — LLM acts as a component
Agent:    LLM decides each step — code provides tools and constraints

Five Common Control Patterns

Most AI systems, when broken down, are combinations of these five patterns. Many scenarios don’t need full Agent autonomy; composing a few of these patterns is often sufficient. The key is matching the design to the task.

  • Prompt Chaining: Break the task into sequential steps. Each step’s LLM processes the output of the previous step, with optional code checkpoints in between. Suitable for linear flows like “generate then translate” or “outline then full text.”
  • Routing: Classify the input and route it to a dedicated processing flow. Simple questions go to a lightweight model, complex ones to a strong model. Technical support and billing queries follow different logic.
  • Parallelization: Two variants. The “sectioning” approach splits the task into independent subtasks running concurrently. The “voting” approach runs the same task multiple times and takes a consensus. Suitable for high-risk decisions or scenarios needing multiple perspectives.
  • Orchestrator-Workers: A central LLM dynamically decomposes the task, delegates to worker LLMs, and synthesizes the results. nanobot’s spawn tool and learn-claude-code’s sub-agent pattern are examples.
  • Evaluator-Optimizer: The generator produces output, the evaluator provides feedback, and the loop runs until the quality criteria are met. Suitable for tasks like translation or creative writing where quality standards are hard to define precisely in code.

These patterns address how to structure the control flow. Next comes a more engineering-focused question: what makes the system run reliably.

2. Why Harness Matters More Than the Model

Harness refers to the test, verification, and constraint infrastructure built around the Agent. At a minimum, a harness includes: acceptance baselines, execution boundaries, feedback signals, and fallback mechanisms.

While the model is important, the factor that determines whether a system runs stably is often these peripheral engineering conditions. This judgment holds strongest for highly verifiable tasks like code writing, but for weakly verifiable tasks like open-ended research or multi-round negotiation, the model’s ceiling is still more critical.

OpenAI’s Agent-First Development Practice

Three engineers wrote a million lines of code in five months, producing nearly 1,500 PRs — ten times the traditional development speed. This speed wasn’t due to a super-powerful model, but to several correct engineering decisions:

  • If the Agent can’t see it, it doesn’t exist: Knowledge must exist in the codebase itself. External documentation is invisible to a running Agent. AGENTS.md only keeps about 100 lines as an index; details are split into docs/ directories and referenced on demand.
  • Encode constraints, don’t document them: Specifications written in documents are easily ignored. Constraints encoded in linters, type systems, or CI rules are enforceable. Architectural layering is enforced mechanically by custom linters, not by manual review.
  • Agent end-to-end autonomously completes tasks: From verifying current state, reproducing bugs, implementing fixes, driving application verification, to opening PRs, handling review feedback, and merging autonomously — the full chain requires no human intervention. The Agent actively queries logs, metrics, and traces.
  • Minimize merge friction: Occasional test failures are handled by rerunning rather than blocking progress. In high-throughput environments, the cost of waiting for human review often exceeds the cost of fixing small errors. The discipline of writing good code hasn’t disappeared — it’s just shifted from human review to machine-enforced constraints. Write once, enforce everywhere.

APP distributes logs, metrics, and traces through Vector into Victoria storage, providing LogQL, PromQL, and TraceQL query interfaces. Codex queries, correlates, and reasons using these three interfaces. After making changes, the Agent restarts the application, reruns the workload, and feeds results back to Codex. UI journeys are also ingested as input. The entire observability stack is created temporarily for a task and destroyed upon completion. The Agent doesn’t wait for someone to tell it about errors — it directly queries the system state to verify if a modification took effect.

What’s the Key Takeaway About Harness?

The chart below divides tasks into four states based on task clarity and verification automation. The top-right quadrant — clear goals and automatically verifiable results — is where Agents perform best. The top-left quadrant has clear tasks but requires human verification for acceptance, so throughput is bottlenecked by human review speed. The bottom-right quadrant has automated feedback but vague goals — the system will efficiently run in the wrong direction. The bottom-left quadrant lacks both, and an Agent is essentially useless there.

+------------------+------------------+
| Verify: Manual   | Verify: Auto    |
| Goal: Clear      | Goal: Clear     |
| Bottleneck: Human| Best for Agents |
+------------------+------------------+
| Verify: Manual   | Verify: Auto    |
| Goal: Vague      | Goal: Vague     |
| Agent ineffective| Efficiently wrong|
+------------------+------------------+

The job of the Harness is to push tasks into the top-right quadrant, so that right and wrong have machine-executable criteria, rather than relying on human supervision.

3. Why Context Engineering Determines Stability

Transformer attention complexity is O(n²). The longer the context, the more likely critical signals are diluted by noise. In practice, the most common failure mode is that once irrelevant content takes up a large portion of the context, the Agent’s decision quality drops noticeably. This phenomenon is often called “Context Rot.” Many problems that look like insufficient model capability can often be traced back to poorly organized context.

Why Split Context Into Layers?

The problem is usually not that the window is too short, but that the information density is wrong. Things used infrequently are loaded every time, stable rules are mixed with dynamic state, and the model sees more and more content while the truly useful parts become harder to notice.

The solution is to manage context in layers based on usage frequency and stability. Each layer only contains what belongs there:

  • Permanent Layer: Identity definition, project conventions, absolute prohibitions. Content that must hold for every session. Keep it short, hard, and enforceable.
  • On-demand Loading: Skills and domain knowledge. Descriptors are permanent; full content is injected only when triggered. Unused content takes no space.
  • Runtime Injection: Current time, channel ID, user preferences, etc. Dynamic info is assembled per turn.
  • Memory Layer: Cross-session experience is written to MEMORY.md. It doesn’t go directly into the system prompt; it’s read only when needed.
  • System Layer: Hooks or code rules handle deterministic logic. These never enter the context.

Don’t put deterministic logic into the context. Anything that can be expressed via hooks, code rules, or tool constraints should be handled by external systems, not by making the model read it repeatedly.

Three Common Compression Strategies

  1. Sliding Window: Discard old messages. Very low cost, but loses early context. Suitable for short conversations.
  2. LLM Summarization: The model generates a summary. Medium cost, loses details but retains decisions. Suitable for long tasks.
  3. Tool Result Replacement: Replace original output with a placeholder. Very low cost. Suitable for tool-call-intensive scenarios.

Sliding window is the simplest to implement but loses early decision-making context. An advanced form of LLM summarization is “branch summarization,” where the summary explicitly retains architectural decisions, unfinished tasks, and key constraints. For tool result replacement, micro_compact replaces old tool outputs each turn, while auto_compact triggers automatically when the context exceeds a threshold.

Reducing Repetitive Cost with Prompt Caching

During LLM inference, Transformer attention computes Key-Value pairs for each token. If the input prefix of the current request exactly matches that of a previous request, those KV pairs don’t need to be recomputed — they can be read from cache. This is the underlying principle of Prompt Caching. The prerequisite is an exact prefix match; content similarity alone won’t trigger it. Any different token breaks the match. Therefore, a cache-friendly design revolves around stability. System prompts, tool definitions, and long documents that remain largely unchanged across multiple requests are naturally cacheable. Dynamic information (current time, user input, tool call results) should be placed after the stable prefix, so as not to disrupt prefix stability.

This is directly related to the layered context design. The more stable the permanent layer, the higher the prefix hit rate and the lower the marginal cost. So “keep the permanent layer short and stable” is not just about saving tokens — it also protects cache hits. The benefits of lazy Skill loading are also here: on-demand content is appended after the stable prefix, not injected into it. Tool definitions also participate in cache computation. If an Agent with many MCP tools changes its toolset frequently, cache hits will keep failing. A counterintuitive point: a large, stable system prompt can have a lower actual cost than a small, frequently changing one, because the write cost is paid only once, and subsequent calls can get up to 90% off on reads.

Why Skills Should Be Loaded On Demand

Skills are a very effective pattern in context engineering. The core idea: the system prompt only holds an index; full knowledge is loaded on demand.

Skill descriptions should be short enough to avoid constantly inflating the permanent context token count, and should read more like routing conditions than feature introductions. They should at least specify when to use, when not to use, and what the output is. The most direct format is “Use when / Don’t use when” plus a few negative examples. Many routing failures are not about model capability, but about unclear boundaries.

The system prompt should also state the calling rules explicitly: before each reply, scan available_skills; when there’s a clear match, read the corresponding SKILL.md; when multiple matches, prefer the most specific one; if no match, don’t read any; load only one at a time.

The data in the chart is straightforward: without negative examples, accuracy dropped from a baseline of 73% to 53%; adding negative examples raised it to 85%, and response time also decreased by 18.1%. Negative examples are not optional — they are key to making Skill descriptions work.

Skills cannot just wait for the Agent to remember to use them; the descriptions must be scanned every turn. But the scanning cost must be low, and the actual number of loaded Skills must be controlled. If a Skill triggers external API writes, the system prompt should explicitly add rate limiting requirements: batch writes when possible, avoid per-item loops, and actively wait on 429 errors.

Two common pitfalls in writing Skill descriptors are worth mentioning. The first is length:

Routing accuracy differences are small, but each enabled Skill descriptor is permanently resident in the context. With many Skills, the cumulative cost of long descriptions is significant. The second is precision. Descriptions that are too short (“help with backend”) mean any backend task could trigger it, leading to chaotic routing. Truly effective descriptors are routing conditions, not feature introductions. “When should I be used” is far more important than “what can I do.”

Quantity also needs to be controlled: only high-frequency Skills should be in the permanent system prompt; low-frequency ones should not be in the default list — introduce them manually when needed. Very low frequency ones can be replaced by documentation; they don’t need to be a Skill. Typical anti-patterns: cramming a hundred-line playbook into the Skill body instead of splitting into supporting files; one Skill trying to cover review, deploy, debug, and incident; Skills with side effects having no explicit restriction on when they can be called. These three problems all cause Skill routing to lose accuracy, and they are hard to debug.

Skills and MCP have different characteristics in terms of context cost. Many MCP servers return the full result directly to the model, which can quickly consume the context budget. A CLI + single-line description of a Skill is closer to the calling method the model is familiar with, and is often more concise for data retrieval tasks that can be filtered and spliced. Of course, MCP also has clear use cases, such as tasks that require maintaining state (like Playwright).

What Is Most Easily Lost During Compression?

The most common problem during compression is not that the summary is too short, but that the retention priority is set incorrectly. LLMs typically prefer to delete information that seems recoverable. Early tool outputs are often removed first, but along with them, architectural decisions, reasons for constraints, and failure paths are also easily lost. It’s best to specify the retention priority when compressing in a document like CLAUDE.md:

  • Architecture decisions and reasons
  • Unfinished tasks and pending actions
  • Key constraints and assumptions
  • Tool call results (can be re-fetched if needed)
  • Detailed intermediate steps (least important)

Another easy trap during compression: don’t change identifiers. UUIDs, hashes, IPs, ports, URLs, filenames must be preserved verbatim. If a PR number or commit hash is altered even by one character, subsequent tool calls will break directly.

Why the File System Is a Good Interface for Context

Cursor calls this “Dynamic Context Discovery”: give less by default, read only when needed. The file system is a natural fit for this interface. Tool calls often return large amounts of JSON, and a few searches can pile up tens of thousands of tokens. Instead, write results to files and let the Agent read them on demand via grep, rg, or scripts. Tools write files, Agent reads files, and developers can also view them directly.

Cursor also validated this direction for MCP tools: they synchronized tool descriptions to folders; the Agent only sees tool names by default and queries the specific definition when needed. In A/B testing, the total token consumption of tasks calling MCP tools decreased by 46.9%.

The same idea applies to long task compression. When compression is triggered, don’t discard the history; instead, keep the full conversation record as a file, and only reference the file path in the summary. If the Agent later finds that the summary lacks details, it can still go back to the history file for retrieval. This way, compression becomes a lossy but traceable operation, not an unrecoverable hard truncation.

4. Tool Design Determines What an Agent Can Do

Context determines what the model can see; tools determine what the model can do. The quality of tool definitions is more critical than the quantity. Just 5 MCP servers can bring about ~55,000 tokens of tool definition overhead, using up nearly 30% of a 200K context before any conversation even starts. When there are too many tools, the model’s attention to individual tools is also diluted.

Tool problems are usually not about insufficient quantity, but about picking the wrong tool, unclear descriptions, returning irrelevant results, and the Agent not knowing how to fix errors.

How Tool Design Has Evolved

Tool design has roughly gone through three stages. The early approach was to directly wrap existing APIs as tools and give them to the model. Later, people realized that model misselection was not about model capability, but about the tool design perspective: they were designed for engineers, not for Agents.

First Generation: API Wrapping: Each API endpoint corresponded to one tool. The granularity was too fine; the Agent often had to coordinate multiple tools to accomplish one goal.

Second Generation: ACI (Agent-Computer Interface): Tools should correspond to the Agent’s goals, not the underlying API operations. Don’t expose create_file, write_content, set_permissions separately; instead, give a create_script(path, content, executable) that does it all at once.

Third Generation: Advanced Tool Use: On top of tool design, further optimize the discovery, invocation, and description of tools. This includes three main directions:

  • Tool Search (Dynamic Tool Discovery): Don’t put all tool definitions into the context at once. The Agent discovers tool definitions on demand via search_tools. Context retention can reach 95%, and Opus 4’s accuracy improved from 49% to 74%.
  • Programmatic Tool Calling (Code Orchestration): Don’t let intermediate data pass through the model turn by turn. Instead, let the model orchestrate multiple tool calls with code; intermediate results flow within the execution environment and never enter the LLM context. Token consumption can drop from ~150,000 to ~2,000.
  • Tool Use Examples (Example-Driven): Attach 1–5 real invocation examples to each tool. JSON Schema can only describe parameter types, but it can’t express how to call it. Adding examples improves tool call accuracy from 72% to 90%.

What Are the Principles of ACI Tool Design?

Just as HCI affects humans, tool design affects Agents directly. It’s not enough to check “can the tool be called?” — we also need to consider “if the call is wrong, can the Agent recover on its own?”

Three principles are clearer when viewed together. Bad practices have vague parameters, non-recoverable errors, and separate definitions from implementations. Good practices use something like betaZodTool to bind definition and implementation together, use parameter descriptions to constrain format directly, and provide structured error messages with correction suggestions.

Bad tool design: The tool only says what it can do, not when to use it or when not to. The result is that the Agent easily selects the wrong tool, fills in wrong parameters, and keeps retrying in circles after errors. Good ACI-compliant tool design: Clear boundaries, structured errors with correction suggestions — the Agent is more likely to pick the right tool the first time and can quickly recover if it fails.

When debugging an Agent, check tool definitions first. Most tool selection errors are caused by imprecise descriptions, not model capability. Also, be restrained with the number of tools. Anything that can be handled by Shell, requires only static knowledge, or is better suited as a Skill, does not need a new tool.

A Zod schema can simultaneously generate JSON Schema and TypeScript types, merging parameter validation and documentation constraints in one place. The tool call loop is also handled automatically by the SDK.

Why Tool Messages Should Be Isolated Internal Events

The framework produces some internal events during operation: compression happened, a notification was pushed, a tool call was skipped. These events need to be recorded in the session history, but they should not go into the LLM. Otherwise, the model sees a bunch of fields it doesn’t understand, wasting tokens.

The solution is to have two types of messages at the framework level:

  • AgentMessage: for the application layer, can carry any custom fields.
  • Message: the type actually sent to the LLM, only keeping user, assistant, and tool_result — the three standard types. Filter before sending.

The session history retains the complete framework state; the LLM only receives what it needs.

5. How to Design a Memory System

Agents don’t have native temporal continuity. When a session ends, the context is cleared, and the next startup doesn’t automatically retain the previous state. To give the system cross-session consistency, the memory layer must be designed separately. For an Agent, it’s infrastructure, not a feature that can be added later.

Where Do the Four Kinds of Memory Live?

This classification is not by storage medium, but by the problem the Agent actually needs to solve:

  • Context Window (Working Memory): The minimum information needed for the current task. Token-limited, must be actively managed.
  • Skills (Procedural Memory): How to do something — operational procedures, domain conventions. Loaded on demand, not permanently resident.
  • JSONL Session History (Episodic Memory): What happened. Persisted to disk, supports cross-session retrieval.
  • MEMORY.md (Semantic Memory): Facts that the Agent actively writes as important. Injected into the system prompt at each startup.

On the left is the Agent runtime. Only the context window exists in messages[] and will be cleared when the session ends. On the right is the persistent layer on disk: Skills files are loaded on demand, JSONL session history retains the full process and supports retrieval, and MEMORY.md accumulates stable facts written by the Agent, which are continuously injected in subsequent sessions.

How MEMORY.md and Skills Work Together

Actual implementations differ, but the core is solving two things: important facts must be kept, and the content injected into the model must not spiral out of control.

ChatGPT’s Four-Layer Memory

Taking it as a product implementation: it doesn’t use vector databases or RAG retrieval-augmented generation. The overall architecture is simpler than many expect:

  1. Session Metadata: Device, location, usage patterns — not persisted.
  2. User Memory: ~33 key preference facts — persisted, injected every time.
  3. Conversation Summary: Lightweight summaries of the ~15 most recent conversations — persisted.
  4. Current Session: The sliding window of the current conversation — not persisted.

OpenClaw’s Hybrid Retrieval

  1. memory/YYYY-MM-DD.md: Append-only logs, retaining raw details.
  2. MEMORY.md: Curated facts, actively maintained by the Agent.
  3. memory_search: Hybrid retrieval with 70% vector similarity + 30% keyword weighting.

The benefit of this design: readable, editable, and searchable. Markdown files can be viewed and revised directly. When searching, only the relevant content is pulled — no need to stuff the entire memory into the context. For most Agents, the scale of the memory store doesn’t require a vector store from the start. Structured Markdown plus keyword search already offers good debuggability, maintainability, and cost performance. When the scale exceeds a few thousand entries and semantic similarity retrieval is genuinely needed, then consider introducing vector retrieval.

When and How to Trigger Memory Consolidation — and How to Roll Back

With memory layering in place, the next step is not “should we save?” but “when to consolidate, and what to do if consolidation fails?”

This diagram emphasizes not “delete old messages,” but move them safely out of the active context. On the left is the ever-growing flow of conversation messages. The trigger threshold is tokenUsage / maxTokens >= 0.5. When reached, the success path first applies llmSummarize(toConsolidate) to the messages to be consolidated, then appends the summary to MEMORY.md, and finally updates lastConsolidatedIndex. The failure path writes the raw messages to archive/, preserving the full history, so that if consolidation fails, there’s no loss of context.

The most critical part is not how well the summary is written, but that the process itself must be reversible. The system only moves a pointer; it doesn’t delete raw messages. Even if consolidation fails, it can return to the raw archive to continue working.

6. How to Gradually Increase Agent Autonomy

Autonomy here doesn’t mean a few fewer human confirmations. It means enabling the Agent to drive tasks forward stably over longer time spans. The prerequisite is not to just hand over control, but to first build three types of infrastructure: cross-session continuation, within-session progress constraints, and background integration for slow I/O.

How to Continue Long Tasks Across Sessions

The most common failure of long tasks is not a single-step error, but that the task isn’t finished when the session ends. Even with compaction, two problems remain: trying to finish an entire application in one session (context runs out first), or completing only part of the work and failing to accurately resume the site in the next session (premature completion judgment).

A more stable approach is to split long tasks into two roles: an Initializer Agent and a Coding Agent. This pattern is best suited for tasks like code generation, application setup, refactoring, and migration — tasks that can’t be completed in one session but can be broken down into a batch of verifiable subtasks.

The Initializer Agent runs only once in the first session. It generates feature-list.json, init.sh, the initial git commit, and claude-progress.txt. It turns the task into a persistent external state. Subsequent sessions are executed by the Coding Agent in a loop: each session resumes from claude-progress.txt and git log, locates the current task, implements one feature, runs tests, updates the passes field, commits the code, and exits. Even if a crash happens mid-way, work can continue directly from the file system state, not from scratch.

The task progress should be in a file, not in the context. Use JSON for the feature list, not Markdown — structured formats are more stable for the model to modify. The task is complete only when all features in feature-list.json show "passes": true.

Why Task State Must Be Explicitly Written Out

Cross-session handling solves “where to continue next time.” Within a single session, we also need to solve “what step am I currently on?” Once a long task stretches out, without an external progress anchor, the Agent is prone to drift or to prematurely concluding before all tasks are done.

Task state should be explicitly recorded as an external control object, not left in the model’s working memory:

{
  "task_id": "feature-login",
  "status": "in_progress",  // "not_started" | "in_progress" | "completed" | "failed"
  "checklist": [
    {"item": "Add login form UI", "done": true},
    {"item": "Implement authentication API", "done": false}
  ]
}

The constraint is simple: only one task can be in_progress at a time. Each step completed updates the state before moving to the next. Optionally, add lightweight corrections — for example, if there’s no task state update for several consecutive turns, automatically inject a prompt about the current progress.

How to Handle Background I/O

As autonomy increases, what really slows down the main loop is usually not model inference, but external I/O like file operations, network requests, and long-running commands. Once these operations block the main loop, the execution rhythm degrades noticeably.

A practical approach is to move slow subprocesses into background threads. The results are injected into the next LLM call via a notification queue. The main loop doesn’t need to know many concurrency details; it only needs to check before each turn whether new results are available, then decide whether to continue, wait, or adjust the plan. This is usually more stable and maintainable than turning the entire loop into a complex async runtime.

7. How to Organize Multiple Agents

When talking about multi-agent systems, many people first think of parallelism. But the engineering challenges to solve first are isolation and collaboration, which correspond to two very different working modes.

The director mode is synchronous collaboration: a human interacts tightly with a single Agent, adjusting decisions each round. The obvious drawback: when the session ends, the context is gone, and the output is ephemeral.

The coordinator mode is asynchronous delegation: the human sets goals at the start, lets multiple Agents work in parallel, and reviews the final outputs. The human appears only at the start and end; intermediate outputs become persistent artifacts like branches and PRs. This is where the main value of multiple Agents lies — not just running several models, but turning continuous human involvement into final artifact review.

A common organizational pattern is a main Agent as Orchestrator overseeing the global plan, with multiple sub-agents working independently in parallel. They communicate via a JSONL inbox protocol, use Worktrees to isolate file modifications, and manage dependencies with a task graph.

What Are Sub-Agents Good For?

The searching, trial-and-error, and debugging processes within subtasks should not pollute the main Agent’s context. The main Agent only needs the conclusions. The exploration details stay in the sub-agent’s own message history.

Why Collaboration Must Be Formalized as a Protocol

Once multi-agent collaboration relies on natural language to align, it quickly breaks down. Models don’t reliably remember who promised what, or who is waiting for whose results. Once tasks start depending on each other, the protocol must be written clearly.

At a minimum, three things are needed: a protocol, a task graph, and isolation boundaries.

  • Protocol: The main Agent dispatches tasks to sub-agents via a JSONL message queue. Sub-agents only return summaries after execution; search and debug details stay in their own independent context.
  • Task Graph: .tasks/ records the task graph and dependencies.
  • Isolation: .worktrees/ isolates file modifications for each sub-agent.

The order matters: define the protocol first, establish isolation, then talk about collaboration and parallelism.

Hallucinations Can Amplify Each Other in Multi-Agent Systems

When multiple Agents interact frequently, errors can be amplified layer by layer. Agent A goes off first, Agent B reinforces it, Agent C adds more, and eventually all Agents converge on the same high-confidence wrong conclusion. This is where the value of cross-validation lies — it breaks the chain, allowing an independent judgment from one Agent instead of following the previous conclusion. Again, there’s an order: first, create a persistent task graph; then introduce teammates with identities; then introduce a structured communication protocol; finally, add cross-validation or external feedback (e.g., an independent second Agent, unit tests, a compiler, or human review).

Sub-Agent Depth Limits and Minimal Prompts

Sub-agents have two basic limits. First, a depth limit to prevent infinite recursion generating sub-sub-agents — a maximum depth is enough. Second, a minimal system prompt: only include sections for Tooling, Workspace, and Runtime. Do not include Skills and Memory instructions, to avoid permission leaks and to preserve isolation boundaries.

8. How to Evaluate Agents

Whether an Agent is doing the right thing ultimately depends on evaluation. Many teams postpone this step, and the result is: they change the prompt and don’t know if it got better; they switch models and don’t know if it regressed; in the end, they only have an uninterpretable set of fluctuating numbers. The core of evaluation is test cases, scoring criteria, and automated verification. The real difficulty is not whether there’s a score, but whether the score reflects actual quality.

Why Agent Evaluation Has a More Complex Structure

The top part shows traditional Single-turn evaluation: one prompt goes in, the model outputs one response, and we judge whether it’s correct. The bottom part shows Agent evaluation: first prepare tools, runtime environment, and a task; the Agent calls tools multiple times and modifies the environment state during execution; the final scoring is not about what it said, but about running a set of tests to verify what actually happened in the environment. Structurally, it’s more than one level more complex. That’s why traditional evaluation methods often fall short in Agent scenarios.

From that diagram, three groups of concepts are the ones to remember:

  1. Task, Trial, Grader: What to test, how many runs, how to score.
  2. Transcript (full execution record) and Outcome (final environment state): Evaluation must look at both.
  3. Agent Harness (the evaluated Agent’s runtime framework) and Evaluation Harness (the evaluation infrastructure): The latter is responsible for running tasks, scoring, and aggregating results. An Evaluation Suite is a collection of tasks — the raw material for evaluation.

Current Evaluation Landscape and Common Metrics

Agent evaluation is harder than traditional software evaluation: the input space is nearly infinite, LLMs are highly sensitive to prompt phrasing, and the same task can produce different results across runs. Survey data shows many teams still lack mature evaluation systems; human review and LLM scoring remain the most common methods.

Evaluation Methods:          Common Metrics:
Human annotation + LLM judge:  ~60%+ combined
Traditional ML metrics:        16.9%
No evaluation at all:         ~25%

Among specific statistical methods, the two most common are Pass@k and Pass^k. They have different purposes and should not be mixed. Pass@k is suitable for the development phase to answer “can this Agent theoretically do it?” Pass^k is suitable before deployment to answer “has any existing functionality been broken?” Mixing them can lead to misjudgment: too lenient regression testing misses issues; too strict capability evaluation triggers alarms for every small change.

The Differences Between Three Types of Graders

The reliability of an evaluation depends first on choosing the right grader. Among the three main types, determinism and coverage usually have an inverse relationship:

  1. Code Grader: String matching, unit tests, structural comparison. Highest determinism. Best for tasks with a clear right answer.
  2. Model Grader: Score against criteria, compare two answers, or run multiple models and vote for consensus.
  3. Human Grader: Expert sampling review, calibration. Reliable but slow. Best for establishing baselines.

Code graders are least likely to introduce noise due to poor design. If there’s a clear correct answer, use them first.

“Looking at what the Agent says” and “looking at what the system ends up like” are two different things. The Agent says “the booking is complete” — that’s looking at the transcript. A record actually exists in the database — that’s looking at the outcome. Relying solely on the transcript misses cases where it “said it but didn’t do it.” Relying solely on the outcome may miss when intermediate steps went wrong. Both must be covered.

Anthropic

Similar Articles

@AxtonLiu: https://x.com/AxtonLiu/status/2073791557547794579

X AI KOLs Timeline

This article discusses the concept of Agent OS, emphasizing the division of tasks into multiple workstations (fetch, refine, verify, confirm) through specialization, each managed by an independent Agent to achieve controllable automation. The author uses the example of digesting browser tabs to demonstrate how specialization isolates context, responsibility, and risks, ensuring the accuracy and reliability of AI output.

@Potatoloogs: https://x.com/Potatoloogs/status/2057391224592667051

X AI KOLs Timeline

This article deeply analyzes the concept of Agent Harness, which is the engineering infrastructure wrapped around an LLM, including 12 components such as orchestration loops, tool calling, memory systems, context management, etc. The article cites practices from companies like Anthropic, OpenAI, and LangChain, arguing for the critical role of the harness in production-grade AI agents.

@idoubicc: https://x.com/idoubicc/status/2069014328037330953

X AI KOLs Timeline

This article reviews the design highlights and shortcomings of the OpenClaw Agent framework, and shares the author's experience in designing a better agent framework, FastClaw, emphasizing principles such as cloud-native, lightweight, and multi-tenancy.

@Yonah_x: https://x.com/Yonah_x/status/2073313721829540171

X AI KOLs Timeline

This article shares the team's practice of drawing on OpenAI's Harness engineering philosophy to enable an AI Agent to run autonomously for 17 hours with 16 iterations of prompt optimization, and successfully launch the project, including key mechanisms such as anti-cheating and preventing early stopping.

@knoYee_: https://x.com/knoYee_/status/2062780637677752366

X AI KOLs Timeline

The author reviews three months of experience using multi-agent collaboration, summarizing five main pain points (such as conflicts between agents, ignoring boundary conditions, self-censorship failure, difficulty in merging decisions, and exposing harder problems after compressed execution) and two insights (the high value of read-only review agents, and that agent conflicts expose ambiguous requirements), emphasizing the core decision-making role of humans in AI collaboration.