sy/dev
Tool
13 min read

open-multi-agent: 목표를 task DAG로 바꾸는 TypeScript multi-agent 런타임

open-multi-agent를 예로 목표 기반 multi-agent orchestration을 task DAG, scheduler, replay 관점에서 살펴본다.

한 줄 요약

open-multi-agent는 TypeScript 백엔드에서 여러 에이전트를 묶어 실행하는 orchestration framework다. 사용자는 목표를 주고, coordinator agent가 작업을 DAG로 분해하고, deterministic scheduler가 독립 작업을 병렬 실행한 뒤 결과를 합성한다는 구조를 내세운다.

내가 보기엔 이 프로젝트의 흥미로운 지점은 “multi-agent를 몇 명 붙였나”가 아니다. 핵심은 에이전트 협업을 자연어 채팅방이 아니라 inspectable task graph로 바꾸려는 시도다. multi-agent 시스템이 실무에 들어가려면 역할극보다 실행 계획, dependency, replay, 권한 경계가 먼저다.

왜 task DAG가 중요한가

multi-agent 데모는 보통 이렇게 시작한다.

planner: 계획을 세운다
coder: 구현한다
reviewer: 검토한다

보기에는 그럴듯하지만, 운영 관점에서는 부족하다. 실제로 알고 싶은 것은 “누가 말했나”보다 아래 질문들이다.

  • 어떤 작업이 어떤 작업에 의존하는가?
  • 독립적으로 병렬 실행해도 되는 작업은 무엇인가?
  • 실패한 node만 재시도할 수 있는가?
  • 최종 결과가 어떤 중간 산출물에서 왔는지 추적할 수 있는가?
  • 같은 계획을 나중에 다시 실행하거나 diff로 리뷰할 수 있는가?

그래서 task DAG가 중요하다. DAG는 멋있는 시각화용 구조가 아니라, agent runtime의 실행 단위다. 자연어 plan은 사람이 읽기 좋지만 scheduler가 신뢰하기 어렵다. 반대로 task graph는 dependency와 status를 명시하므로 replay, partial retry, audit에 훨씬 유리하다.

open-multi-agent README도 이 차이를 강조한다. graph-first framework처럼 모든 node와 edge를 미리 손으로 열거하는 대신, coordinator가 런타임에 goal을 task DAG로 만들고, 그 계획을 데이터로 내보낸 뒤 scheduler가 실행한다는 흐름이다. 즉 “그래프를 직접 코딩하라”가 아니라 “목표를 주면 그래프를 만들되, 만들어진 그래프는 검사 가능해야 한다”에 가깝다.

기본 구조: coordinator와 deterministic scheduler

README 기준으로 open-multi-agent의 핵심 흐름은 대략 이렇다.

user goal
  -> coordinator agent
      -> task DAG 생성
  -> deterministic scheduler
      -> dependency 없는 task 병렬 실행
      -> blocked task는 선행 task 완료 후 실행
  -> synthesis
      -> 최종 결과 생성

여기서 coordinator는 모든 일을 직접 처리하는 “슈퍼 에이전트”가 아니라 planner 역할에 가깝다. 목표를 보고 task를 나누고, 각 task에 assignee와 dependency를 붙인다. 실행은 scheduler가 담당한다. 이 분리가 중요하다. 계획 생성은 LLM이 잘할 수 있지만, 실행 순서와 dependency 해석까지 LLM에게 계속 맡기면 비결정성이 커진다.

실무형 agent runtime은 보통 다음 원칙을 가져야 한다.

  • LLM은 ambiguity를 줄이고 계획 후보를 만든다.
  • scheduler는 계획을 deterministic하게 해석한다.
  • tool permission은 agent별로 명시한다.
  • 실행 로그는 사람이 나중에 재구성할 수 있어야 한다.

open-multi-agent의 방향은 이 원칙과 맞다. README 예제에서는 architect, developer, reviewer 같은 agent config를 두고, 각 agent가 사용할 수 있는 tool을 명시한다. built-in tool은 default-deny이고, agent가 toolstoolPreset에 적은 도구만 받는다고 설명한다. 이건 작은 디테일처럼 보이지만 꽤 중요하다. multi-agent에서 권한을 “팀 전체”에 주면 결국 가장 위험한 agent의 권한이 전체 시스템 권한이 된다.

실행 모드 세 가지

문서가 제시하는 실행 방식은 크게 세 가지다.

  • runAgent(): 단일 agent에 하나의 prompt를 실행한다.
  • runTeam(): 목표를 주면 coordinator가 task graph를 만들고 팀 실행을 orchestration한다.
  • runTasks(): 사용자가 task graph와 assignment를 직접 정의한다.

이 구분은 괜찮다. 모든 문제를 auto-orchestration으로 풀 필요는 없다.

단순 요약, 형식 변환, 작은 코드 수정은 단일 agent가 낫다. coordinator를 끼우면 latency와 비용만 늘어난다. 반대로 구현, 테스트, 리뷰, 문서화처럼 자연스럽게 dependency가 생기는 작업은 runTeam()이 맞다. 규제·배포·정산처럼 절차가 고정된 업무는 runTasks()처럼 사람이 graph를 명시하는 편이 더 안전하다.

내 기준으로 multi-agent framework를 고를 때 가장 먼저 보는 것도 이 지점이다. “자동으로 다 해준다”만 있으면 위험하다. 자동 계획과 수동 계획을 모두 지원하고, 둘 사이를 오갈 수 있어야 한다. 처음에는 coordinator에게 맡기더라도, 안정화된 업무는 plan artifact로 고정해서 재현 가능하게 만드는 쪽이 운영에 맞다.

planOnly와 replay가 주는 운영상 이점

open-multi-agent 문서에서 눈에 띄는 기능은 plan preview와 replay다. planOnly: true로 coordinator가 만든 task DAG를 실행하지 않고 먼저 확인할 수 있고, createPlanArtifact()로 JSON artifact를 만든 뒤, 나중에 같은 graph를 runFromPlan()으로 다시 실행하는 흐름을 제시한다.

이건 agent 운영에서 꽤 실용적인 패턴이다.

1. coordinator가 plan 초안 생성
2. 사람이 plan artifact 리뷰
3. 위험한 task, 권한, dependency 수정
4. 승인된 plan만 실행
5. 실패하면 동일 plan으로 재현 또는 일부 수정 후 재실행

특히 repo 변경, 배포, 데이터 마이그레이션처럼 side effect가 있는 작업에서는 agent가 바로 실행하는 것보다 plan artifact를 먼저 남기는 편이 낫다. 사람 리뷰도 “이 에이전트가 똑똑해 보이는가”가 아니라 “이 DAG의 edge와 권한이 맞는가”로 바뀐다. 이게 훨씬 리뷰 가능한 단위다.

단, 여기서 착각하면 안 된다. plan artifact가 있다고 해서 실행이 완전히 재현된다는 뜻은 아니다. LLM output, 외부 API, 파일 시스템 상태, dependency version이 바뀌면 결과는 달라질 수 있다. 그래도 최소한 task id, dependency, assignee, 실행 순서를 고정할 수 있다는 점은 큰 차이다.

TypeScript backend에 들어갈 때 볼 포인트

open-multi-agent는 TypeScript-native를 내세운다. README 기준으로 Node.js 18 이상이 필요하고, Vercel AI SDK bridge는 Node.js 22 이상이 필요하다고 적혀 있다. 기본 package는 @open-multi-agent/core이고, OpenAI, Anthropic, OpenAI-compatible endpoint를 다루며 Gemini, Bedrock, MCP, Vercel AI SDK bridge는 opt-in peer dependency로 둔다고 설명한다.

이 설계는 마음에 든다. agent framework가 모든 provider와 integration을 기본 dependency로 끌고 오면 설치는 편하지만 production service에는 부담이 된다. 특히 TypeScript 백엔드에서는 bundle, runtime version, infra policy가 얽히기 쉽다. core를 가볍게 두고 필요한 integration만 넣는 편이 장기적으로 낫다.

도입 전에 확인할 체크리스트는 이 정도다.

  • 우리 업무가 정말 DAG로 쪼개지는가, 아니면 단일 agent loop면 충분한가?
  • coordinator가 만든 plan을 저장·리뷰·diff할 방법이 있는가?
  • agent별 tool permission을 최소권한으로 줄일 수 있는가?
  • 실행 로그에 task id, assignee, token usage, tool result가 남는가?
  • 실패한 task만 재시도할 수 있는가?
  • provider 교체 시 prompt, tool schema, structured output이 얼마나 깨지는가?
  • MCP나 외부 tool을 붙일 경우 인증과 sandbox 경계는 어디에 둘 것인가?

특히 마지막 두 항목이 중요하다. multi-agent framework는 orchestration을 쉽게 해주지만, tool 권한과 데이터 경계까지 자동으로 안전하게 만들어주지는 않는다. DAG가 생기면 오히려 side effect를 만드는 node가 많아질 수 있다.

언제 쓰고, 언제 피할까

open-multi-agent 같은 런타임이 잘 맞는 경우는 명확하다.

  • 목표는 하나지만 하위 작업이 여러 갈래로 나뉜다.
  • 설계, 구현, 검토, 문서화처럼 역할이 실제로 다르다.
  • 중간 산출물과 실행 순서를 기록해야 한다.
  • 병렬 실행으로 latency를 줄일 여지가 있다.
  • TypeScript/Node.js 서비스 안에 agent runtime을 직접 넣고 싶다.

반대로 아래 상황에서는 과하다.

  • 작업이 단일 prompt-response로 끝난다.
  • task dependency가 거의 없다.
  • 결과 검증 기준이 모호해서 reviewer agent도 감으로 평가한다.
  • tool permission과 sandbox를 설계하지 않았다.
  • “multi-agent니까 더 좋겠지” 정도의 이유로 붙인다.

multi-agent는 공짜 성능 향상 버튼이 아니다. 오케스트레이션을 붙이면 token, latency, failure mode도 같이 늘어난다. 그래서 이 계열의 프레임워크는 성능보다 운영 가시성을 사는 도구로 보는 편이 정확하다.

내 의견: 채팅방보다 실행 그래프가 맞다

요즘 multi-agent 프로젝트를 보면 아직도 “여러 persona가 서로 토론한다”는 형태가 많다. 연구나 브레인스토밍에는 쓸 수 있지만, production workflow에는 애매하다. 운영팀이 원하는 것은 재밌는 대화가 아니라 다음 질문에 대한 답이다.

  • 지금 어느 task가 막혔는가?
  • 어떤 output이 다음 task input으로 들어갔는가?
  • 어떤 agent가 어떤 권한으로 어떤 tool을 호출했는가?
  • 실패한 부분만 다시 돌릴 수 있는가?
  • 이 plan을 다음 release에서도 재사용할 수 있는가?

그런 점에서 open-multi-agent의 task DAG 중심 접근은 방향이 좋다. 다만 아직은 README와 예제만으로 판단할 수 있는 부분이 많고, 실제 운영에서 중요한 것은 scheduler 안정성, provider별 structured output 품질, 장기 실행 중 state 관리, tool sandbox의 견고함일 것이다. 첫 도입은 production mutation 업무보다 내부 자동화, 테스트 생성, 문서 정리처럼 rollback이 쉬운 영역에서 시작하는 게 맞다.

참고 자료

Comments