Pattern 09. Advanced Patterns — Dual Judge, Complex Topology, Deployment
Learning Objectives
After completing this tutorial, you will be able to:
- Design a dual Judge pattern with two independent Judge cycles
- Prevent
NO_ENTRY_NODE,MULTIPLE_ENTRY_NODES, andFINALIZE_UNREACHABLEerrors in complex graph topologies - Design graphs so that cycles do not intersect
- Understand and apply pattern ID naming conventions
- Deploy completed patterns to a workspace and verify them with
euleragent pattern list
Prerequisites
04_judge_and_loop.mdcompleted (Judge basics)07_multi_route.mdcompleted (multi-routing)- Experience writing complex YAML
euleragent pattern list
euleragent agent list
1. When Dual Judge Patterns Are Needed
A single Judge evaluates from one perspective. Sometimes evaluation from two independent perspectives is required.
Blog + SEO: Content quality (readability, informativeness) and SEO optimization (keywords, metadata) require different areas of expertise.
Code + Security: Functional correctness and security vulnerabilities must be evaluated independently. Even if the functionality is perfect, security vulnerabilities are unacceptable.
Documentation + Legal Review: Cases where a separate legal compliance review is needed after technical accuracy review.
Design Principle: The two Judges must not cross each other's loops. Design them as independent chains.
2. Dual Judge Architecture
Serial Dual Judge (Sequential)
The second Judge independently evaluates only after the first Judge passes.
[draft] → [content_judge] → content_revise → content_judge (루프)
│ (finalize 선택 시)
▼
[technical_judge] → tech_revise → technical_judge (루프)
│ (finalize 선택 시)
▼
[FINALIZE]
Key characteristics of this design:
- The content_judge loop and technical_judge loop are completely separate
- Technical evaluation only proceeds when content is sufficiently good
- Each Judge has its own independent max_iterations
3. Pattern Design: Blog + SEO Dual Evaluation
Node Flow Diagram
┌─────────────────────────────────────────────────────────────────┐
│ writing.dual_judge 패턴 흐름도 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ [draft] │
│ │ 블로그 초안 작성 (llm/execute) │
│ │ when: true │
│ ▼ │
│ ─── STAGE 1: 콘텐츠 평가 사이클 ───────────────────────────── │
│ │
│ [content_judge] ── when: judge.route == content_ok ────────────┐
│ │ 콘텐츠 품질 평가 (judge/evaluator_v1) │
│ │ routes: [content_ok, content_revise] │
│ │ when: judge.route == content_revise │
│ ▼ │
│ [content_revise] │
│ │ 콘텐츠 개선 (llm/execute) │
│ └──────────────────────────► [content_judge] (최대 3회) │
│ │
│ ─── STAGE 2: SEO 평가 사이클 ───────────────────────────────── │
│ │
│ [seo_optimize] ◄────────────────────────────────────────────-──┘
│ │ SEO 최적화 (llm/execute) │
│ │ when: true │
│ ▼ │
│ [seo_judge] ── when: judge.route == seo_ok ────────────────────┐
│ │ SEO 품질 평가 (judge/evaluator_v1) │
│ │ routes: [seo_ok, seo_revise] │
│ │ when: judge.route == seo_revise │
│ ▼ │
│ [seo_revise] │
│ │ SEO 재최적화 (llm/execute) │
│ └──────────────────────────► [seo_judge] (최대 2회) │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ [FINALIZE] final_post.md 저장 │◄──┘
│ └──────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
4. Writing the YAML
Create the dual_judge_blog.yaml file.
id: writing.dual_judge
version: 1
category: writing
description: "콘텐츠 품질 + SEO 최적화 이중 Judge 블로그 작성 패턴"
defaults:
# 이중 사이클이 있으므로 충분한 max_iterations
# content_judge 사이클 최대 3회 + seo_judge 사이클 최대 2회
# defaults.max_iterations는 전체 사이클 총합에 적용됨
max_iterations: 5
max_total_tool_calls: 30
pass_threshold: 0.85
nodes:
# ── STAGE 1: 초안 작성 ──
- id: draft
kind: llm
runner:
mode: execute
exclude_tools: [web.search, web.fetch, shell.exec]
prompt:
system_append: |
당신은 기술 블로그 작가입니다.
주제에 대한 완성된 블로그 포스트 초안을 작성하세요.
요구사항:
- 길이: 1000-1500 단어
- 구성: 도입 → 본문(3섹션) → 결론
- 코드 예시 포함
- 마크다운 포맷
artifacts:
primary: draft.md
# ── STAGE 1: 콘텐츠 평가 사이클 ──
- id: content_judge
kind: judge
judge:
schema: evaluator_v1
# content 전용 route_values — seo_judge와 독립적
route_values: [content_ok, content_revise]
prompt:
system_append: |
당신은 기술 블로그 편집장입니다.
다음 기준으로 콘텐츠 품질만 평가하세요. (SEO는 나중에 별도 평가)
평가 기준:
- 기술적 정확성 (35%): 정보가 정확하고 최신인가?
- 독자 가치 (30%): 실용적 통찰과 배움이 있는가?
- 구성과 흐름 (20%): 논리적으로 연결되는가?
- 코드 품질 (15%): 예시가 실행 가능하고 명확한가?
score >= 0.85 → 'content_ok' (SEO 단계로 진행)
score < 0.85 → 'content_revise' (콘텐츠 개선 필요)
- id: content_revise
kind: llm
runner:
mode: execute
exclude_tools: [web.search, web.fetch, shell.exec]
prompt:
system_append: |
편집장의 콘텐츠 피드백을 반영하여 블로그 포스트를 개선하세요.
SEO는 아직 고려하지 마세요. 콘텐츠 품질에만 집중하세요.
artifacts:
primary: draft.md
# ── STAGE 2: SEO 최적화 + 평가 사이클 ──
- id: seo_optimize
kind: llm
runner:
mode: execute
exclude_tools: [web.search, web.fetch, shell.exec]
prompt:
system_append: |
콘텐츠 품질 평가를 통과한 포스트를 SEO 관점에서 최적화하세요.
SEO 최적화 항목:
1. 제목 태그: H1에 주요 키워드 포함 (60자 이내)
2. 메타 설명: 150-160자, 키워드 포함, 클릭 유도
3. 헤딩 구조: H1→H2→H3 계층 구조
4. 키워드 밀도: 1-2% (과다 사용 금지)
5. 내부 링크 제안: [관련 포스트: ...] 형식
6. 이미지 alt 텍스트 제안 (이미지가 있는 경우)
7. 포스트 하단에 SEO 메타데이터 섹션 추가:
```
<!-- SEO
title: ...
description: ...
keywords: ...
-->
```
artifacts:
primary: seo_draft.md
- id: seo_judge
kind: judge
judge:
schema: evaluator_v1
# seo_judge 전용 route_values — content_judge와 독립적
route_values: [seo_ok, seo_revise]
prompt:
system_append: |
당신은 SEO 전문가입니다.
콘텐츠 품질은 이미 검증됐습니다. SEO 측면만 평가하세요.
평가 기준:
- 키워드 최적화 (30%): 자연스럽게 키워드가 포함됐는가?
- 제목 최적화 (25%): 클릭률을 높이는 제목인가?
- 메타 설명 (20%): 검색 결과에서 클릭을 유도하는가?
- 구조 최적화 (25%): 헤딩 계층, 가독성이 검색 엔진 친화적인가?
score >= 0.80 → 'seo_ok' (최종 발행 준비 완료)
score < 0.80 → 'seo_revise' (SEO 재최적화 필요)
- id: seo_revise
kind: llm
runner:
mode: execute
exclude_tools: [web.search, web.fetch, shell.exec]
prompt:
system_append: |
SEO 전문가의 피드백을 반영하여 SEO를 재최적화하세요.
콘텐츠 내용은 변경하지 마세요. SEO 요소만 개선하세요.
artifacts:
primary: seo_draft.md
edges:
# Stage 1: 초안 → 콘텐츠 평가
- from: draft
to: content_judge
when: "true"
# Stage 1: 콘텐츠 사이클
- from: content_judge
to: seo_optimize # content_ok → Stage 2로 진행
when: "judge.route == content_ok"
- from: content_judge
to: content_revise # content_revise → 콘텐츠 개선
when: "judge.route == content_revise"
- from: content_revise
to: content_judge # 콘텐츠 재평가
when: "true"
# Stage 2: SEO 사이클
- from: seo_optimize
to: seo_judge
when: "true"
- from: seo_judge
to: finalize # seo_ok → 최종 완료
when: "judge.route == seo_ok"
- from: seo_judge
to: seo_revise # seo_revise → SEO 재최적화
when: "judge.route == seo_revise"
- from: seo_revise
to: seo_judge # SEO 재평가
when: "true"
finalize:
artifact: seo_draft.md
5. Validation
euleragent pattern validate dual_judge_blog.yaml
Expected output:
Validating pattern: dual_judge_blog.yaml
Stage 1 (Schema) PASS
Stage 2 (Structural) PASS
Judge node 'content_judge':
content_ok → seo_optimize ✓
content_revise → content_revise ✓
Judge node 'seo_judge':
seo_ok → finalize ✓
seo_revise → seo_revise ✓
All route_values covered ✓
Stage 3 (IR Analysis) PASS
Cycles detected:
1. content_judge → content_revise → content_judge
bounded_by: max_iterations=5 ✓
2. seo_judge → seo_revise → seo_judge
bounded_by: max_iterations=5 ✓
Cycles are independent (no intersection) ✓
Entry node: draft ✓
All paths reach finalize ✓
Validation complete: 0 errors, 0 warnings
6. Design Considerations for Complex Topologies
Consideration 1: Entry Node Uniqueness
There must be exactly one entry node (a node with no incoming edges).
# 잘못된 예 — MULTIPLE_ENTRY_NODES
nodes:
- id: draft # 수신 엣지 없음 ← 진입점 1
- id: outline # 수신 엣지 없음 ← 진입점 2
edges:
- from: draft
to: content_judge
when: "true"
# outline에서 content_judge로 가는 엣지도 있다면?
# → MULTIPLE_ENTRY_NODES
euleragent pattern validate broken_multi_entry.yaml
ERROR [MULTIPLE_ENTRY_NODES]
Nodes with no incoming edges: draft, outline
Only one entry node is allowed.
Fix: Connect one of these nodes with an incoming edge,
or merge them into a single entry node.
Consideration 2: Preventing Cycle Intersection
When two cycles share a node, complex behavior arises.
# 잘못된 예 — 사이클 교차
content_judge → content_revise → content_judge (사이클 1)
seo_judge → content_revise → seo_judge (사이클 2)
↑ content_revise가 두 사이클에 속함!
This kind of design makes max_iterations counting complex, and the context of which Judge requested the revision gets mixed up. Keep cycles independent.
Consideration 3: FINALIZE_UNREACHABLE
All paths must reach finalize.
# 컴파일 출력에서 모든 경로 확인
euleragent pattern compile dual_judge_blog.yaml | \
python3 -c "
import json, sys
d = json.load(sys.stdin)
for route, info in d.get('route_coverage', {}).items():
print(f'{route}: reaches_finalize={info[\"reaches_finalize\"]}')
"
Consideration 4: Unreachable Nodes
Nodes that are defined but not connected to any edge:
WARNING [UNREACHABLE_NODE]
Node 'orphan_node' is defined but has no incoming edges
and is not the entry node. It will never be executed.
This is a WARNING, not an ERROR. Validation passes but the node is never executed.
7. Execution Example
cp dual_judge_blog.yaml .euleragent/patterns/
euleragent pattern run writing.dual_judge my-agent \
--task "쿠버네티스 Horizontal Pod Autoscaler(HPA) 완전 가이드" \
--project default \
--stream
Streaming output:
[event] pattern.start {pattern: writing.dual_judge}
[event] node.start {node: draft}
[event] node.complete {node: draft, words: 1234}
[event] node.start {node: content_judge, iteration: 1}
[event] node.complete {node: content_judge, score: 0.79, route: content_revise}
[event] node.start {node: content_revise, iteration: 1}
[event] node.complete {node: content_revise}
[event] node.start {node: content_judge, iteration: 2}
[event] node.complete {node: content_judge, score: 0.88, route: content_ok}
[event] edge.traverse {from: content_judge, to: seo_optimize, reason: "judge.route == content_ok"}
[event] node.start {node: seo_optimize}
[event] node.complete {node: seo_optimize}
[event] node.start {node: seo_judge, iteration: 1}
[event] node.complete {node: seo_judge, score: 0.91, route: seo_ok}
[event] edge.traverse {from: seo_judge, to: finalize, reason: "judge.route == seo_ok"}
[event] pattern.complete {artifact: seo_draft.md}
Final summary:
[run:n5e8j2k6] Pattern: writing.dual_judge
✓ draft Completed (13s) — 1,234 words
✓ content_judge Completed (7s) — score: 0.79 → content_revise (iteration 1)
✓ content_revise Completed (15s) — improved
✓ content_judge Completed (6s) — score: 0.88 → content_ok (iteration 2)
✓ seo_optimize Completed (9s)
✓ seo_judge Completed (5s) — score: 0.91 → seo_ok (iteration 1)
✓ finalize Completed
Iterations: content_judge×2, seo_judge×1
Artifact: .euleragent/runs/n5e8j2k6/artifacts/seo_draft.md
8. ID Naming Conventions
Pattern IDs are recommended to follow the category.descriptor format.
Analyzing Built-in Pattern Examples
| Pattern ID | Category | Descriptor | Meaning |
|---|---|---|---|
report.evidence |
report | evidence | Evidence-based report |
code.tdd |
code | tdd | Test-driven development |
ops.triage |
ops | triage | Operations triage |
research.broad_to_narrow |
research | broad_to_narrow | Broad-to-deep research |
Recommended Categories
| Category | Description | Examples |
|---|---|---|
report |
Report writing | report.evidence, report.competitor |
code |
Code-related | code.tdd, code.pr_review, code.refactor |
ops |
Operations/Infrastructure | ops.triage, ops.incident, ops.deploy |
research |
Investigation/Analysis | research.broad_to_narrow, research.lit_review |
writing |
Documentation/Content | writing.blog, writing.newsletter |
security |
Security | security.audit, security.threat_model |
docs |
Internal documentation | docs.faq_update, docs.onboarding |
Incorrect ID Formats
id: myPattern # 카멜케이스 — 비권장
id: my_pattern # 언더스코어 — 비권장
id: MY.PATTERN # 대문자 — 비권장
id: my.complex.pattern.v2 # 3단계 이상 — 비권장
id: blog # 카테고리 없음 — 비권장
id: writing.dual_judge # 권장
id: ops.internal_triage # 권장
id: code.security_audit # 권장
9. Workspace Deployment
Deploy completed patterns to your workspace.
# 패턴 디렉토리 확인
ls .euleragent/patterns/
# 배포
cp dual_judge_blog.yaml .euleragent/patterns/dual_judge_blog.yaml
# 배포 확인
euleragent pattern list
Expected output:
Built-in Patterns
─────────────────────────────────────────────────────────
report.evidence research Evidence-based report writing
code.tdd code Test-driven development workflow
ops.triage ops Operations ticket triage
research.broad_to_narrow research Broad-to-narrow research synthesis
Workspace Patterns (.euleragent/patterns/)
─────────────────────────────────────────────────────────
blog.quality_loop writing Judge 노드로 품질 루프를 갖춘 블로그 작성 패턴
blog.web_research writing 웹 검색 + Judge 루프가 결합된 고품질 블로그 작성 패턴
code.pr_review code PR 코드 리뷰 — 승인/수정요청/거절 3-way Judge 라우팅
docs.faq_update docs 사내 FAQ 업데이트 — 에어갭, 인간 검토 게이트
my_first.pattern writing 주제를 입력받아 기술 블로그 포스트를 작성하는 단순 선형 패턴
ops.internal_triage ops 에어갭 고객 지원 트리아지
ops.policy_compliant ops 내부 정책 로드 → 분류 → 초안 → 정책 준수 검토 게이트
writing.dual_judge writing 콘텐츠 품질 + SEO 최적화 이중 Judge 블로그 작성 패턴
writing.human_review writing 초안 작성 후 인간 검토 게이트를 통과하는 문서 작성 패턴
13 patterns available (4 built-in + 9 workspace).
Deployed patterns can be referenced directly by their ID:
euleragent pattern validate writing.dual_judge
euleragent pattern show writing.dual_judge
euleragent pattern run writing.dual_judge my-agent --task "..."
10. Practice Exercise: Blog Writing + SEO Dual Evaluation Variant
Exercise: Global Deployment Pattern
A pattern that writes the original in Korean, then separately evaluates translation quality and SEO.
[draft_korean] → [translation] → [translation_quality_judge]
│ ok → [seo_optimize_english]
│ → [seo_judge] → finalize
│ revise → [retranslate] → [translation_quality_judge]
id: writing.global_publish
version: 1
category: writing
description: "한국어 원문 작성 → 영어 번역 품질 평가 → SEO 최적화 이중 Judge 패턴"
defaults:
max_iterations: 4
max_total_tool_calls: 25
nodes:
- id: draft_korean
kind: llm
runner:
mode: execute
exclude_tools: [web.search, web.fetch, shell.exec]
prompt:
system_append: |
한국어로 완성된 기술 블로그 포스트를 작성하세요.
길이: 800-1000 단어. 전문적이고 명확한 문체.
- id: translation
kind: llm
runner:
mode: execute
exclude_tools: [web.search, web.fetch, shell.exec]
prompt:
system_append: |
한국어 블로그 포스트를 영어로 번역하세요.
직역 대신 자연스러운 영어 표현을 사용하세요.
기술 용어는 영어 원어를 사용하세요.
- id: translation_quality_judge
kind: judge
judge:
schema: evaluator_v1
route_values: [translation_ok, retranslate]
prompt:
system_append: |
영어 번역의 품질을 평가하세요.
- 자연스러운 영어 표현 (40%)
- 기술적 정확성 유지 (35%)
- 문화적 적절성 (25%)
score >= 0.82 → 'translation_ok'
score < 0.82 → 'retranslate'
- id: retranslate
kind: llm
runner:
mode: execute
exclude_tools: [web.search, web.fetch, shell.exec]
prompt:
system_append: |
번역 품질 피드백을 반영하여 영어 번역을 개선하세요.
원문의 의미를 유지하면서 더 자연스러운 영어로 수정하세요.
- id: seo_optimize_english
kind: llm
runner:
mode: execute
exclude_tools: [web.search, web.fetch, shell.exec]
prompt:
system_append: |
영어 번역 포스트를 영어권 독자를 위한 SEO로 최적화하세요.
영어 SEO 키워드 전략을 적용하세요.
- id: seo_judge
kind: judge
judge:
schema: evaluator_v1
route_values: [seo_ok, seo_revise]
prompt:
system_append: |
영어권 SEO 기준으로 평가하세요.
score >= 0.78 → 'seo_ok'
score < 0.78 → 'seo_revise'
- id: seo_revise
kind: llm
runner:
mode: execute
exclude_tools: [web.search, web.fetch, shell.exec]
prompt:
system_append: SEO 피드백 반영. 콘텐츠 내용 변경 금지.
edges:
- from: draft_korean
to: translation
when: "true"
- from: translation
to: translation_quality_judge
when: "true"
- from: translation_quality_judge
to: seo_optimize_english
when: "judge.route == translation_ok"
- from: translation_quality_judge
to: retranslate
when: "judge.route == retranslate"
- from: retranslate
to: translation_quality_judge
when: "true"
- from: seo_optimize_english
to: seo_judge
when: "true"
- from: seo_judge
to: finalize
when: "judge.route == seo_ok"
- from: seo_judge
to: seo_revise
when: "judge.route == seo_revise"
- from: seo_revise
to: seo_judge
when: "true"
finalize:
artifact: final_english_post.md
Validation:
euleragent pattern validate writing_global_publish.yaml
Verify that the route_values for both Judges are fully covered.
11. Common Errors and Solutions
Error 1: Shared max_iterations Within Cycles
In a dual Judge pattern, both cycles share defaults.max_iterations. If you set max_iterations: 3, the content_judge might use 3 iterations and seo_judge might only get 1. Set a sufficiently large value.
Error 2: JUDGE_DEAD_END in Complex Topology
When a specific Judge route cannot reach finalize in a complex graph:
euleragent pattern validate complex_pattern.yaml --format json | \
python3 -c "
import json, sys
result = json.load(sys.stdin)
for err in result['stages']['ir_analysis']['errors']:
print(err['code'], err['message'])
"
Error 3: Mixed Memory Context
In a dual Judge pattern, if the stage 2 (SEO) Judge receives evaluation context from stage 1 (content), the evaluations can become mixed. Clearly restrict this in system_append with phrases like "Evaluate only SEO."
Next Steps
You have completed advanced pattern design. Now we move on to the complete reference covering all fields, error codes, and design checklists.
- Full Reference: 10_reference.md -- 19 Error Codes, All YAML Fields, 20 Checklists