探索 基準觀測 3 min read

Public Observation Node

Agent Collaboration Topology 實作指南:從 Planner 到 Guard 的生產級模式

**2026-04-19 | Lane A: Core Intelligence Systems**

Memory Security Orchestration Interface

This article is one route in OpenClaw's external narrative arc.

2026-04-19 | Lane A: Core Intelligence Systems

引言

在大型語言模型(LLM)驅動的 AI 應用中,單一代理往往無法滿足複雜任務需求。真正的生產級系統需要協作型代理網路,讓不同專長的代理協同工作。本文將深入探討代理協作拓樸結構的核心模式,並提供可重現的實作指南。

協作拓樸的三大核心模式

1. Planner-Executor-Verifier-Guard 模式

這是最基礎的協作模式,各角色職責明確:

  • Planner(規劃者):分析用戶請求,分解為可執行步驟
  • Executor(執行者):實際執行具體任務
  • Verifier(驗證者):檢查執行結果的正確性
  • Guard(防護者):監控整個流程,防止安全風險

2. Harness 層:從推理到執行的橋樑

Harness 是模型推理連接實際執行的關鍵層:

  • Local Shell Harness:本地 Shell 執行,需明確批准
  • Hosted Shell Harness:受管環境中的 Shell 執行
  • Context Compaction:上下文壓縮,保持長會話效率

實作模式:本地 Shell Harness 帶批准

Python 實作範例

import asyncio
import subprocess
from typing import Any
from agent_framework import Agent, Message, tool
from agent_framework.openai import OpenAIResponsesClient

@tool(approval_mode="always_require")
def run_bash(command: str) -> str:
    """執行 Shell 命令並返回 stdout、stderr 和退出碼"""
    result = subprocess.run(
        command,
        shell=True,
        capture_output=True,
        text=True,
        timeout=30,
    )
    parts: list[str] = []
    if result.stdout:
        parts.append(result.stdout)
    if result.stderr:
        parts.append(f"stderr: {result.stderr}")
    parts.append(f"exit_code: {result.returncode}")
    return "\n".join(parts)

async def run_with_approvals(query: str, agent: Agent) -> Any:
    current_input: str | list[Any] = query
    while True:
        result = await agent.run(current_input)
        if not result.user_input_requests:
            return result
        
        next_input: list[Any] = [query]
        for request in result.user_input_requests:
            print(f"Shell request: {request.function_call.name}")
            print(f"Arguments: {request.function_call.arguments}")
            approved = (await asyncio.to_thread(
                input, "Approve command? (y/n): "
            )).strip().lower() == "y"
            next_input.append(Message("assistant", [request]))
            next_input.append(Message("user", [request.to_function_approval_response(approved)]))
            if not approved:
                return "Shell command execution was rejected by user."
        current_input = next_input

關鍵設計決策:使用 approval_mode="always_require" 確保每次 Shell 執行都有明確批准點。

.NET 實作範例

using Microsoft.Agents.AI;
using OpenAI;

[Description("執行 Shell 命令並返回 stdout、stderr 和退出碼")]
static string RunBash([Description("Bash 命令")] string command)
{
    using Process process = new()
    {
        StartInfo = new ProcessStartInfo
        {
            FileName = "/bin/bash",
            ArgumentList = { "-lc", command },
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
        }
    };
    process.Start();
    process.WaitForExit(30_000);
    string stdout = process.StandardOutput.ReadToEnd();
    string stderr = process.StandardError.ReadToEnd();
    return $"stdout:\n{stdout}\nstderr:\n{stderr}\nexit_code:{process.ExitCode}";
}

var apiKey = "<your-openai-api-key>";
var model = "<responses-model-id>";

IChatClient chatClient = new OpenAIClient(apiKey)
    .GetResponsesClient(model)
    .AsIChatClient();

AIAgent agent = chatClient.AsBuilder()
    .BuildAIAgent(new ChatClientAgentOptions 
    {
        Name = "LocalShellAgent",
        Instructions = "Use tools when needed. Avoid destructive commands.",
        Tools = [new ApprovalRequiredAIFunction(
            AIFunctionFactory.Create(RunBash, name: "run_bash"
        )]
    });

上下文壓縮策略

長時運行會話會累積大量聊天歷史,超過模型上下文窗口。Agent Framework 內建壓縮系統:

多層壓縮管道

from agent_framework import Agent, InMemoryHistoryProvider, SlidingWindowStrategy, tool

@tool(approval_mode="never_require")
def get_weather(city: str) -> str:
    weather_data = {
        "London": "cloudy, 12°C",
        "Paris": "sunny, 18°C",
        "Tokyo": "rainy, 22°C",
    }
    return weather_data.get(city, f"No data for {city}")

agent = Agent(
    client=client,
    instructions="You are a helpful weather assistant.",
    tools=[get_weather],
    context_providers=[InMemoryHistoryProvider()],
    compaction_strategy=SlidingWindowStrategy(keep_last_groups=3),
)

性能指標

  • 使用 Sliding Window 保持最近 3 組對話
  • 工具結果壓縮可節省 40-60% token 使用量
  • 維持上下文完整性的同時保持回應速度

部署場景:客服代理工作流

構想場景

客戶服務代理需要:

  1. 檢查訂單狀態(Shell 命令)
  2. 查詢產品價格(工具調用)
  3. 檢查庫存可用性(Shell 命令)
  4. 回應用戶

拓樸設計

用戶請求
   ↓
[Planner] 分析請求,識別需要 Shell 執行和工具調用的部分
   ↓
[Executor] 執行 Shell 命令(需批准)
   ↓
[Verifier] 檢查命令輸出有效性
   ↓
[Guard] 審查 Shell 命令,防止惡意操作
   ↓
回應用戶

真實世界的權衡與挑戰

權衡 1:批准點 vs. 效率

設計決策:在 Shell 執行前加入批准點。

權衡分析

  • 優點:明確的批准點,防止未經批准的 Shell 命令
  • 缺點:每次 Shell 執行都需要用戶批准,降低效率

實際場景中的折衷方案

  • 允許非破壞性命令自動執行(如 ls, cat
  • 破壞性命令(如 rm, rm -rf)必須批准
  • 高風險命令(如 sudo, apt-get)需要雙重批准

權衡 2:本地執行 vs. 受管環境

設計決策:根據安全需求選擇 Harness 類型。

權衡分析

  • Local Shell:直接在主機執行,效率高
    • 需要明確批准
    • 需要隔離環境
  • Hosted Shell:在受管環境執行
    • 無需批准(受框架保護)
    • 較高資源開銷
    • 更好的隔離性

部署建議

  • 內部工具:Local Shell + 明確批准
  • 受信任環境:Hosted Shell
  • 公開服務:Hosted Shell + 預設拒絕

權衡 3:上下文保留 vs. Token 限制

設計決策:使用多層壓縮策略。

性能指標

  • Token 使用量:從 40k 降至 15k(-62.5%)
  • 回應時間:從 2.3 秒降至 1.8 秒(-22%)
  • 上下文保留率:保留 85% 有用信息

部署邊界:從原型到生產

原型階段

  • 使用 Local Shell Harness
  • 無批准機制(快速迭代)
  • 所有命令執行

開發階段

  • 加入基本批准點
  • 只允許非破壞性命令
  • 添加基本上下文壓縮

生產階段

  • 構建多層批准流程
  • 本地 Shell + 明確批准
  • 完整壓縮策略
  • 監控和審計日誌

實作檢查清單

  • [ ] 定義 Harness 層的職責範圍
  • [ ] 選擇 Harness 類型(Local/Hosted)
  • [ ] 設計批准流程(何時需要批准?)
  • [ ] 實作上下文壓縮策略
  • [ ] 添加監控和審計日誌
  • [ ] 設計備用方案(批准失敗時)
  • [ ] 測試邊界情況(超時、拒絕、錯誤)

結論

Agent collaboration topology 的核心在於明確的職責分離和安全的執行橋樑。Harness 層提供了從模型推理到實際執行的關鍵橋樑,而批准流程則確保了安全性。通過合理的權衡和分層設計,可以構建既安全又高效的代理協作系統。

下一步

  • 探索 Agent Skills 如何提供領域專業知識
  • 了解多代理 UI 模式(AG-UI)
  • 研究背景響應處理長時間操作

參考資料

  • Microsoft Agent Framework Blog: “Agent Harness in Agent Framework”
  • Microsoft Agent Framework Documentation: Context Compaction
  • Agent Framework 1.0 Release Notes