Skip to content

에이전트 개요

Ongrid 는 멀티 에이전트 ReAct 시스템 입니다. 사용자는 항상 coordinator — 채팅 표면 위의 최상위 persona 와 대화합니다. 작업이 전문화된 도메인 (깊은 근본 원인 investigation, mutating-action 리뷰, 네트워크 심층 분석) 에 맞으면 coordinator 는 AgentTool 을 통해 서브 에이전트 ("worker") 로 디스패치 합니다. 각 worker 는 필터링된 도구 가방 에 대해 같은 그래프 커널을 실행하고, coordinator 가 답변에 엮어 넣는 최종 답변을 반환합니다.

이 페이지는 지도입니다. persona 별 페이지가 각 에이전트를 상세히 설명합니다.

Persona, 채팅 스레드가 아닌

persona 는 에이전트가 하는 일을 설명하는 디스크 상의 파일입니다. 표준 레이아웃 — snake_case 키를 가진 Claude Code 의 에이전트 포맷과 같은 형태:

yaml
---
name: specialist-disk
description: 文件系统 / 磁盘容量专家 — du / find / stat / inode / 挂载 / 大文件
when_to_use: |
  When the task is about disk / filesystem health:
    - Disk full / utilization climbing
    - Hunt for large files / large directories
    - inode exhaustion / mount point inspection
tools:
  - query_knowledge
  - host_find_large_files
  - host_du_summary
  - host_stat_file
  - host_bash
  - query_promql
  - get_host_load
permission_mode: read-only
max_turns: 15
---
[markdown body — this becomes the system prompt]

frontmatter 아래 body 가 SystemPrompt 입니다. 같은 name 의 persona 파일 두 개는 충돌하며 로더가 경고를 로깅합니다. 모든 필드는 persona 포맷 참조 를 참고하세요.

Persona 는 매니저 이미지의 ./agents/ 아래 (컨테이너 내부의 /app/agents/) 에 있습니다. Ongrid 는 이미지에 내장 persona 를 출하하며 마운트된 디렉터리에서 사용자 작성 persona 도 읽습니다 — 커스텀 에이전트 참고.

Coordinator vs worker

AspectCoordinatorWorker
사용자와 대화예 (채팅 표면 또는 IM 경유)절대 — worker 출력은 coordinator 로
도구 가방넓음: query_*, AgentTool, redirect stub좁음: persona tools: 화이트리스트
Persona 이름default (또는 조직별 오버라이드)specialist-*, incident-investigator, reviewer
스폰됨런타임 (채팅 세션당 하나)AgentTool 또는 review_gate 데코레이터
스폰 가능예 (worker)아니오 (설계상 worker 는 중첩 불가)
세션장수, 영속화스폰당 새 세션, 한 턴 범위

Coordinator 의 역할은 디스패치 + 분류 + 합성 입니다. 심층 분석 도구는 worker 에 있습니다. Coordinator 는 LLM 이 환각하는 것으로 알려진 도구 (host_bash, get_host_load, …) 용 RedirectStub 슬롯을 운반합니다. 그중 하나를 호출하면 모델이 AgentTool 로 재호출하도록 유도하는 redirect 메시지를 반환합니다.

AgentTool

Coordinator 의 디스패치 프리미티브. 와이어 이름 AgentTool (Claude Code 의 도구 카탈로그와 정렬되도록 PascalCase). LLM 가시 스키마:

json
{
  "type": "object",
  "properties": {
    "description":   {"type": "string"},
    "subagent_type": {"type": "string"},
    "prompt":        {"type": "string"}
  },
  "required": ["description", "subagent_type", "prompt"]
}
  • description — SPA 타일이 사용하는 1 줄 작업 요약.
  • subagent_type — persona name. coordinator 의 system prompt 에 주입된 카탈로그가 유효 값을 나열 (persona 레지스트리에서 reviewerdefault 제외).
  • prompt — 전체 작업 브리프. worker 는 coordinator 의 컨텍스트를 볼 수 없음 — 필요한 모든 세부 (incident_id, device_id, 정확한 표현) 를 싸서 보내야 합니다.

호출은 coordinator 관점에서 동기 입니다. worker 가 completed / failed / killed 에 도달할 때까지 블록. 이전 리비전에 background: true 비동기 플래그가 있었으나 약한 모델이 이를 받아 사용자에게 대기 중인 task_id 로 답하고는 후속 조치를 하지 않았습니다. 그 플래그는 오늘 사라졌습니다 (사후 분석 코멘트는 agent_tool.go 참고). 유일한 비동기 경로는 reviewer 이며 그것은 데코레이터가 구동합니다, LLM 이 아님.

Dedupe 내장

sha256(subagent_type + canonical(prompt)) 키의 120 초 LRU 가 동일한 AgentTool 호출 두 개 중 두 번째를 short-circuit. LLM 은 "이미 디스패치했습니다" 힌트와 함께 이전 결과를 봅니다. coordinator 루프 폭주를 끊습니다 (E2E eval D1 은 dedupe 없이 240 초에 122 도구 호출을 봤습니다).

System prompt 가 어떻게 합성되는가

ComposeSystemPrompt 가 LLM 이 받는 prompt 를 순서대로 조립:

  1. basePrompt — 런타임의 보편적 서두. 비어 있을 수 있음.
  2. agentProfile.SystemPrompt — persona 의 markdown body. coordinator 는 가질 수도 있고 (대부분 가짐), worker 는 항상 가짐.
  3. agentProfile.CriticalReminder<critical-reminder>...</critical-reminder> 로 래핑. 이는 persona 레벨 상수; 그래프 레이어가 또한 턴별로 <system-reminder> 로 재주입하여 긴 세션 attention drift 에서 살아남게 합니다.
  4. 각 활성 기능에 대해: [能力: <name>] 헤더 + 기능의 PromptBody.

Coordinator 는 기능 리스트 전에 추가 블록을 받습니다: 에이전트 카탈로그 (buildAgentCatalog) — descriptionwhen_to_use 의 첫 줄을 가진 "이용 가능한 specialists" 의 markdown 불릿 리스트. 카탈로그는 의도적으로 reviewer (오직 ReviewGate 데코레이터만 스폰 가능) 와 default (가상 최상위 persona — 스폰 가능한 서브 에이전트로 나열하면 coordinator 가 자신을 재귀 스폰하게 됨) 를 제외합니다.

에이전트 레지스트리

AgentRegistry 는 파싱된 persona 들을 메모리에 보관. 시작 시 한 번 로드; Reload() 는 단일 sync.RWMutex 스왑 하에서 동작하므로 진행 중인 coordinator 턴이 절반 로드된 레지스트리를 절대 관측하지 않습니다.

MethodWhen
Load(root)시작. <root>/**/*.md 재귀 워크.
Reload(root, ...)마켓플레이스 설치/제거. 원자적 스왑.
ByName(name)스폰 시점 조회. miss 시 (nil, false) 반환.
Replace(ag)사용자 에이전트 편집. 제자리 upsert — 라이브 레지스트리, 재시작 없음.
Remove(name)사용자 에이전트 삭제.

파일별 파싱 에러는 워크를 중단하지 않고 경고로 안착 (기능 레지스트리와 동일한 정책). 존재하지 않는 에이전트 루트는 에러가 아님 — 빈 레지스트리를 얻으며 시작 실패가 아님.

Reviewer 와 review gate

Reviewer 는 특별: coordinator 가 스폰할 수 없음. 모든 Class"write" 또는 "destructive" 인 도구를 가로채는 ReviewGate 데코레이터로 게이트됩니다. 데코레이터는:

  1. proposal payload (action, target, reason, blast_radius, operator) 빌드.
  2. 자체 60 초 타임아웃 (내부 도구의 15 초와 독립) 으로 reviewer worker 스폰 (내부 도구 관점에서 동기).
  3. reviewer 가 Decision: approve 를 반환하면 호출이 내부 도구로 떨어짐. 그 외는 데코레이터가 reviewer 의 reason 을 래핑한 ErrReviewRejected 를 반환.

이것이 에이전트 카탈로그가 reviewer 를 떨어트리는 이유: 오직 데코레이터만 호출 가능. 카탈로그에 두면 coordinator 가 아무것도 게이트 하지 않는 임시 "리뷰" 를 디스패치할 수 있게 됩니다.

전체 상태 머신은 Reviewer 참고.

Worker 생명주기

Runtime.SpawnWorker 상태 머신:

text
pending  → running  → completed
                   ↘ failed
                   ↘ killed     (StopWorker called while running)
  • worker 가 실행 중에도 audit + parent → worker 트리 쿼리가 해석되도록 chat_sessions 행이 사전에 생성됩니다.
  • 백그라운드 스폰은 장수 런타임 컨텍스트에서 파생되어 종료하는 HTTP 요청이 worker 를 중간에 찢지 않습니다; 동기 스폰은 호출자의 ctx 를 상속.
  • 세션 행은 모든 터미널 경로 (panic 포함) 에서 닫힙니다 (closed_at 설정) — 이것 없이는 고아 행이 누적 (테스트 환경은 수정 도착 전 161 개 도달).

Worker 는 worker 를 스폰할 수 없습니다. SpawnWorkerRuntime 에서만 노출되며 disabledForWorker 필터가 모든 worker 의 도구 가방에서 AgentTool 을 제거합니다. 하나의 coordinator, N 개의 병렬 worker, 더 깊은 중첩 없음.

다음은

  • Coordinator — 기본 persona, 세 가지 컨트롤 도구, 디스패치 vs 직접 답변 시점.
  • Incident investigator — "patient zero" 까지의 근본 원인, 18 도구 예산, F1 eval.
  • Specialists — compute / disk / network / ops / sre, 각각 무엇을 소유하는지, coordinator 가 어떻게 고르는지.
  • Reviewer — mutating 도구 위의 SOP 이중 서명 게이트.
  • 커스텀 에이전트 — 자체 persona 작성, 핫 리로드, 디버그.