"""루트 에이전트 — 개입 포켓 턴 파이프라인 조립 (팩토리는 조립만 담당). pocket_session (SequentialAgent) — 유저 메시지 1건 = 1회 실행 ├── pocket_context_loader ← BaseAgent: 카드 브리프/결 적재 (스포일러 필터) ├── input_guard ← BaseAgent: 정체직격/약점/메타 감지 → 지시 생성 ├── carmilla ← LlmAgent: 캐릭터 응답 └── director ← LlmAgent: 축/비트/수렴 판정 (도구로 state 기록) 주: CLAUDE.md의 turn_loop(LoopAgent) 기준 구조는 씬 전체를 1회 호출로 도는 자율 루프용이다. 사람이 턴마다 입력하는 채팅은 Runner의 표준 패턴대로 "유저 메시지마다 파이프라인 1회 실행"이 ADK 공식 흐름이며, 턴 상한·수렴 재검증은 services/pocket.py의 결정적 코드가 담당한다. director가 마지막이므로 finish_pocket의 escalate가 삼킬 후속 에이전트는 없다. `adk web /path/to/sorac` 실행 시 이 모듈의 root_agent가 노출된다 (앱 이름: engine). """ from __future__ import annotations from pathlib import Path from google.adk.agents import SequentialAgent from engine.agents.input_guard import create_input_guard from engine.agents.pocket_context_loader import create_pocket_context_loader from engine.repositories.content import ContentRepository from engine.sub_agents.character.agent import create_character from engine.sub_agents.director.agent import create_director _CONTENT_DIR = Path(__file__).resolve().parent.parent / "content" def create_pocket_pipeline(repo: ContentRepository | None = None, character_model=None, director_model=None) -> SequentialAgent: # ADK 2.3이 SequentialAgent에 deprecation(→ google.adk.workflow)을 띄우지만, # Workflow는 그래프 기반 신 API라 CLAUDE.md의 에이전트 규칙과 함께 별도 검토 후 # 마이그레이션한다 (follow-up). 현행 공식 릴리스에서 SequentialAgent는 정상 동작. repo = repo or ContentRepository(_CONTENT_DIR) return SequentialAgent( name="pocket_session", sub_agents=[ create_pocket_context_loader(repo), create_input_guard(repo), create_character(character_model), create_director(director_model), ], ) root_agent = create_pocket_pipeline()