에이전트를 만들려면 당연히 LangGraph 인 줄 알았다
워크플로 그래프를 쓰지 않기로 한 팀에 합류하고 두 달, 오픈소스 세 개를 뜯어보며 그 이유를 이해한 기록
AI 에이전트를 만든다고 하면 LangGraph 부터 떠올렸다. 노드를 놓고 엣지를 잇고 조건 분기를 그리는 그림. 이전 회사에서 실제로 그렇게 만들어보기도 했다.
그런데 지금 회사에 와서 알게 된 건, 우리는 LangGraph 를 쓰지 않는다는 것이었다.
솔직히 좀 당황했다. 에이전트를 만드는데 에이전트 프레임워크를 안 쓴다니. 내가 모르는 사정이 있는 걸까, 아니면 그냥 아직 도입을 안 한 걸까. 물어보기 전에 스스로 답을 찾아보고 싶었다.
두 달 걸렸다. 그리고 이유는 기술 취향의 문제가 아니었다.
남들은 어떻게 만드나#
일단 남의 코드부터 봤다. 잘 만들어진 에이전트가 실제로 어떻게 생겼는지 보면 답이 나올 것 같았다.
Waiting for api.github.com...
파일이 7,845 개나 되는 큰 프로젝트다. 이런 규모라면 정교한 그래프 엔진 하나쯤 있겠거니 하고
심장부인 agent/conversation_loop.py 를 열었는데, 구조가 이랬다.
user message
↓
conversation_loop
① 프롬프트 조립
② 모델 호출
③ tool_calls 있으면 실행하고 결과를 다시 넣는다
└── 반복 (max_iterations 소진까지)
↓ tool_calls 없으면
turn_finalizerplaintext노드도 엣지도 없다. 루프와 도구 호출, 그리고 반복 상한이 전부였다.
Waiting for api.github.com...
이쪽은 좀 달랐다. Interview → Seed → Execute → Evaluate → Evolve 라는 뚜렷한 단계가 있다.
순서가 이렇게 명확한데도 그래프 프레임워크를 쓰지 않는다. 순서가 정해져 있으면 그래프로 그리는 게
자연스러운 것 아닌가. 이 질문은 뒤에서 다시 다룬다.
마지막은 Cloudflare 가 사내에서 쓰던 AI 작업 공간을 공개한 Cloudflare OS ↗ 다. 여기는 아예 방향이 다르다. 미리 정해둔 절차를 따르는 대신 모델이 코드를 작성해서 실행한다. 데이터를 통째로 컨텍스트에 밀어 넣는 대신, 검색하고 걸러내고 합치는 코드를 그때그때 짜게 하는 방식이다. 문서 어디에도 LangGraph 같은 프레임워크 이야기는 없다.
셋 다 그래프 프레임워크가 없었다. 그런데 읽다 보니 이유가 조금씩 다르다는 게 더 흥미로웠다.
우리가 안 쓰는 이유#
우리 서비스는 SaaS 다. 기업들이 우리 플랫폼 위에서 각자 에이전트를 만든다.
여기에 결정적인 제약이 하나 있다. 우리는 고객이 무슨 에이전트를 만들지 모른다. 계약서를 검토하는 에이전트를 만들지, 매출 지표를 정리하는 에이전트를 만들지 알 방법이 없다. 알아야 할 이유도 없고, 알아서도 안 된다.
모르는 업무의 순서는 그릴 수 없다.
처음에는 이걸 인력 문제로 생각했다. “우리 팀이 수천 개의 워크플로를 다 만들 수는 없으니까.” 그런데 그건 정확한 진단이 아니었다. 사람이 더 있어도 못 만든다. 무엇을 만들어야 하는지 모르니까.
그럼 워크플로 빌더를 만들어서 고객이 직접 그리게 하면 되지 않을까. 노드를 끌어다 놓는 방식으로. 실제로 그런 제품들이 이미 있다.
이 생각도 같은 벽에 부딪힌다. 그 빌더에 들어갈 노드는 누가 만드나. 고객이 어떤 작업을 원하는지 모르는데 무슨 노드를 미리 만들어 둘 수 있을까. 결국 “우리가 하나하나 만든다”로 되돌아온다.
그래서 실행 흐름을 설계 시점에 정하지 않고 런타임으로 미뤘다. 무엇을 어떤 순서로 할지는 모델이 그때그때 판단한다.
그럼 순서는 어떻게 지키나#
여기서 당연한 반문이 나온다. 순서를 안 정하면 아무렇게나 돌아도 되는 건가?
앞에서 미뤄둔 질문으로 돌아가자. Ouroboros 는 5단계 순서가 뚜렷한데 왜 그래프로 안 그렸을까. 저장소를 보면 순서를 이렇게 지킨다.
-
게이트 조건
모호도 점수가 임계값 아래로 떨어져야 다음 단계로 넘어간다. 조건을 못 넘기면 거기서 막힌다.
-
데이터 의존
각 단계가 이전 단계의 출력을 입력으로 요구한다. 건너뛰면 넣을 입력이 없다.
-
이벤트 저장
진행 상태를 이벤트로 남긴다. 중단돼도 멈춘 지점부터 재개된다.
그래프와 무엇이 다른가. 핵심은 순서를 선언하느냐 검증하느냐 다.
[그래프] 순서를 선언한다. A → B → C 를 미리 그린다
경로가 고정된다. 새 경로가 필요하면 그래프를 고쳐야 한다
[게이트+상태] 순서를 검증한다. "이 조건을 만족해야 다음으로 간다"
경로는 자유롭다. 조건만 지키면 어떤 순서로 가든 상관없다plaintext이 차이가 우리 상황과 정확히 맞물린다. 고객이 어떤 경로로 갈지는 모르지만, 어떤 경로로 가든 지켜야 할 조건은 우리가 정의할 수 있다.
| 우리가 모르는 것 | 우리가 아는 것 |
|---|---|
| 무슨 작업을 하는지 | 권한 없이 자원에 접근하면 안 된다 |
| 어떤 순서로 하는지 | 승인이 필요한 작업은 사람을 거쳐야 한다 |
| 도구를 몇 번 쓰는지 | 무한히 돌면 안 된다 |
경로는 모델에게 맡기고, 불변 조건은 강제한다. 그래프가 하던 일을 상태와 게이트가 대신하는 셈이다.
흐름을 포기한 대신 떠안은 것#
실행 흐름을 모델에게 넘기면 편해질 것 같지만 오히려 책임이 늘어난다. 무엇을 할지 예측할 수 없는 프로그램을 남의 회사 데이터 위에서 돌려야 하기 때문이다.
그래프였다면 실행 경로가 곧 명세였다. 어떤 노드가 어떤 자원에 닿는지 그림만 봐도 알 수 있고, 위험한 노드는 아예 안 그리면 그만이다. 그 안전장치가 사라진 자리를 전부 직접 채워야 한다.
지금 붙들고 있는 건 이런 것들이다.
- 샌드박스 격리 — 모델이 짠 코드를 어디서 돌릴 것인가. 무엇을 막고 무엇을 열어줄 것인가
- 도구 선정 — 애초에 어떤 도구를 쥐여줄 것인가. 도구가 곧 에이전트의 행동 반경이 된다
- 권한 분리 — 그 도구를 누가, 어디까지 쓸 수 있게 할 것인가
- 관측 — 스스로 판단해서 움직인 걸 나중에 어떻게 들여다볼 것인가
Cloudflare OS 가 보안 계층을 제품 전면에 내세운 것도 같은 이유일 것이다. 자율성을 주는 순간 경계를 세우는 일이 부가 기능이 아니라 본체가 된다.
솔직히 아직 답을 모른다. 넷 다 구현 전이고, 지금은 최적의 설계를 먼저 그리기보다 하나씩 만들면서 부딪혀 보는 중이다. 어차피 해봐야 아는 일이라는 점에서, 우리가 만드는 에이전트와 우리가 일하는 방식이 닮아 있다.
그래도 그래프가 맞는 경우#
이 글이 “프레임워크는 필요 없다”로 읽히면 곤란하다. 오히려 반대에 가깝다.
Cloudflare OS 문서에도 이런 취지의 문장이 있다. 모든 일이 완전한 에이전트 세션을 필요로 하지는 않으며, 상당수는 순서가 이미 알려져 있고 판단이 필요한 지점만 한두 곳이라는 것이다.
기준은 결국 하나다. 순서를 미리 알 수 있는가.
매주 같은 지표를 뽑아 같은 채널에 올리는 일이라면 순서를 안다. 그리면 된다. 그래프가 훨씬 싸고 빠르고 예측 가능하다. 이런 일까지 모델에게 맡기는 건 낭비다.
반대로 무엇을 해야 할지 해봐야 아는 일, 그리고 누가 무엇을 시킬지조차 모르는 플랫폼이라면 그릴 수 없다. 우리가 후자였을 뿐이다.
정리#
두 달 동안 헤맨 끝에 알게 된 건, 이게 애초에 프레임워크를 고르는 문제가 아니었다는 것이다. 실행 흐름을 설계 시점에 정할 것인가, 런타임으로 미룰 것인가. 그 질문에 먼저 답해야 도구가 정해진다.
우리는 고객이 무엇을 만들지 모르는 자리에 있어서 미리 정할 수가 없었다. 그래서 경로 대신 조건을 책임지기로 한 것이다.
처음에 느꼈던 의아함은 이제 없다. 대신 다른 게 생겼는데, 그래프가 대신 해주던 일을 전부 직접 설계해야 한다는 부담이다. 그건 또 다른 글이 될 것 같다.