에이전트 파이프라인의 가장 위험한 실패는 시끄럽지 않다. 에러 로그가 터지는 게 아니라, 그럴듯한 JSON이 조용히 흘러내려간다. 파이프라인 어딘가에서 페이지가 블록됐는데 LLM이 '친절하게' 데이터를 채워 넣고, 에이전트 하나가 침해됐는데 신뢰 체인을 타고 퍼져나가고, 프롬프트가 잘못 설계됐는데 출력이 그럴듯해 보여서 아무도 눈치채지 못한다. 이 세 가지 실패 패턴은 사실 하나의 설계 결함에서 비롯된다. 신뢰를 기본값으로 설계했다는 것.
네트워크 레이어: 에이전트 간 신뢰는 '자동' 이 아니라 '검증'이어야 한다
Dev.to에 게재된 멀티에이전트 시스템 네트워크 보안 분석은 전통적 보안 모델이 MAS에 작동하지 않는 이유를 명쾌하게 짚는다. 서버는 고정돼 있고 사용자는 인간이라는 두 가지 가정 위에 세워진 퍼리미터 보안은, 에이전트가 동적으로 연결을 맺고 클라우드 경계를 넘나드는 환경에서 무력해진다.
실질적인 위협은 외부 공격자보다 내부에서 온다. 이미 침해된 에이전트가 신뢰된 인사이더처럼 행동하면서 다운스트림 에이전트에 오염된 명령을 전달하는 trust amplification, 캡처된 유효한 메시지를 재전송해 권한을 에스컬레이션하는 replay attack, 그리고 초기 침해가 에이전트 메시를 따라 수평 전파되는 compromise propagation이 핵심 위협이다. 더 무서운 건 이 모든 과정이 사람이 볼 수 있는 지표 없이 진행된다는 점이다.
방어 아키텍처는 세 레이어로 쌓인다. 네트워크 레이어(암호화 터널, mTLS)가 도청과 스푸핑을 잡고, 에이전트 런타임 레이어(프롬프트 인스펙션, 출력 필터링, 툴콜 제한)가 인젝션과 정책 위반을 잡고, 오케스트레이션 레이어(pub/sub 감사 훅, 오토스케일링 제한)가 리플레이 어뷰즈와 리소스 소진을 잡는다. 각 레이어는 위 레이어가 놓친 것을 잡도록 설계된다.
여기서 팀 리드로서 경험상 가장 투자가 부족한 지점은 에이전트 런타임 레이어다. 인퍼런스 타임 정책 집행, 즉 모든 프롬프트와 툴콜이 실행 전에 룰셋에 대해 검사받는 구조는 단순히 나쁜 입력을 막는 것이 아니라 인시던트 대응 시 재현 가능한 감사 추적을 만드는 것이다. MCP 페이로드를 연결 메타데이터 수준이 아니라 페이로드 레벨로 로깅해야 하는 이유가 여기에 있다.
프롬프트 레이어: '더 좋은 답'이 아니라 '실패가 보이는 구조'를 설계하라
프롬프트를 요청(request)으로 보는 시각이 에이전트 파이프라인을 취약하게 만드는 근본 원인이다. Dev.to의 또 다른 분석이 제시하는 프레임이 훨씬 정확하다. 프롬프트는 제어 표면(control surface)이다.
이 관점에서 프롬프트는 세 가지 역할을 동시에 수행한다. 첫째, 모델이 어떤 종류의 답을 생성할 수 있는지를 구조적으로 제한하는 사고 도구다. 스틸맨을 요청하는 프롬프트와 크리틱을 요청하는 프롬프트는 같은 모델에서 근본적으로 다른 인지 출력을 만든다. 둘째, 외부 입력을 받는 모든 지점이 조작 가능한 공격 표면이다. 프롬프트 인젝션, RAG 포이즈닝, 평가자 캡처(evaluator capture)는 이미 문서화된 공격 클래스다. 셋째, 잘 구성된 프롬프트는 수용 가능한 출력의 하한선을 높이는 품질 필터다.
프로덕션에서 쓸 수 있는 프롬프트와 데모용 프롬프트의 차이는 여기서 갈린다. 실패가 보이지 않는 프롬프트는 프로덕션에 들어가선 안 된다. 구체적으로 말하면, 프롬프트 설계 시 반드시 포함해야 할 것들이 있다. 문서화된 실패 모드: 이 프롬프트가 어떻게 실패하는지, 실패의 신호는 무엇인지를 프롬프트 엔트리 자체에 명시한다. 특정성 검증 조건: 출력된 분석이나 발견이 다른 아이디어나 컨텍스트에도 그대로 적용될 수 있다면, 그 프롬프트는 실패한 것이다. 출력 가능성 제한: 추론하거나 일반 지식으로 빈칸을 채우지 않도록 구조적으로 강제한다.
에이전트 오케스트레이터가 다른 에이전트의 출력을 평가하는 LLM-as-judge 패턴을 쓴다면, 이 평가 프롬프트 자체가 조작될 수 있다는 점을 반드시 설계에 반영해야 한다. 평가자 캡처는 AI 평가 파이프라인에서 가장 간과되는 취약점 중 하나다.
데이터 레이어: 500 에러가 조용한 할루시네이션보다 낫다
웹 추출 도구가 에이전트 워크플로우에 붙는 순간 세 번째 실패 레이어가 열린다. Haunt API 개발 과정에서 나온 분석은 이 문제를 가장 직접적으로 지적한다. 나쁜 추출은 나쁜 추론이 된다.
패턴은 단순하다. 스크래핑 파이프라인이 실패하면(CAPTCHA, 로그인 월, 빈 콘텐츠), LLM은 '친절하게' 그럴듯한 JSON을 생성한다. HTTP 200이 돌아왔으니 콘텐츠가 있다고 가정하고, 없는 데이터를 채워 넣는다. 이 가짜 JSON이 에이전트 파이프라인 다음 단계로 흘러가면, 하위 에이전트는 그것을 사실로 취급하고 계획을 세운다. 500 에러는 파이프라인에게 재시도·라우팅·알림·스킵 중 하나를 선택하게 한다. 조용한 할루시네이션은 아무것도 선택하게 하지 않는다. 그냥 오염시킨다.
해결책은 의도적으로 지루하게 설계하는 것이다. 콘텐츠를 LLM에 넘기기 전에, 실제로 추출 가능한 콘텐츠가 있는지를 먼저 검사한다. HTTP 200을 '페이지를 얻었다'는 신호로 해석하지 않는다. 로그인 월, 컨센트 월, CAPTCHA, JS 쉘, 빈 PDF 래퍼는 모두 200으로 돌아올 수 있다. 그리고 추출이 불가능할 때는 구조화된 실패 객체를 반환한다. 에러 타입, 메시지, URL을 포함한 machine-readable 실패 응답은 에이전트가 다음 행동을 선택하게 한다.
MCP 도구로 연결된 에이전트 워크플로우에서는 이 계약이 더 엄격해야 한다. 추출이 근거 있을 때만 구조화된 JSON을 반환하고, 근거 없을 때는 구조화된 에러를 반환하며, 실패 이유를 에이전트가 다음 스텝을 선택할 수 있을 만큼 명확하게 노출한다.
시사점: '신뢰 기본값'을 '의심 기본값'으로 뒤집는 설계 원칙
세 기사가 수렴하는 지점은 하나다. 에이전트 파이프라인의 기본값은 신뢰가 아니라 의심이어야 한다는 것. 이를 실무에 적용하면 세 가지 설계 원칙이 나온다.
첫째, 에이전트 간 신뢰는 자동으로 상속되지 않는다. 에이전트 A가 신뢰받는다고 해서 에이전트 A가 전달하는 메시지가 신뢰받아야 한다는 의미가 아니다. MCP와 A2A 프로토콜에서 AgentCard 서명 검증, nonce 기반 리퀘스트 사이닝, 페이로드 레벨 감사 로그를 빠뜨리는 팀이 많다. 프로토콜 선택보다 이 세 가지를 구현했는지가 더 중요하다.
둘째, 프롬프트 실패 모드는 설계 산출물이다. 코드 리뷰에서 엣지 케이스를 검토하듯, 프롬프트 리뷰에서 실패 모드를 검토해야 한다. '출력이 그럴듯해 보이는가'가 아니라 '이 프롬프트가 실패했을 때 우리가 알아챌 수 있는가'를 기준으로 삼아야 한다.
셋째, 데이터 공백은 할루시네이션으로 채우지 않는다. 에이전트가 빈 컨텍스트에서 계속 진행하도록 허용하는 것은 설계 결정이다. 구조화된 실패를 반환하고 파이프라인이 그것을 처리하도록 강제하는 것도 설계 결정이다. 후자가 훨씬 낫다.
전망: 에이전트 속도가 올라갈수록 '의심 레이어'는 더 많아져야 한다
AI-First 팀이 에이전트 파이프라인을 더 많이 프로덕션에 올릴수록, 이 세 레이어의 중요성은 선형이 아니라 지수적으로 커진다. 에이전트 하나가 초당 수십 개의 툴콜을 날리고, 그 결과가 다른 에이전트의 컨텍스트로 흘러들어가는 환경에서, 신뢰 기본값 설계는 하나의 침해를 전체 메시 붕괴로 증폭시킨다.
내일 당장 팀에 적용할 수 있는 액션은 세 가지다. 첫째, 기존 에이전트 워크플로우에서 LLM이 비어 있거나 오염된 컨텍스트를 받았을 때 어떻게 행동하는지 테스트한다. 둘째, 프롬프트 엔트리마다 문서화된 실패 모드를 추가한다. 셋째, 에이전트 간 메시지에 nonce와 타임스탬프를 붙이는 것을 당장 시작한다. 복잡한 아키텍처 변경 없이 할 수 있는 일이고, 하지 않을 이유가 없다.
에이전트가 빠를수록, 조용한 실패가 더 멀리 번진다. 의심을 기본값으로 설계하는 것은 속도를 줄이는 것이 아니라, 속도를 지속 가능하게 만드는 것이다.