
에이전트 오케스트레이션(Agent Orchestration)은 코드에 속해야 합니다 | Focused Labs
요약
에이전트 오케스트레이션이 프롬프트 기반의 지시에서 코드 기반의 실행으로 진화하고 있습니다. LangChain의 동적 서브에이전트 기능을 통해 모델이 직접 프로그램을 작성하고 실행함으로써 복잡한 작업을 더 정교하게 제어할 수 있습니다.
핵심 포인트
- 에이전트 오케스트레이션이 프롬프트 안무에서 코드로 이동 중
- LangChain의 동적 서브에이전트를 통한 프로그램 기반 작업 수행
- 모델의 메모리 부담을 줄이기 위한 코드 기반의 실행 전략 필요
- 배치 작업 및 복잡한 워크플로우에서의 에이전트 제어 방식 변화
에이전트 오케스트레이션(Agent orchestration)이 프롬프트 안무(prompt choreography)에서 코드로 이동하고 있습니다.
LangChain의 새로운 동적 서브에이전트(dynamic subagents) 헤드라인 아래에는 정말 멋진 기능이 있습니다. 이제 루트 모델(root model)은 아주 작은 프로그램을 작성하고, 이를 인터프리터(interpreter)에서 실행하며, 해당 프로그램이 좁은 task() 브리지 내에서 단계별로 작업을 수행하도록 할 수 있습니다. 예를 들어, 프롬프트가 모델에게 모든 파일을 다루라고 요청하면, 모델은 요청 자체가 커버리지를 생성하는 척하는 대신 해당 파일들을 열거하는 루프(loop)를 작성할 수 있습니다.
'AI 에이전트 오케스트레이션(ai agent orchestration)' 대화에서 우리가 계속 놓치고 있었던 부분은 이것입니다: 모델에게 계획(plan), 위임(delegate), 검증(verify), 재시도(retry) 및 합성(synthesize)을 지시하십시오. 그런 다음 도구 결과(tool results)가 컨텍스트 윈도우(context window)로 스트리밍되어 돌아올 때 전체 흐름을 기억하도록 요청하십시오. 희망은 전략이 아니며, 비용이 많이 듭니다.
LangChain의 동적 서브에이전트에 대한 문서 dynamic subagents documentation는 "더 깔끔한 계약(cleaner contract)"을 설명합니다. 이 모델에서 인터프리터 코드는 당면한 과제를 위해 구성된 서브에이전트들을 직렬(series), 분기(branches) 또는 배치(batches) 단위의 병렬(parallel) 방식으로 디스패치(dispatches)합니다. 모델은 여전히 어떤 작업을 할지 결정하고 있으며, 코드는 커버리지를 위한 것입니다.
실제 AI 에이전트에서의 오래된 하네스(harness) 문제인 real AI agents가 여기서 다시 나타나고 있습니다. 프레임워크에 대한 논의는 배포(deployment) / 트레이싱(tracing) / 평가(evals) / 소유권(ownership) 단계로 넘어갈 때만 가치가 있습니다. LangChain의 Interrupt runtime shift LangChain previewed at Interrupt 컨퍼런스에서 예고된 그 런타임 전환(runtime shift)이 이미 오케스트레이션 계층에서 나타나고 있습니다.
기존 패턴은 작동 샘플을 보여줍니다
작은 액션 체인(action chains)의 경우 일반적인 에이전트 루프(agent loop)로도 충분합니다. 모델은 행동 방침을 계산하고, 도구(tool)를 호출하고, 도구의 출력을 읽고, 체인의 다음 도구를 호출하는 등의 과정을 거칩니다. 매우 작은 작업의 경우 이러한 사고방식은 완벽하게 적절합니다.
배치 작업(Batch work)은 리듬을 깨뜨립니다.
파일 시스템 내의 경로 디렉터리에 대한 보안 검토는 단순히 느낌(vibes)에 의존하는 작업이 아닙니다. 에이전트는 파일을 발견하고, 발견된 각 파일에 대해 검토를 할당하며, 코드 리뷰를 위한 줄 번호를 추적하고, 발견된 결과에서 중복을 제거하며, 결과의 심각도를 확인하는 등의 과정을 거쳐 완전한 보고서가 생성될 때까지 작업을 수행합니다. 위에서 설명한 단계별 위임(Turn-by-turn delegation) 방식은 모델이 메모리에 많은 장부 기록(bookkeeping)을 유지하도록 요구합니다. 모델이 하위 에이전트(subagents)를 할당할 수는 있지만, 이것이 필요한 횟수나 재시도 형태(retry shape) 등은 모두 텍스트로 처리됩니다.
LangChain은 동적 하위 에이전트(dynamic subagents)에 관한 좋은 출시 포스트를 작성했습니다 (LangChain의 동적 하위 에이전트 출시 포스트). 그들은 300페이지 분량의 문서에서 페이지당 하나의 하위 에이전트를 사용하는 예시를 언급합니다. 해당 예시에서 중요한 문구는 “Promise.all”입니다. 그리고 일단 하위 에이전트 오케스트레이션(subagent orchestration)이 코드로 작성되면, 커버리지(coverage)는 더 이상 프롬프트 요청 사항이 아닙니다.
루프(loop)는 커버리지를 열망적인 목표가 아닌 구조적인 요소로 만듭니다.
인터프리터 내부의 형태는 가장 좋은 의미에서 지루할 정도로 명확합니다:
const issuesSchema = {
type: "object",
...
이 코드는 현재의 Deep Agents 인터프리터 문서를 따릅니다. 즉, 적용 가능한 경우 허용 목록(allowlisting)을 거친 후 프로그래밍 방식의 도구 호출(programmatic tool calling)이 tools.* 네임스페이스 아래에 노출되며, 구성된 경우 동적 하위 에이전트(dynamic subagents)가 task()를 통해 노출됩니다.
또한 설명된 아키텍처가 이전 아키텍처와 매우 유사하다는 점에도 주목할 수 있습니다. 컨텍스트 윈도우(context window)는 더 이상 중간 값들을 위한 임시 저장소가 아닙니다. 인터프리터는 관심 있는 값들의 작업 세트(working set)를 보유하며, 모델에는 관련 결과가 제시됩니다.
RLMs는 방향을 명확하게 만듭니다
Recursive Language Models (RLMs)는 소위 RLM 패턴을 따릅니다. 여기서 긴 입력 문자열은 언어 모델의 REPL (Read-Eval-Print-Loop)로 로드되는 외부 환경으로 간주됩니다. 이 REPL 내에서 모델은 입력 문자열의 일부를 조사하고, 작업을 일련의 하위 작업(sub-tasks) 세트로 분해하며, 짧은 코드 스니펫(code snippets)에 대해 언어 모델을 재귀적으로 호출하는 코드를 생성합니다. 저자들은 해당 RLM의 컨텍스트 윈도우 (context window)보다 두 자릿수(two orders of magnitude) 더 큰 입력을 보고했으며, 이는 직접적인 모델 호출이나 긴 입력 문자열을 처리하는 다른 방식들보다 현저히 뛰어난 성능을 보였습니다. 모델 컨텍스트 윈도우를 최대 두 자릿수 초과하는 입력 보고
LangChain의 RLMs in Deep Agents 포스트는 이를 에이전트 인프라로 변환합니다. Deep Agents는 인터프리터 변수(interpreter variables)에 작업 세트(working set)를 유지하고, 컨텍스트 슬라이스(context slices)를 선택하며, task()를 통해 하위 에이전트(subagents)를 파견하고, 해당 하위 에이전트들이 반환하는 객체들을 합성합니다. 또한 이 포스트는 REPL 기반 에이전트가 긴 컨텍스트 집계 작업에서 128k 컨텍스트 환경의 일반 에이전트보다 더 나은 성능을 보였다는 OOLONG 개념 증명(proof of concept)을 보고합니다.
이것이 '에이전트형 AI 아키텍처 (agentic ai architecture)'를 위한 올바른 멘탈 모델(mental model)입니다. 에이전트는 다음에 무엇을 할지 알아내기 위해 거대한 컨텍스트 더미 앞에 앉아 있어서는 안 됩니다. 대신 작업 큐(work queue), 루프(loop), 그리고 타입이 지정된 반환 타입(typed return types)을 가져야 합니다. 모델은 시퀀스의 각 개별 항목을 추적하고 순서대로 회상하려고 노력하는 대신, 문제를 구성 요소로 분해하는 판단에 집중하고, 그 구성 요소들을 다시 솔루션으로 합성하는 데 스스로를 투입해야 합니다.
컨텍스트(Context)와 작업은 하네스(harness)가 분할(partition), 라우팅(route), 검증(verify)할 수 있는 데이터가 됩니다.
Claude Code도 유사한 경로를 걷고 있습니다. Anthropic은 동적 워크플로(dynamic workflows)를 통해 Claude가 병렬 서브에이전트(subagents)를 실행하는 오케스트레이션 스크립트를 작성하고, 진행 상황을 저장하며, 작업을 확인하고, 하나의 조정된 답변을 반환할 수 있다고 밝히고 있습니다. 방향은 유사하지만, 하네스는 다릅니다. 에이전트 오케스트레이션(Agent orchestration)이 실행 가능한 형태(executable)가 되어가고 있습니다.
보안 문제는 브리지(bridge)로 이동합니다
에이전트가 코드를 작성하는 것을 우려하는 팀들에게는 또 다른 종류의 공포가 작용합니다. 그들은 샌드박스화된 셸(sandboxed shell)의 모든 복잡성, 즉 패키지 매니저(package manager), 파일 시스템(file system), 네트워크(network) 등을 상상하게 됩니다. 지루해진 엔지니어가 금요일에 풀어놓을 수 있는 그 모든 새로운 혼돈 말입니다. 그것이 한 가지 종류의 공포입니다.
인터프리터(Interpreters)는 더 작습니다.
QuickJS 인터프리터 코드는 기본적으로 호스트 파일 시스템(host filesystem), 네트워크(network), 셸(shell), 패키지 매니저(package manager), 심지어 시계(clock)조차 없습니다. 오직 계산하고, 변수를 유지하며, 콘솔에 출력할 수 있을 뿐입니다. 두 가지 명시적인 브리지(bridge)는 허용 목록(allowlist)을 통한 프로그래밍 방식의 도구 호출(tool calling)과 task()를 통한 서브에이전트 디스패치(subagent dispatch)입니다.
브리지가 좁기 때문에 인터프리터는 유용합니다.
샌드박스 없이 신뢰할 수 없는 에이전트 코드를 실행하는 것에 관한 LangChain의 게시물 running untrusted agent code without a sandbox은 그 경계를 설명합니다. QuickJS는 WebAssembly (Wasm)에서 실행됩니다. 호스트 코드는 신뢰할 수 없는 코드가 사용하도록 의도한 기능만을 노출합니다. WebAssembly 프로젝트의 메인 페이지는 Wasm을 "범용 프로그래밍을 위한 메모리 안전(memory-safe)하고 샌드박스화된 실행 환경(sandboxed execution environment)"이라고 설명합니다 WebAssembly project describes Wasm as a memory-safe, sandboxed execution environment. QuickJS-ng의 홈페이지는 QuickJS를 "작고 임베디드 가능한 JavaScript 엔진(small embeddable JavaScript engine)"이라고 설명합니다 QuickJS-ng describes QuickJS as a small embeddable JavaScript engine. 여기서 '작다'는 것은 공격 표면(surface area)이 적다는 것을 의미하며, 이것이 제가 중요하게 생각하는 부분입니다. 핵심 JavaScript 엔진의 공격 표면이 적다면, 오케스트레이션 (orchestration) 코드에 이상한 권한이 유입될 수 있는 기이한 방식이 줄어들기 때문입니다.
완전한 샌드박스(sandbox)가 오늘날에도 여전히 유효하다는 점에 주목하십시오. 예를 들어, LangChain의 sandbox guidance는 코딩, 데이터 분석, 브라우저 등의 작업(에이전트가 보통 많은 의존성(dependencies)을 다루며, 따라서 샌드박스의 이전 런타임 값들을 통제된 방식으로 사용하며 오랫동안 실행되어야 하는 경우)에 적합한 샌드박스의 기능으로 다음을 나열합니다: 격리된 파일 시스템 (isolated filesystem), 외부 네트워크 연결 제한 (restricted for making outgoing net connections), 제한된 리소스 (limited resources), 샌드박스의 이전 런타임 값의 통제된 재사용 (controlled reuse of prior runtime values of the sandbox), 완전한 커널 수준 격리 (full kernel level isolation). 요컨대, 이러한 작업을 수행하는 데 있어 에이전트는 단순히 컴퓨터를 대체하는 것입니다.
인터프리터 (Interpreter)는 범용 샌드박스 (sandbox)가 아니라, 주어진 역량 내에서 루프 (loops), 조건문 (conditional statements), 필터링 (filtering), 집계 (aggregation), 팬아웃 (fanout)과 같은 특정 작업 세트를 수행하기 위한 도구입니다. 에이전트가 실제로 머신 위에서 실행되어야 하는 작업의 경우에는 완전한 샌드박스 (full sandbox)가 더 적합합니다. 에이전트가 오케스트레이션 (orchestration)을 수행해야 하는 작업의 경우에는 인터프리터 (interpreter)가 더 적합합니다.
Meta의 Agents Rule of Two는 그 위험성을 상세히 설명합니다. 프롬프트 인젝션 (prompt injection) 문제가 해결될 때까지, 에이전트는 한 세션 내에서 신뢰할 수 없는 입력 (untrusted inputs), 민감하거나 개인적인 데이터 (sensitive or private data), 외부 상태 변경 또는 통신 (external state change or communication) 중 두 가지를 초과해서는 안 됩니다. 인터프리터 브리지 (Interpreter bridges)는 하네스 (harness)가 해당 규칙을 강제할 수 있는 공간을 제공합니다. 즉, 어떤 도구가 존재하는지, 어떤 하위 에이전트 (subagents)가 실행되는지, 승인이 어디에서 일어나는지, 그리고 어떤 데이터가 다시 넘어오는지 정의합니다.
이 지점이 바로 하네스가 오케스트레이션 경계(orchestration boundary)를 소유하는 곳입니다. 모델은 프로그램을 제안하고, 하네스는 그 프로그램이 무엇을 건드릴 수 있는지 결정합니다.
실행 가능한 오케스트레이션에는 증거가 남습니다
프로그래밍 방식의 오케스트레이션 (Programmatic orchestration)은 완전히 새로운 종류의 스크립트 버그 (script bugs)를 만들어낼 것입니다. 단순한 스크립트는 여전히 잘못된 스키마 (schema)를 전달할 수 있습니다. 더 복잡한 스크립트는 너무 많은 하위 에이전트 (subagents)를 생성하거나, 제출된 작업에서 신호 (signal)를 필터링하여 없애버릴 수 있습니다. 오래된 인터프리터 변수 (interpreter variable)는 상태 지속성 (state persistence)이 그렇게 설정되었기 때문에 턴 (turns) 사이에도 살아남을 수 있습니다.
좋습니다. 이것들은 검사 가능한 실패들입니다.
LangChain의 인터프리터 지속성 (interpreter persistence)에는 “thread”, “turn”, “call”의 세 가지 모드가 있습니다. 따라서 미들웨어 (middleware)는 “thread” 모드에서 턴 (turns) 사이의 인터프리터 상태를 저장합니다. “call” 모드에서의 모든 “eval”은 처음부터 다시 시작합니다. 도구 허용 목록 (tool allowlists), task() 가시성 (visibility), 동시성 제한 (concurrency limits), 스키마 계약 (schema contracts), 그리고 승인 게이트 (approval gates)와 마찬가지로, 여기서의 트레이드오프 (trade-offs)는 프롬프트 민속 (prompt folklore) 속에 갇혀 있는 것이 아니라 코드 리뷰 (code review)에서 논의되어야 합니다.
이는 동적 서브에이전트 (dynamic subagents) 문서에 포함된 경고 사항이며, 체크리스트에 포함되어야 합니다: task()는 이미 실행 중인 eval 호출 내부에서 작업을 할당 (dispatch)합니다. 부모 에이전트 (Parent-agent)의 interrupt_on 승인 워크플로우 (approval workflows)는 작업 할당 (task dispatch)마다 강제되지 않습니다. 즉, 오케스트레이션 (orchestration)이 실행되기 전에 승인이 이루어져야 하는 경우, eval 도구 (tool)에 게이트 (gate)를 설치해야 한다는 의미입니다.
이 문구는 운영 모델 (operating model)에 포함되어야 합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기
