Files
connectai/docs/AgentEngine_Architecture.md
T

315 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AgentEngine Architecture Document
> **Version:** v2.61.0 | **Last Updated:** 2026-05-04 | **Author:** ConnectAI Lab
---
## 1. Overview (설계 개요)
`AgentEngine`은 ConnectAI(Astra) 확장의 핵심 실행 엔진으로, **Producer-Consumer 패턴** 기반의 멀티 에이전트 오케스트레이션을 담당합니다. Planner → Researcher → Writer의 3단계 파이프라인을 통해 사용자의 자연어 요청을 전략 수립, 정보 수집, 최종 보고서 작성이라는 전문화된 단계로 분할 처리합니다.
### 핵심 설계 원칙
| 원칙 | 구현 |
|---|---|
| **의존성 주입 (DI)** | `IAgent` 인터페이스를 통해 에이전트를 런타임에 교체 가능 |
| **명시적 동시성 제어** | `LockManager`(Mutex) + `ActionQueueManager`(Concurrency Limit) |
| **복원력 우선 (Resilience-First)** | `ErrorRecoveryMatrix`를 통한 오류 자동 분류 및 복구 |
| **투명한 상태 관리** | `MissionState`를 통한 감사 이력(Audit Trail) 자동 기록 |
---
## 2. Architecture Diagram (아키텍처 다이어그램)
```
┌──────────────────────────────────────────────────────────────┐
│ AgentWorkflowManager │
│ (Public Entry Point) │
└──────────────────────────┬───────────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐
│ AgentEngine │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 1. LockManager.acquire() ← Mutex (동일 미션 중복 방지) │ │
│ │ 2. ActionQueue.enqueue() ← Concurrency Limit (≤3) │ │
│ │ 3. resilientExecute() ← Error Recovery Matrix │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────────┐ ┌────────────┐ │
│ │ Planner │──▶│ Researcher │──▶│ Writer │ │
│ │ (IAgent) │ │ (IAgent) │ │ (IAgent) │ │
│ └──────────┘ └──────┬───────┘ └────────────┘ │
│ │ │
│ ┌──────┴───────┐ │
│ │ WriterPrep │ ← Promise.all() 병렬 실행 │
│ │ (Parallel) │ │
│ └──────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ MissionState (Audit Trail) │ │
│ │ idle → planner → researcher → writer → completed │ │
│ │ [toStructuredLog()] → JSON 출력 → 모니터링 대시보드 │ │
│ └─────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
```
---
## 3. Lock Management (락 관리)
### 3.1 LockManager (Mutex)
**파일:** `src/core/lock.ts`
**설계 의도:** 동일한 `missionId`에 대한 중복 실행을 방지합니다. 예를 들어, 사용자가 동일한 질문을 빠르게 두 번 전송한 경우, 두 번째 요청은 첫 번째 요청이 완료될 때까지 대기합니다.
**동작 원리:**
```
Mission A (id: "abc") 시작 → Lock 획득 ✅
Mission B (id: "abc") 시작 → Lock 대기 ⏳ (Mission A 완료까지)
Mission A 완료 → Lock 해제 → Mission B Lock 획득 ✅
```
**핵심 보장:**
- 동일 미션 ID의 순차 실행 보장 (Race Condition 방지)
- `finally` 블록에서 반드시 `release()` 호출 → 데드락 불가
### 3.2 ActionQueueManager (동시성 제어)
**파일:** `src/core/queue.ts`
**설계 의도:** 시스템 전체에서 동시에 실행되는 에이전트 작업 수를 제한하여 리소스 고갈을 방지합니다.
**핵심 파라미터:**
| 파라미터 | 기본값 | 설명 |
|---|---|---|
| `concurrencyLimit` | 3 | 동시 실행 가능한 최대 작업 수 |
| `activeCount` | - | 현재 실행 중인 작업 수 (동적) |
| micro-delay | 10ms | 작업 간 시스템 호흡 시간 |
**Mutex vs Queue의 역할 분리:**
| 구분 | LockManager | ActionQueueManager |
|---|---|---|
| 범위 | 미션 단위 (단일 ID) | 시스템 전체 |
| 목적 | 중복 실행 방지 | 리소스 포화 방지 |
| 방식 | 독점 잠금 (Exclusive) | 동시성 제한 (Bounded) |
---
## 4. Error Recovery Matrix (오류 복구 매트릭스)
### 4.1 오류 분류 체계
`ErrorClassifier`는 에러 객체의 `name``message`를 정규식 패턴 매칭하여 세 범주로 자동 분류합니다.
```
┌──────────────┬──────────┬──────────────┬─────────────────────────────────┐
│ Error Type │ Retries │ Backoff │ Action │
├──────────────┼──────────┼──────────────┼─────────────────────────────────┤
│ TRANSIENT │ 3 │ Exponential │ 자동 재시도 (1s → 2s → 4s) │
│ │ │ (1000ms) │ │
├──────────────┼──────────┼──────────────┼─────────────────────────────────┤
│ PERMANENT │ 0 │ N/A │ 즉시 중단 + 사용자 안내 메시지 │
├──────────────┼──────────┼──────────────┼─────────────────────────────────┤
│ ABORT │ 0 │ N/A │ Graceful Exit (조용한 종료) │
└──────────────┴──────────┴──────────────┴─────────────────────────────────┘
```
### 4.2 분류 패턴 목록
**Transient (재시도 가능):**
- `ECONNREFUSED`, `ECONNRESET`, `ETIMEDOUT`, `ENOTFOUND`
- `timeout`, `network`, `fetch failed`, `Failed to fetch`
- HTTP `502`, `503`, `429`
- `socket hang up`
**Permanent (즉시 중단):**
- HTTP `401`, `403`, `404`
- `유효한 응답을 받지 못했습니다` (내부 검증 실패)
- `Ollama URL이 설정되지 않았습니다` (설정 누락)
- `invalid model`, `model not found` (모델 문제)
**분류 불가 → Permanent (보수적 처리):**
- 알려지지 않은 오류는 안전하게 Permanent로 분류하여 무한 재시도를 방지
### 4.3 resilientExecute 실행 흐름
```
resilientExecute(agent, ...)
├─ attempt 0: agent.execute()
│ ├─ 성공 → return result
│ └─ 실패 → ErrorClassifier.classify(error)
│ ├─ ABORT → throw (즉시 전파)
│ ├─ PERMANENT → throw (사용자 메시지 첨부)
│ └─ TRANSIENT → continue
├─ attempt 1: wait 1000ms → agent.execute()
│ └─ (동일 분기)
├─ attempt 2: wait 2000ms → agent.execute()
│ └─ (동일 분기)
└─ attempt 3: wait 4000ms → agent.execute()
└─ 실패 시 → "재시도 소진" 에러 throw
```
---
## 5. MissionState & Monitoring (상태 관리 및 모니터링)
### 5.1 MissionState 설계 의도
엔진 내부의 상태(`this.stage`)를 독립 객체로 분리하여:
1. **감사 이력(Audit Trail)** 자동 기록: 모든 상태 전환이 타임스탬프, 소요 시간과 함께 기록됨
2. **외부 노출**: `getMissionState()`를 통해 외부 모니터링 시스템이 실시간 상태를 읽을 수 있음
3. **디버깅 지원**: 에러 발생 시 `summarizeAudit()`로 전체 전환 이력을 한 줄로 덤프
### 5.2 toStructuredLog() 출력 포맷
```json
{
"missionId": "mission_1714832400000",
"status": "completed",
"startTime": "2026-05-04T02:40:00.000Z",
"totalElapsedMs": 12450,
"transitionCount": 4,
"transitions": [
{
"from": "idle",
"to": "planner",
"durationMs": 0,
"message": "전략 수립 중...",
"ts": "2026-05-04T02:40:00.000Z"
},
{
"from": "planner",
"to": "researcher",
"durationMs": 3200,
"message": "핵심 정보 수집 및 분석 중...",
"ts": "2026-05-04T02:40:03.200Z"
}
]
}
```
이 포맷은 ELK Stack, Loki, Datadog 등의 외부 시스템에 파싱 없이 직접 인제스트할 수 있습니다.
### 5.3 Mission Control Dashboard
**파일:** `assets/mission_control.html`
`toStructuredLog()`의 JSON 출력을 브라우저에서 시각화하는 독립형 대시보드입니다.
- 에이전트 타임라인 시각화
- 단계별 지연 시간(Latency) 표시
- 미션 상태 및 효율성 분석 지표 제공
---
## 6. IAgent Interface (에이전트 인터페이스)
### 6.1 기본 시그니처
```typescript
interface IAgent {
execute(
input: string,
context?: string,
signal?: AbortSignal,
options?: AgentExecuteOptions
): Promise<string>;
}
```
### 6.2 AgentExecuteOptions (확장 옵션)
| 필드 | 타입 | 용도 |
|---|---|---|
| `context` | `string` | 추가 컨텍스트 |
| `signal` | `AbortSignal` | 중단 시그널 |
| `config` | `Record<string, unknown>` | 에이전트별 커스텀 설정 (temperature, maxTokens 등) |
| `priorResults` | `Record<string, string>` | 이전 단계 중간 결과물 (병렬 파이프라인용) |
**확장 전략:** 새로운 에이전트가 추가될 때 `options.config`에 자유롭게 설정을 넣을 수 있으므로, `IAgent` 시그니처를 변경할 필요가 없습니다.
---
## 7. Test & Benchmark Coverage (테스트 커버리지)
**파일:** `tests/agentEngine.test.ts` | **총 41개 테스트**
| Suite | Tests | Description |
|---|---|---|
| ErrorClassifier | 20 | Transient(10), Permanent(7), Abort(2), Unknown(1) 분류 정확성 |
| Recovery Matrix | 3 | 매트릭스 규칙 정합성 |
| MissionState | 4 | 상태 전환, Audit Trail, JSON 포맷 |
| Engine Integration | 6 | 정상/재시도/즉시중단/취소/재시도소진/상태정리 |
| Performance | 3 | 정상 Latency, 재시도 오버헤드, 즉시 중단 시간 |
| Concurrency & Stress | 4 | 병렬 실행, 혼합 오류, 큐 포화, Race Condition |
### 벤치마크 기준치
| Metric | Measured | Threshold |
|---|---|---|
| Normal Mission Avg Latency | 165ms | < 1,000ms |
| Retry Overhead (2 retries) | 3,012ms | 2,50010,000ms |
| Permanent Fail Time | 11ms | < 500ms |
| 5 Concurrent Missions | 23ms | < 30,000ms |
| Queue Saturation (10 tasks) | 44ms | all complete |
### 배포 게이트
```json
"vscode:prepublish": "npm run test && npm run compile"
```
모든 41개 테스트가 통과해야만 `.vsix` 패키징이 진행됩니다.
---
## 8. File Map (파일 맵)
```
src/
├── lib/
│ └── engine.ts ← AgentEngine, MissionState, ErrorClassifier,
│ ErrorRecoveryMatrix, IAgent, AgentExecuteOptions
├── core/
│ ├── queue.ts ← ActionQueueManager (Concurrency Limit)
│ └── lock.ts ← LockManager (Mutex)
├── agents/
│ ├── factory.ts ← PlannerAgent, ResearcherAgent, WriterAgent (BaseAgent)
│ └── AgentWorkflowManager.ts ← Public API (runStrictWorkflow)
└── utils.ts ← logInfo, logError, logWarn (→ VS Code Output Channel "Astra")
tests/
└── agentEngine.test.ts ← 41 integration tests + benchmarks
assets/
└── mission_control.html ← Mission Control Dashboard (standalone)
```
---
## 9. Maintenance Notes (유지보수 참고)
### 새 에이전트 추가 시
1. `IAgent`를 구현하는 새 클래스를 `factory.ts`에 추가
2. `AgentEngine` 생성자에 주입 (DI)
3. `PipelineStage` 타입에 새 단계 추가
4. `AgentWorkflowManager.mapStageToUI()`에 UI 매핑 추가
### 새 오류 패턴 추가 시
1. `ErrorClassifier.TRANSIENT_PATTERNS` 또는 `PERMANENT_PATTERNS`에 정규식 추가
2. `tests/agentEngine.test.ts`의 해당 describe 블록에 테스트 케이스 추가
3. `npm run test:engine`으로 검증
### 동시성 제한 변경 시
`src/core/queue.ts``new ActionQueueManager(N)` 생성자 인자를 조정합니다.
기본값은 3이며, 리소스 여유에 따라 조정 가능합니다.