在前一篇文章《多 Agent 系統的 Token 用量調優指南》中,我們介紹了 選擇性 Context 傳遞 作為多 Agent 系統中最具影響力的優化策略之一。本文將深入實作層面,探討如何在真實系統中建構精確的 Context 傳遞機制,讓每個 Agent 只接收完成任務所需的最小資訊集合。
為什麼 Context 傳遞是關鍵瓶頸?
多 Agent 系統的 Context 爆炸
傳統的完整 Context 傳遞:
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ Orchestrator │
│ │ │
│ │ 傳遞完整 Context (30,000 tokens) │
│ ├─────────────────────────────────────────────────────────▶ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Agent A │ 實際只需要 2,000 tokens │
│ │ 資料分析師 │ 浪費:28,000 tokens (93%) │
│ └─────────────┘ │
│ │ │
│ │ 傳遞完整 Context + Agent A 輸出 (35,000 tokens) │
│ ├─────────────────────────────────────────────────────────▶ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Agent B │ 實際只需要 3,000 tokens │
│ │ 程式開發者 │ 浪費:32,000 tokens (91%) │
│ └─────────────┘ │
│ │ │
│ │ 傳遞完整 Context + 所有輸出 (45,000 tokens) │
│ ├─────────────────────────────────────────────────────────▶ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Agent C │ 實際只需要 1,500 tokens │
│ │ 文件撰寫者 │ 浪費:43,500 tokens (97%) │
│ └─────────────┘ │
│ │
│ 總 Token 消耗:110,000 tokens │
│ 實際所需:~6,500 tokens │
│ 浪費比例:94% │
│ │
└─────────────────────────────────────────────────────────────────────┘
選擇性傳遞的效益
優化後的選擇性 Context 傳遞:
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ Orchestrator │
│ │ │
│ │ 只傳遞相關 Context (2,000 tokens) │
│ ├─────────────────▶ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Agent A │ 輸出結構化摘要 (500 tokens) │
│ │ 資料分析師 │ │
│ └─────────────┘ │
│ │ │
│ │ 只傳遞 Agent A 摘要 + 相關需求 (3,000 tokens) │
│ ├─────────────────▶ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Agent B │ 輸出結構化結果 (800 tokens) │
│ │ 程式開發者 │ │
│ └─────────────┘ │
│ │ │
│ │ 只傳遞文件所需資訊 (1,500 tokens) │
│ ├─────────────────▶ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Agent C │ │
│ │ 文件撰寫者 │ │
│ └─────────────┘ │
│ │
│ 總 Token 消耗:6,500 tokens │
│ 節省:94% │
│ │
└─────────────────────────────────────────────────────────────────────┘
核心概念:Context 依賴圖
定義 Agent 間的資訊依賴
1from dataclasses import dataclass, field
2from typing import Optional
3from enum import Enum
4
5class ContextType(Enum):
6 """Context 類型"""
7 FULL_OUTPUT = "full_output" # 完整輸出
8 SUMMARY = "summary" # 摘要
9 KEY_FINDINGS = "key_findings" # 關鍵發現
10 STRUCTURED_DATA = "structured" # 結構化資料
11 METADATA = "metadata" # 元資料
12 NONE = "none" # 不需要
13
14@dataclass
15class ContextDependency:
16 """Context 依賴定義"""
17 source_agent: str # 來源 Agent
18 context_type: ContextType # 需要的 Context 類型
19 required_fields: list[str] = field(default_factory=list) # 需要的特定欄位
20 max_tokens: Optional[int] = None # 最大 token 數限制
21 priority: int = 1 # 優先級(用於裁剪)
22
23@dataclass
24class AgentContextSpec:
25 """Agent 的 Context 規格"""
26 agent_name: str
27 dependencies: list[ContextDependency] = field(default_factory=list)
28 requires_original_task: bool = True
29 requires_shared_state: bool = False
30 max_total_context: int = 8000 # 最大總 Context
31
32# 定義依賴關係圖
33CONTEXT_DEPENDENCY_GRAPH = {
34 "orchestrator": AgentContextSpec(
35 agent_name="orchestrator",
36 dependencies=[], # Orchestrator 接收原始請求
37 requires_original_task=True,
38 max_total_context=4000
39 ),
40
41 "requirements_analyst": AgentContextSpec(
42 agent_name="requirements_analyst",
43 dependencies=[], # 只需要原始任務
44 requires_original_task=True,
45 max_total_context=6000
46 ),
47
48 "architect": AgentContextSpec(
49 agent_name="architect",
50 dependencies=[
51 ContextDependency(
52 source_agent="requirements_analyst",
53 context_type=ContextType.KEY_FINDINGS,
54 required_fields=["functional_requirements", "non_functional_requirements"],
55 max_tokens=1500
56 )
57 ],
58 requires_original_task=True,
59 max_total_context=8000
60 ),
61
62 "developer": AgentContextSpec(
63 agent_name="developer",
64 dependencies=[
65 ContextDependency(
66 source_agent="requirements_analyst",
67 context_type=ContextType.SUMMARY,
68 max_tokens=500
69 ),
70 ContextDependency(
71 source_agent="architect",
72 context_type=ContextType.STRUCTURED_DATA,
73 required_fields=["architecture_decision", "tech_stack", "api_design"],
74 max_tokens=2000
75 )
76 ],
77 requires_original_task=False, # 不需要原始任務
78 max_total_context=10000
79 ),
80
81 "code_reviewer": AgentContextSpec(
82 agent_name="code_reviewer",
83 dependencies=[
84 ContextDependency(
85 source_agent="developer",
86 context_type=ContextType.FULL_OUTPUT, # 需要完整程式碼
87 max_tokens=5000
88 ),
89 ContextDependency(
90 source_agent="architect",
91 context_type=ContextType.SUMMARY,
92 required_fields=["coding_standards"],
93 max_tokens=500
94 )
95 ],
96 requires_original_task=False,
97 max_total_context=8000
98 ),
99
100 "doc_writer": AgentContextSpec(
101 agent_name="doc_writer",
102 dependencies=[
103 ContextDependency(
104 source_agent="requirements_analyst",
105 context_type=ContextType.KEY_FINDINGS,
106 max_tokens=800
107 ),
108 ContextDependency(
109 source_agent="architect",
110 context_type=ContextType.SUMMARY,
111 max_tokens=600
112 ),
113 ContextDependency(
114 source_agent="developer",
115 context_type=ContextType.METADATA,
116 required_fields=["file_list", "api_endpoints", "function_signatures"],
117 max_tokens=1000
118 ),
119 ContextDependency(
120 source_agent="code_reviewer",
121 context_type=ContextType.SUMMARY,
122 max_tokens=400
123 )
124 ],
125 requires_original_task=True,
126 max_total_context=6000
127 )
128}
視覺化依賴關係
Agent 依賴關係圖:
┌─────────────────┐
│ 原始任務請求 │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Orchestrator │
└────────┬────────┘
│
┌──────────────┼──────────────┐
│ │ │
▼ │ │
┌─────────────────┐ │ │
│ Requirements │ │ │
│ Analyst │ │ │
└────────┬────────┘ │ │
│ │ │
┌───────┴───────┐ │ │
│ KEY_FINDINGS │ │ │
▼ ▼ │ │
┌─────────┐ ┌─────────┐ │ │
│Architect│ │Doc │◀──┘ │
└────┬────┘ │Writer │ │
│ └────▲────┘ │
│ STRUCTURED │ │
▼ │ │
┌─────────┐ │ │
│Developer│────────┤ METADATA │
└────┬────┘ │ │
│ │ │
│ FULL_OUTPUT │ │
▼ │ │
┌─────────┐ │ │
│Code │────────┘ SUMMARY │
│Reviewer │ │
└─────────┘ │
圖例:
─────▶ Context 傳遞方向
標籤為 Context 類型
策略一:結構化輸出格式
強制 Agent 輸出結構化資料,便於下游選擇性提取。
定義標準輸出格式
1from pydantic import BaseModel, Field
2from typing import Optional, Any
3from enum import Enum
4
5class OutputSection(Enum):
6 """輸出區段類型"""
7 SUMMARY = "summary"
8 KEY_FINDINGS = "key_findings"
9 DETAILED_ANALYSIS = "detailed_analysis"
10 RECOMMENDATIONS = "recommendations"
11 STRUCTURED_DATA = "structured_data"
12 METADATA = "metadata"
13 RAW_OUTPUT = "raw_output"
14
15class AgentOutput(BaseModel):
16 """標準化 Agent 輸出"""
17 agent_name: str
18 task_id: str
19
20 # 必要的摘要區段(永遠保留)
21 summary: str = Field(
22 description="簡短摘要,100-200 字",
23 max_length=500
24 )
25
26 # 關鍵發現(高優先級保留)
27 key_findings: list[str] = Field(
28 default_factory=list,
29 description="關鍵發現清單,每項 50 字以內"
30 )
31
32 # 結構化資料(可選擇性提取欄位)
33 structured_data: dict[str, Any] = Field(
34 default_factory=dict,
35 description="結構化資料,便於下游精確提取"
36 )
37
38 # 詳細內容(通常不傳遞給下游)
39 detailed_output: Optional[str] = Field(
40 default=None,
41 description="完整詳細輸出,僅在需要時傳遞"
42 )
43
44 # 元資料(輕量級資訊)
45 metadata: dict[str, Any] = Field(
46 default_factory=dict,
47 description="執行元資料:時間、tokens、狀態等"
48 )
49
50 def get_section(self, section: OutputSection, max_tokens: Optional[int] = None) -> str:
51 """取得特定區段,可選擇性截斷"""
52 content = ""
53
54 if section == OutputSection.SUMMARY:
55 content = self.summary
56 elif section == OutputSection.KEY_FINDINGS:
57 content = "\n".join(f"- {f}" for f in self.key_findings)
58 elif section == OutputSection.STRUCTURED_DATA:
59 import json
60 content = json.dumps(self.structured_data, ensure_ascii=False, indent=2)
61 elif section == OutputSection.DETAILED_ANALYSIS:
62 content = self.detailed_output or ""
63 elif section == OutputSection.METADATA:
64 import json
65 content = json.dumps(self.metadata, ensure_ascii=False)
66 elif section == OutputSection.RAW_OUTPUT:
67 content = self.detailed_output or self.summary
68
69 # 截斷處理
70 if max_tokens and len(content) > max_tokens * 4: # 粗略估算
71 content = content[:max_tokens * 4] + "\n...[已截斷]"
72
73 return content
74
75 def to_minimal_context(self) -> str:
76 """轉換為最小 Context(僅摘要和關鍵發現)"""
77 parts = [f"[{self.agent_name} 輸出摘要]", self.summary]
78 if self.key_findings:
79 parts.append("\n關鍵發現:")
80 parts.extend(f"- {f}" for f in self.key_findings[:5])
81 return "\n".join(parts)
82
83 def to_full_context(self) -> str:
84 """轉換為完整 Context"""
85 parts = [
86 f"[{self.agent_name} 完整輸出]",
87 f"\n摘要:{self.summary}",
88 ]
89 if self.key_findings:
90 parts.append("\n關鍵發現:")
91 parts.extend(f"- {f}" for f in self.key_findings)
92 if self.detailed_output:
93 parts.append(f"\n詳細內容:\n{self.detailed_output}")
94 return "\n".join(parts)
95
96
97# 特定 Agent 的輸出格式
98class RequirementsAnalystOutput(AgentOutput):
99 """需求分析師輸出"""
100 structured_data: dict = Field(default_factory=lambda: {
101 "functional_requirements": [],
102 "non_functional_requirements": [],
103 "constraints": [],
104 "assumptions": [],
105 "user_stories": []
106 })
107
108class ArchitectOutput(AgentOutput):
109 """架構師輸出"""
110 structured_data: dict = Field(default_factory=lambda: {
111 "architecture_decision": "",
112 "tech_stack": {},
113 "api_design": [],
114 "data_model": {},
115 "coding_standards": [],
116 "deployment_strategy": ""
117 })
118
119class DeveloperOutput(AgentOutput):
120 """開發者輸出"""
121 structured_data: dict = Field(default_factory=lambda: {
122 "file_list": [],
123 "api_endpoints": [],
124 "function_signatures": [],
125 "dependencies": [],
126 "code_files": {}
127 })
128
129class CodeReviewerOutput(AgentOutput):
130 """程式碼審查者輸出"""
131 structured_data: dict = Field(default_factory=lambda: {
132 "issues": [],
133 "suggestions": [],
134 "security_concerns": [],
135 "performance_notes": [],
136 "approval_status": ""
137 })
Agent 輸出格式化器
1import anthropic
2import json
3from typing import Type
4
5client = anthropic.Anthropic()
6
7class StructuredOutputAgent:
8 """
9 強制結構化輸出的 Agent
10
11 確保輸出符合標準格式,便於下游選擇性提取
12 """
13
14 OUTPUT_FORMAT_PROMPT = """
15你必須以以下 JSON 格式輸出結果:
16
17{{
18 "summary": "簡短摘要(100-200字)",
19 "key_findings": ["發現1", "發現2", ...],
20 "structured_data": {{
21 // 根據任務類型的結構化資料
22 {structured_fields}
23 }},
24 "detailed_output": "完整詳細內容(可選)"
25}}
26
27重要:只輸出 JSON,不要其他說明。
28"""
29
30 def __init__(
31 self,
32 agent_name: str,
33 system_prompt: str,
34 output_class: Type[AgentOutput] = AgentOutput,
35 model: str = "claude-sonnet-4-20250514"
36 ):
37 self.agent_name = agent_name
38 self.system_prompt = system_prompt
39 self.output_class = output_class
40 self.model = model
41
42 def _get_structured_fields_hint(self) -> str:
43 """取得結構化欄位提示"""
44 if self.output_class == RequirementsAnalystOutput:
45 return """
46 "functional_requirements": ["需求1", "需求2"],
47 "non_functional_requirements": ["效能要求", "安全要求"],
48 "constraints": ["限制1"],
49 "user_stories": ["作為...我想要...以便..."]
50"""
51 elif self.output_class == ArchitectOutput:
52 return """
53 "architecture_decision": "架構決策說明",
54 "tech_stack": {"backend": "...", "frontend": "...", "database": "..."},
55 "api_design": [{"endpoint": "/api/...", "method": "GET", "description": "..."}],
56 "coding_standards": ["標準1", "標準2"]
57"""
58 elif self.output_class == DeveloperOutput:
59 return """
60 "file_list": ["file1.py", "file2.py"],
61 "api_endpoints": ["/api/endpoint1", "/api/endpoint2"],
62 "function_signatures": ["def func1(a: int) -> str", ...],
63 "code_files": {"filename.py": "code content..."}
64"""
65 elif self.output_class == CodeReviewerOutput:
66 return """
67 "issues": [{"severity": "high/medium/low", "description": "..."}],
68 "suggestions": ["建議1", "建議2"],
69 "security_concerns": ["安全問題1"],
70 "approval_status": "approved/needs_revision/rejected"
71"""
72 return "{}"
73
74 def execute(self, task: str, context: str = "") -> AgentOutput:
75 """執行任務並返回結構化輸出"""
76 format_prompt = self.OUTPUT_FORMAT_PROMPT.format(
77 structured_fields=self._get_structured_fields_hint()
78 )
79
80 full_prompt = f"{context}\n\n任務:{task}\n\n{format_prompt}" if context else f"任務:{task}\n\n{format_prompt}"
81
82 response = client.messages.create(
83 model=self.model,
84 max_tokens=4096,
85 system=self.system_prompt,
86 messages=[{"role": "user", "content": full_prompt}]
87 )
88
89 # 解析輸出
90 output_text = response.content[0].text
91 try:
92 # 處理可能的 markdown 程式碼區塊
93 if "```json" in output_text:
94 output_text = output_text.split("```json")[1].split("```")[0]
95 elif "```" in output_text:
96 output_text = output_text.split("```")[1].split("```")[0]
97
98 data = json.loads(output_text.strip())
99
100 return self.output_class(
101 agent_name=self.agent_name,
102 task_id="", # 由呼叫者設定
103 summary=data.get("summary", ""),
104 key_findings=data.get("key_findings", []),
105 structured_data=data.get("structured_data", {}),
106 detailed_output=data.get("detailed_output"),
107 metadata={
108 "input_tokens": response.usage.input_tokens,
109 "output_tokens": response.usage.output_tokens
110 }
111 )
112 except (json.JSONDecodeError, KeyError) as e:
113 # 降級處理:將原始輸出作為 detailed_output
114 return self.output_class(
115 agent_name=self.agent_name,
116 task_id="",
117 summary=output_text[:200] + "..." if len(output_text) > 200 else output_text,
118 key_findings=[],
119 structured_data={},
120 detailed_output=output_text,
121 metadata={"parse_error": str(e)}
122 )
策略二:Context 提取器
根據下游 Agent 的需求,從上游輸出中精確提取所需資訊。
完整實作
1import anthropic
2from dataclasses import dataclass
3from typing import Optional
4
5client = anthropic.Anthropic()
6
7@dataclass
8class ExtractionRequest:
9 """提取請求"""
10 source_output: AgentOutput
11 target_agent: str
12 dependency: ContextDependency
13
14class ContextExtractor:
15 """
16 Context 提取器
17
18 根據依賴規格從 Agent 輸出中提取所需資訊
19 """
20
21 def __init__(self, use_llm_extraction: bool = True):
22 """
23 Args:
24 use_llm_extraction: 是否使用 LLM 進行智能提取(更準確但有成本)
25 """
26 self.use_llm_extraction = use_llm_extraction
27
28 def extract(self, request: ExtractionRequest) -> str:
29 """
30 從來源輸出提取目標 Agent 所需的 Context
31 """
32 source = request.source_output
33 dep = request.dependency
34
35 # 根據 Context 類型選擇提取策略
36 if dep.context_type == ContextType.NONE:
37 return ""
38
39 elif dep.context_type == ContextType.SUMMARY:
40 return self._extract_summary(source, dep)
41
42 elif dep.context_type == ContextType.KEY_FINDINGS:
43 return self._extract_key_findings(source, dep)
44
45 elif dep.context_type == ContextType.STRUCTURED_DATA:
46 return self._extract_structured_data(source, dep)
47
48 elif dep.context_type == ContextType.METADATA:
49 return self._extract_metadata(source, dep)
50
51 elif dep.context_type == ContextType.FULL_OUTPUT:
52 return self._extract_full_output(source, dep)
53
54 return source.to_minimal_context()
55
56 def _extract_summary(self, source: AgentOutput, dep: ContextDependency) -> str:
57 """提取摘要"""
58 content = f"[{source.agent_name} 摘要]\n{source.summary}"
59 return self._truncate(content, dep.max_tokens)
60
61 def _extract_key_findings(self, source: AgentOutput, dep: ContextDependency) -> str:
62 """提取關鍵發現"""
63 parts = [f"[{source.agent_name} 關鍵發現]"]
64
65 # 如果指定了特定欄位,只提取那些欄位
66 if dep.required_fields:
67 for field in dep.required_fields:
68 if field in source.structured_data:
69 value = source.structured_data[field]
70 if isinstance(value, list):
71 parts.append(f"\n{field}:")
72 parts.extend(f" - {item}" for item in value[:10])
73 else:
74 parts.append(f"\n{field}: {value}")
75 else:
76 # 提取所有關鍵發現
77 for finding in source.key_findings[:10]:
78 parts.append(f"- {finding}")
79
80 content = "\n".join(parts)
81 return self._truncate(content, dep.max_tokens)
82
83 def _extract_structured_data(self, source: AgentOutput, dep: ContextDependency) -> str:
84 """提取結構化資料"""
85 import json
86
87 if dep.required_fields:
88 # 只提取指定欄位
89 extracted = {}
90 for field in dep.required_fields:
91 if field in source.structured_data:
92 extracted[field] = source.structured_data[field]
93 data = extracted
94 else:
95 data = source.structured_data
96
97 content = f"[{source.agent_name} 結構化資料]\n{json.dumps(data, ensure_ascii=False, indent=2)}"
98 return self._truncate(content, dep.max_tokens)
99
100 def _extract_metadata(self, source: AgentOutput, dep: ContextDependency) -> str:
101 """提取元資料"""
102 import json
103
104 if dep.required_fields:
105 # 從 structured_data 中提取指定的元資料欄位
106 extracted = {}
107 for field in dep.required_fields:
108 if field in source.structured_data:
109 extracted[field] = source.structured_data[field]
110 data = extracted
111 else:
112 data = source.metadata
113
114 content = f"[{source.agent_name} 元資料]\n{json.dumps(data, ensure_ascii=False, indent=2)}"
115 return self._truncate(content, dep.max_tokens)
116
117 def _extract_full_output(self, source: AgentOutput, dep: ContextDependency) -> str:
118 """提取完整輸出"""
119 content = source.to_full_context()
120 return self._truncate(content, dep.max_tokens)
121
122 def _truncate(self, content: str, max_tokens: Optional[int]) -> str:
123 """截斷內容"""
124 if max_tokens is None:
125 return content
126 # 粗略估算:1 token ≈ 4 字元(中英混合)
127 max_chars = max_tokens * 3
128 if len(content) > max_chars:
129 return content[:max_chars] + "\n...[已截斷]"
130 return content
131
132 def extract_with_llm(
133 self,
134 source: AgentOutput,
135 target_agent: str,
136 extraction_prompt: str
137 ) -> str:
138 """
139 使用 LLM 進行智能提取
140
141 適用於需要更精確理解和提取的情況
142 """
143 prompt = f"""從以下 Agent 輸出中提取 {target_agent} 所需的資訊。
144
145來源 Agent:{source.agent_name}
146來源輸出:
147{source.to_full_context()}
148
149提取要求:
150{extraction_prompt}
151
152請只輸出提取後的內容,保持簡潔。"""
153
154 response = client.messages.create(
155 model="claude-3-5-haiku-20241022", # 使用便宜模型做提取
156 max_tokens=1000,
157 messages=[{"role": "user", "content": prompt}]
158 )
159
160 return response.content[0].text
161
162
163class ContextBuilder:
164 """
165 Context 建構器
166
167 根據依賴圖為目標 Agent 建構完整的 Context
168 """
169
170 def __init__(
171 self,
172 dependency_graph: dict[str, AgentContextSpec],
173 extractor: Optional[ContextExtractor] = None
174 ):
175 self.dependency_graph = dependency_graph
176 self.extractor = extractor or ContextExtractor()
177 self._output_store: dict[str, AgentOutput] = {}
178
179 def store_output(self, output: AgentOutput):
180 """儲存 Agent 輸出"""
181 self._output_store[output.agent_name] = output
182
183 def build_context(
184 self,
185 target_agent: str,
186 original_task: str
187 ) -> str:
188 """
189 為目標 Agent 建構 Context
190
191 Args:
192 target_agent: 目標 Agent 名稱
193 original_task: 原始任務描述
194
195 Returns:
196 建構好的 Context 字串
197 """
198 spec = self.dependency_graph.get(target_agent)
199 if not spec:
200 return original_task
201
202 context_parts = []
203 total_tokens = 0
204
205 # 1. 添加原始任務(如果需要)
206 if spec.requires_original_task:
207 task_context = f"[原始任務]\n{original_task}"
208 context_parts.append(task_context)
209 total_tokens += len(task_context) // 3 # 粗略估算
210
211 # 2. 按優先級排序依賴
212 sorted_deps = sorted(spec.dependencies, key=lambda d: d.priority, reverse=True)
213
214 # 3. 提取每個依賴的 Context
215 for dep in sorted_deps:
216 if dep.source_agent not in self._output_store:
217 continue
218
219 source_output = self._output_store[dep.source_agent]
220
221 request = ExtractionRequest(
222 source_output=source_output,
223 target_agent=target_agent,
224 dependency=dep
225 )
226
227 extracted = self.extractor.extract(request)
228
229 # 檢查是否會超過總限制
230 extracted_tokens = len(extracted) // 3
231 if total_tokens + extracted_tokens > spec.max_total_context:
232 # 嘗試截斷
233 remaining = spec.max_total_context - total_tokens
234 if remaining > 100:
235 extracted = extracted[:remaining * 3] + "\n...[已截斷]"
236 else:
237 continue # 跳過這個依賴
238
239 context_parts.append(extracted)
240 total_tokens += extracted_tokens
241
242 return "\n\n---\n\n".join(context_parts)
243
244 def get_context_stats(self, target_agent: str) -> dict:
245 """取得 Context 統計"""
246 spec = self.dependency_graph.get(target_agent)
247 if not spec:
248 return {}
249
250 stats = {
251 "target_agent": target_agent,
252 "max_total_context": spec.max_total_context,
253 "dependencies": []
254 }
255
256 for dep in spec.dependencies:
257 dep_info = {
258 "source": dep.source_agent,
259 "type": dep.context_type.value,
260 "max_tokens": dep.max_tokens,
261 "available": dep.source_agent in self._output_store
262 }
263 stats["dependencies"].append(dep_info)
264
265 return stats
策略三:相關性過濾
使用 LLM 判斷哪些資訊與目標任務相關。
完整實作
1import anthropic
2import json
3from dataclasses import dataclass
4from typing import Optional
5
6client = anthropic.Anthropic()
7
8@dataclass
9class RelevanceScore:
10 """相關性評分"""
11 content: str
12 score: float # 0-1
13 reason: str
14 should_include: bool
15
16class RelevanceFilter:
17 """
18 相關性過濾器
19
20 使用 LLM 判斷內容與目標任務的相關性,
21 只保留高相關性的內容
22 """
23
24 RELEVANCE_PROMPT = """分析以下內容與目標任務的相關性。
25
26目標任務:
27{task}
28
29目標 Agent:{target_agent}
30目標 Agent 職責:{agent_role}
31
32待評估內容:
33{content}
34
35請以 JSON 格式評估相關性:
36{{
37 "score": 0.0-1.0,
38 "reason": "簡短說明",
39 "key_relevant_parts": ["相關部分1", "相關部分2"],
40 "irrelevant_parts": ["不相關部分1"]
41}}
42
43評分標準:
44- 1.0: 完全相關,必須包含
45- 0.7-0.9: 高度相關,建議包含
46- 0.4-0.6: 部分相關,可選包含
47- 0.1-0.3: 低相關,通常不需要
48- 0.0: 完全不相關
49
50只返回 JSON。"""
51
52 def __init__(
53 self,
54 model: str = "claude-3-5-haiku-20241022",
55 relevance_threshold: float = 0.5
56 ):
57 self.model = model
58 self.relevance_threshold = relevance_threshold
59 self._cache: dict[str, RelevanceScore] = {}
60
61 def _compute_cache_key(self, task: str, content: str) -> str:
62 import hashlib
63 combined = f"{task[:100]}|{content[:200]}"
64 return hashlib.md5(combined.encode()).hexdigest()
65
66 def score_relevance(
67 self,
68 content: str,
69 task: str,
70 target_agent: str,
71 agent_role: str
72 ) -> RelevanceScore:
73 """評估內容相關性"""
74 # 檢查快取
75 cache_key = self._compute_cache_key(task, content)
76 if cache_key in self._cache:
77 return self._cache[cache_key]
78
79 prompt = self.RELEVANCE_PROMPT.format(
80 task=task,
81 target_agent=target_agent,
82 agent_role=agent_role,
83 content=content[:3000] # 限制長度
84 )
85
86 response = client.messages.create(
87 model=self.model,
88 max_tokens=500,
89 messages=[{"role": "user", "content": prompt}]
90 )
91
92 try:
93 text = response.content[0].text
94 if "```" in text:
95 text = text.split("```")[1].split("```")[0]
96 if text.startswith("json"):
97 text = text[4:]
98 data = json.loads(text.strip())
99
100 result = RelevanceScore(
101 content=content,
102 score=data.get("score", 0.5),
103 reason=data.get("reason", ""),
104 should_include=data.get("score", 0.5) >= self.relevance_threshold
105 )
106 except (json.JSONDecodeError, KeyError):
107 result = RelevanceScore(
108 content=content,
109 score=0.5,
110 reason="評估失敗,使用預設值",
111 should_include=True
112 )
113
114 self._cache[cache_key] = result
115 return result
116
117 def filter_context_parts(
118 self,
119 parts: list[str],
120 task: str,
121 target_agent: str,
122 agent_role: str,
123 max_parts: Optional[int] = None
124 ) -> list[str]:
125 """
126 過濾 Context 部分,只保留相關內容
127
128 Args:
129 parts: Context 片段列表
130 task: 目標任務
131 target_agent: 目標 Agent
132 agent_role: Agent 職責描述
133 max_parts: 最多保留幾個部分
134
135 Returns:
136 過濾後的 Context 片段列表
137 """
138 scored_parts = []
139
140 for part in parts:
141 if not part.strip():
142 continue
143 score = self.score_relevance(part, task, target_agent, agent_role)
144 if score.should_include:
145 scored_parts.append((score.score, part))
146
147 # 按相關性排序
148 scored_parts.sort(key=lambda x: x[0], reverse=True)
149
150 # 限制數量
151 if max_parts:
152 scored_parts = scored_parts[:max_parts]
153
154 return [part for _, part in scored_parts]
155
156
157class SmartContextFilter:
158 """
159 智能 Context 過濾器
160
161 結合規則和 LLM 的混合過濾策略
162 """
163
164 # 不同 Agent 角色的關鍵字
165 AGENT_KEYWORDS = {
166 "developer": ["程式", "code", "實作", "implement", "API", "函數", "class"],
167 "architect": ["架構", "architecture", "設計", "design", "模式", "pattern"],
168 "reviewer": ["審查", "review", "問題", "issue", "建議", "suggestion"],
169 "doc_writer": ["文件", "document", "說明", "description", "API", "用法"],
170 "tester": ["測試", "test", "用例", "case", "驗證", "verify"]
171 }
172
173 def __init__(
174 self,
175 use_llm_filter: bool = True,
176 relevance_threshold: float = 0.5
177 ):
178 self.use_llm_filter = use_llm_filter
179 self.llm_filter = RelevanceFilter(relevance_threshold=relevance_threshold) if use_llm_filter else None
180
181 def _keyword_filter(self, content: str, target_agent: str) -> bool:
182 """基於關鍵字的快速過濾"""
183 keywords = self.AGENT_KEYWORDS.get(target_agent, [])
184 if not keywords:
185 return True
186 content_lower = content.lower()
187 return any(kw.lower() in content_lower for kw in keywords)
188
189 def filter(
190 self,
191 context_parts: list[str],
192 task: str,
193 target_agent: str,
194 agent_role: str
195 ) -> list[str]:
196 """
197 智能過濾 Context
198
199 流程:
200 1. 關鍵字快速過濾
201 2. LLM 相關性評估(如果啟用)
202 """
203 # 階段 1:關鍵字快速過濾
204 keyword_filtered = [
205 part for part in context_parts
206 if self._keyword_filter(part, target_agent)
207 ]
208
209 # 如果過濾後內容很少,保留全部
210 if len(keyword_filtered) <= 2:
211 keyword_filtered = context_parts
212
213 # 階段 2:LLM 相關性過濾
214 if self.use_llm_filter and self.llm_filter:
215 return self.llm_filter.filter_context_parts(
216 keyword_filtered,
217 task,
218 target_agent,
219 agent_role,
220 max_parts=5
221 )
222
223 return keyword_filtered
策略四:完整的多 Agent 協調系統
整合所有策略的生產級系統。
系統架構
完整的選擇性 Context 傳遞系統:
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ Orchestrator │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 1. 任務解析與規劃 │ │
│ │ 2. Agent 調度 │ │
│ │ 3. 結果整合 │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Context Manager │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Dependency │ │ Context │ │ Relevance │ │ │
│ │ │ Graph │ │ Extractor │ │ Filter │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Output │ │ Context │ │ Token │ │ │
│ │ │ Store │ │ Builder │ │ Counter │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌───────────────┼───────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Agent A │ │ Agent B │ │ Agent C │ │
│ │ (結構化輸出) │ │ (結構化輸出) │ │ (結構化輸出) │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
完整實作
1import anthropic
2import json
3from dataclasses import dataclass, field
4from typing import Optional, Callable
5from enum import Enum
6import time
7
8client = anthropic.Anthropic()
9
10@dataclass
11class AgentConfig:
12 """Agent 配置"""
13 name: str
14 role: str
15 system_prompt: str
16 output_class: type = AgentOutput
17 model: str = "claude-sonnet-4-20250514"
18 max_output_tokens: int = 4096
19
20@dataclass
21class TaskResult:
22 """任務執行結果"""
23 task_id: str
24 agent_name: str
25 output: AgentOutput
26 context_tokens_used: int
27 output_tokens: int
28 execution_time_ms: float
29 success: bool
30 error: Optional[str] = None
31
32class SelectiveContextOrchestrator:
33 """
34 選擇性 Context 傳遞的 Multi-Agent Orchestrator
35
36 核心功能:
37 1. 管理 Agent 依賴關係
38 2. 建構最小化 Context
39 3. 協調 Agent 執行
40 4. 追蹤 Token 使用
41 """
42
43 def __init__(
44 self,
45 dependency_graph: dict[str, AgentContextSpec],
46 enable_relevance_filter: bool = True,
47 enable_smart_extraction: bool = True
48 ):
49 self.dependency_graph = dependency_graph
50
51 # 核心組件
52 self.context_builder = ContextBuilder(dependency_graph)
53 self.extractor = ContextExtractor(use_llm_extraction=enable_smart_extraction)
54 self.relevance_filter = SmartContextFilter(use_llm_filter=enable_relevance_filter)
55
56 # Agent 註冊表
57 self.agents: dict[str, AgentConfig] = {}
58
59 # 執行記錄
60 self._execution_history: list[TaskResult] = []
61 self._stats = {
62 "total_context_tokens": 0,
63 "total_output_tokens": 0,
64 "context_tokens_saved": 0,
65 "agents_executed": 0
66 }
67
68 def register_agent(self, config: AgentConfig):
69 """註冊 Agent"""
70 self.agents[config.name] = config
71
72 def _create_agent_executor(self, config: AgentConfig) -> StructuredOutputAgent:
73 """創建 Agent 執行器"""
74 return StructuredOutputAgent(
75 agent_name=config.name,
76 system_prompt=config.system_prompt,
77 output_class=config.output_class,
78 model=config.model
79 )
80
81 def _estimate_tokens(self, text: str) -> int:
82 """估算 token 數"""
83 return len(text) // 3 # 粗略估算
84
85 def _build_optimized_context(
86 self,
87 target_agent: str,
88 original_task: str
89 ) -> tuple[str, int, int]:
90 """
91 建構優化的 Context
92
93 Returns:
94 (context, actual_tokens, potential_tokens_without_optimization)
95 """
96 spec = self.dependency_graph.get(target_agent)
97 agent_config = self.agents.get(target_agent)
98
99 if not spec or not agent_config:
100 return original_task, self._estimate_tokens(original_task), self._estimate_tokens(original_task)
101
102 # 收集所有可能的 Context
103 all_context_parts = []
104 potential_tokens = 0
105
106 # 原始任務
107 if spec.requires_original_task:
108 all_context_parts.append(f"[原始任務]\n{original_task}")
109
110 # 從依賴中提取
111 for dep in spec.dependencies:
112 if dep.source_agent not in self.context_builder._output_store:
113 continue
114
115 source_output = self.context_builder._output_store[dep.source_agent]
116
117 # 計算未優化情況下的 tokens(完整輸出)
118 full_context = source_output.to_full_context()
119 potential_tokens += self._estimate_tokens(full_context)
120
121 # 提取優化後的 Context
122 request = ExtractionRequest(
123 source_output=source_output,
124 target_agent=target_agent,
125 dependency=dep
126 )
127 extracted = self.extractor.extract(request)
128 all_context_parts.append(extracted)
129
130 # 相關性過濾
131 filtered_parts = self.relevance_filter.filter(
132 all_context_parts,
133 original_task,
134 target_agent,
135 agent_config.role
136 )
137
138 # 組合最終 Context
139 final_context = "\n\n---\n\n".join(filtered_parts)
140
141 # 確保不超過限制
142 max_tokens = spec.max_total_context
143 actual_tokens = self._estimate_tokens(final_context)
144
145 if actual_tokens > max_tokens:
146 # 截斷
147 final_context = final_context[:max_tokens * 3] + "\n...[Context 已截斷]"
148 actual_tokens = max_tokens
149
150 return final_context, actual_tokens, potential_tokens
151
152 def execute_agent(
153 self,
154 agent_name: str,
155 original_task: str,
156 task_id: str = ""
157 ) -> TaskResult:
158 """
159 執行單個 Agent
160
161 自動建構最小化 Context 並執行
162 """
163 start_time = time.time()
164
165 agent_config = self.agents.get(agent_name)
166 if not agent_config:
167 return TaskResult(
168 task_id=task_id,
169 agent_name=agent_name,
170 output=AgentOutput(agent_name=agent_name, task_id=task_id, summary=""),
171 context_tokens_used=0,
172 output_tokens=0,
173 execution_time_ms=0,
174 success=False,
175 error=f"Agent {agent_name} 未註冊"
176 )
177
178 # 建構優化 Context
179 context, actual_tokens, potential_tokens = self._build_optimized_context(
180 agent_name, original_task
181 )
182
183 # 執行 Agent
184 executor = self._create_agent_executor(agent_config)
185
186 try:
187 output = executor.execute(original_task, context)
188 output.task_id = task_id
189
190 # 儲存輸出供下游使用
191 self.context_builder.store_output(output)
192
193 execution_time = (time.time() - start_time) * 1000
194 output_tokens = output.metadata.get("output_tokens", 0)
195
196 # 更新統計
197 self._stats["total_context_tokens"] += actual_tokens
198 self._stats["total_output_tokens"] += output_tokens
199 self._stats["context_tokens_saved"] += (potential_tokens - actual_tokens)
200 self._stats["agents_executed"] += 1
201
202 result = TaskResult(
203 task_id=task_id,
204 agent_name=agent_name,
205 output=output,
206 context_tokens_used=actual_tokens,
207 output_tokens=output_tokens,
208 execution_time_ms=execution_time,
209 success=True
210 )
211
212 except Exception as e:
213 result = TaskResult(
214 task_id=task_id,
215 agent_name=agent_name,
216 output=AgentOutput(agent_name=agent_name, task_id=task_id, summary=""),
217 context_tokens_used=actual_tokens,
218 output_tokens=0,
219 execution_time_ms=(time.time() - start_time) * 1000,
220 success=False,
221 error=str(e)
222 )
223
224 self._execution_history.append(result)
225 return result
226
227 def execute_pipeline(
228 self,
229 original_task: str,
230 agent_sequence: list[str],
231 task_id: str = ""
232 ) -> list[TaskResult]:
233 """
234 執行 Agent 管線
235
236 按順序執行多個 Agent,自動傳遞 Context
237 """
238 results = []
239
240 for i, agent_name in enumerate(agent_sequence):
241 print(f"\n{'='*50}")
242 print(f"執行 Agent {i+1}/{len(agent_sequence)}: {agent_name}")
243 print(f"{'='*50}")
244
245 result = self.execute_agent(
246 agent_name,
247 original_task,
248 task_id=f"{task_id}_{i}" if task_id else str(i)
249 )
250
251 results.append(result)
252
253 if result.success:
254 print(f"✅ 成功")
255 print(f" Context tokens: {result.context_tokens_used}")
256 print(f" Output tokens: {result.output_tokens}")
257 print(f" 執行時間: {result.execution_time_ms:.0f}ms")
258 else:
259 print(f"❌ 失敗: {result.error}")
260
261 return results
262
263 def get_stats(self) -> dict:
264 """取得統計資訊"""
265 total_potential = self._stats["total_context_tokens"] + self._stats["context_tokens_saved"]
266 savings_pct = (
267 self._stats["context_tokens_saved"] / total_potential * 100
268 if total_potential > 0 else 0
269 )
270
271 return {
272 **self._stats,
273 "total_tokens": self._stats["total_context_tokens"] + self._stats["total_output_tokens"],
274 "context_savings_pct": f"{savings_pct:.1f}%",
275 "execution_count": len(self._execution_history)
276 }
277
278 def get_execution_summary(self) -> str:
279 """取得執行摘要"""
280 lines = ["執行摘要:", ""]
281
282 for result in self._execution_history:
283 status = "✅" if result.success else "❌"
284 lines.append(
285 f"{status} {result.agent_name}: "
286 f"Context {result.context_tokens_used} tok, "
287 f"Output {result.output_tokens} tok, "
288 f"{result.execution_time_ms:.0f}ms"
289 )
290
291 lines.append("")
292 stats = self.get_stats()
293 lines.append(f"總 Context tokens: {stats['total_context_tokens']}")
294 lines.append(f"總 Output tokens: {stats['total_output_tokens']}")
295 lines.append(f"Context 節省: {stats['context_savings_pct']}")
296
297 return "\n".join(lines)
298
299
300# 使用範例
301def create_development_pipeline() -> SelectiveContextOrchestrator:
302 """創建軟體開發管線"""
303
304 orchestrator = SelectiveContextOrchestrator(
305 dependency_graph=CONTEXT_DEPENDENCY_GRAPH,
306 enable_relevance_filter=True,
307 enable_smart_extraction=True
308 )
309
310 # 註冊 Agents
311 orchestrator.register_agent(AgentConfig(
312 name="requirements_analyst",
313 role="需求分析師,負責理解和整理使用者需求",
314 system_prompt="""你是專業的需求分析師。
315分析使用者需求,產出結構化的需求文件。
316重點關注:功能需求、非功能需求、限制條件、使用者故事。""",
317 output_class=RequirementsAnalystOutput
318 ))
319
320 orchestrator.register_agent(AgentConfig(
321 name="architect",
322 role="系統架構師,負責設計系統架構和技術選型",
323 system_prompt="""你是資深系統架構師。
324根據需求設計系統架構,包括技術選型、API 設計、資料模型。
325考慮可擴展性、可維護性、效能需求。""",
326 output_class=ArchitectOutput
327 ))
328
329 orchestrator.register_agent(AgentConfig(
330 name="developer",
331 role="軟體開發者,負責實作程式碼",
332 system_prompt="""你是資深軟體開發者。
333根據架構設計實作乾淨、可維護的程式碼。
334遵循最佳實踐和程式碼規範。""",
335 output_class=DeveloperOutput
336 ))
337
338 orchestrator.register_agent(AgentConfig(
339 name="code_reviewer",
340 role="程式碼審查者,負責審查程式碼品質",
341 system_prompt="""你是程式碼審查專家。
342審查程式碼的品質、安全性、效能和可維護性。
343提供具體的改進建議。""",
344 output_class=CodeReviewerOutput,
345 model="claude-3-5-haiku-20241022" # 審查用較輕量模型
346 ))
347
348 orchestrator.register_agent(AgentConfig(
349 name="doc_writer",
350 role="技術文件撰寫者,負責撰寫文件",
351 system_prompt="""你是技術文件撰寫專家。
352撰寫清晰、完整的技術文件。
353包括 API 文件、使用說明、架構說明。""",
354 model="claude-3-5-haiku-20241022"
355 ))
356
357 return orchestrator
358
359
360if __name__ == "__main__":
361 # 創建管線
362 orchestrator = create_development_pipeline()
363
364 # 執行任務
365 task = """
366 開發一個簡單的待辦事項 API,需要:
367 1. CRUD 操作(建立、讀取、更新、刪除待辦事項)
368 2. 使用者認證(JWT)
369 3. 待辦事項可以設定優先級和截止日期
370 4. 支援分頁查詢
371 """
372
373 results = orchestrator.execute_pipeline(
374 original_task=task,
375 agent_sequence=[
376 "requirements_analyst",
377 "architect",
378 "developer",
379 "code_reviewer",
380 "doc_writer"
381 ],
382 task_id="todo_api"
383 )
384
385 print("\n" + "="*60)
386 print(orchestrator.get_execution_summary())
進階:動態依賴調整
根據任務類型動態調整依賴關係。
1from typing import Callable
2
3class DynamicDependencyManager:
4 """
5 動態依賴管理器
6
7 根據任務特性動態調整 Agent 間的依賴關係
8 """
9
10 def __init__(self, base_graph: dict[str, AgentContextSpec]):
11 self.base_graph = base_graph
12 self.modifiers: list[Callable[[str, dict], dict]] = []
13
14 def add_modifier(self, modifier: Callable[[str, dict], dict]):
15 """添加依賴修改器"""
16 self.modifiers.append(modifier)
17
18 def get_graph_for_task(self, task: str) -> dict[str, AgentContextSpec]:
19 """根據任務取得調整後的依賴圖"""
20 import copy
21 graph = copy.deepcopy(self.base_graph)
22
23 for modifier in self.modifiers:
24 graph = modifier(task, graph)
25
26 return graph
27
28
29def security_focused_modifier(task: str, graph: dict) -> dict:
30 """安全敏感任務的修改器"""
31 security_keywords = ["安全", "認證", "加密", "權限", "security", "auth"]
32
33 if any(kw in task.lower() for kw in security_keywords):
34 # 增加 code_reviewer 對 architect 的依賴
35 if "code_reviewer" in graph:
36 graph["code_reviewer"].dependencies.append(
37 ContextDependency(
38 source_agent="architect",
39 context_type=ContextType.STRUCTURED_DATA,
40 required_fields=["security_requirements"],
41 max_tokens=1000,
42 priority=2
43 )
44 )
45 # 增加最大 context 限制
46 if "developer" in graph:
47 graph["developer"].max_total_context = 15000
48
49 return graph
50
51
52def simple_task_modifier(task: str, graph: dict) -> dict:
53 """簡單任務的修改器"""
54 simple_indicators = ["簡單", "基本", "simple", "basic", "小型"]
55
56 if any(ind in task.lower() for ind in simple_indicators):
57 # 簡化依賴
58 for spec in graph.values():
59 spec.max_total_context = min(spec.max_total_context, 4000)
60 # 只保留 SUMMARY 類型的依賴
61 spec.dependencies = [
62 dep for dep in spec.dependencies
63 if dep.context_type in [ContextType.SUMMARY, ContextType.KEY_FINDINGS]
64 ]
65
66 return graph
67
68
69# 使用範例
70def create_adaptive_orchestrator(task: str) -> SelectiveContextOrchestrator:
71 """創建自適應的 Orchestrator"""
72
73 manager = DynamicDependencyManager(CONTEXT_DEPENDENCY_GRAPH)
74 manager.add_modifier(security_focused_modifier)
75 manager.add_modifier(simple_task_modifier)
76
77 adapted_graph = manager.get_graph_for_task(task)
78
79 return SelectiveContextOrchestrator(
80 dependency_graph=adapted_graph,
81 enable_relevance_filter=True
82 )
效能比較與分析
選擇性 Context 傳遞效益分析:
┌─────────────────────────────────────────────────────────────────────┐
│ Token 使用量對比 │
├──────────────────┬──────────────┬──────────────┬───────────────────┤
│ 場景 │ 完整傳遞 │ 選擇性傳遞 │ 節省 │
├──────────────────┼──────────────┼──────────────┼───────────────────┤
│ 5 Agent 管線 │ 150,000 tok │ 25,000 tok │ 83% │
│ 10 Agent 管線 │ 450,000 tok │ 55,000 tok │ 88% │
│ 複雜專案開發 │ 800,000 tok │ 95,000 tok │ 88% │
│ 簡單任務 │ 30,000 tok │ 8,000 tok │ 73% │
└──────────────────┴──────────────┴──────────────┴───────────────────┘
成本節省計算(假設 Sonnet $3/1M input tokens):
場景:每日 100 個 5-Agent 管線任務
完整傳遞:100 × 150,000 × $3 / 1M = $45/天 = $1,350/月
選擇性傳遞:100 × 25,000 × $3 / 1M = $7.5/天 = $225/月
月度節省:$1,125(83%)
最佳實踐清單
選擇性 Context 傳遞 Checklist:
依賴設計
□ 是否明確定義了每個 Agent 的依賴關係?
□ 是否為每個依賴指定了 Context 類型?
□ 是否設定了合理的 max_tokens 限制?
輸出格式
□ Agent 輸出是否結構化?
□ 是否區分了 summary 和 detailed_output?
□ 是否定義了 structured_data 的欄位?
提取策略
□ 是否只提取下游 Agent 真正需要的資訊?
□ 是否使用了相關性過濾?
□ 是否處理了 Context 超長的情況?
效能監控
□ 是否追蹤每個 Agent 的 Context tokens?
□ 是否計算節省的 tokens 數量?
□ 是否有 Token 使用警報?
品質保障
□ 過濾後的 Context 是否足夠支援任務?
□ 是否有機制在需要時請求更多 Context?
□ 是否驗證了 Agent 輸出品質?
總結
選擇性 Context 傳遞是多 Agent 系統中最具影響力的優化策略,可以節省 70-95% 的 Context tokens。本文介紹的方案涵蓋:
| 策略 | 節省效果 | 實作複雜度 | 適用場景 |
|---|---|---|---|
| 結構化輸出 | 中 | 低 | 所有場景 |
| Context 提取 | 高 | 中 | 明確依賴 |
| 相關性過濾 | 高 | 中高 | 動態任務 |
| 完整系統 | 最高 | 高 | 生產環境 |
關鍵原則:
- 明確依賴:每個 Agent 只接收它真正需要的資訊
- 結構化輸出:便於下游精確提取所需欄位
- 分層提取:summary → key_findings → structured_data → full_output
- 持續監控:追蹤 Token 使用,驗證節省效果
透過選擇性 Context 傳遞,你可以建構高效、低成本的多 Agent 協作系統,同時保持輸出品質。
