하나의 워크플로우에서 여러 에이전트 도구 체이닝하기: 레시피
요약
서로 다른 인증 모델과 응답 형식을 가진 여러 에이전트 도구를 하나의 파이프라인으로 효율적으로 연결하는 방법을 다룹니다. '발견(Discover), 설치(Install), 호출(Call)' 패턴을 통해 복잡한 오케스트레이션 코드 없이 JSON 기반의 로컬 계약을 활용하여 도구 체이닝을 구현하는 레시피를 제공합니다.
핵심 포인트
- 도구 간의 인증 및 응답 형식을 통일하는 로컬 계약의 중요성
- 복잡한 REST 호출 대신 '설치 후 호출' 방식의 효율성
- JSON 입출력을 활용한 간결한 에이전트 체이닝 패턴
- 검색, 정보 강화, 배포로 이어지는 워크플로우 구축 사례
지난 한 주 동안 저는 세 가지 에이전트 도구(agent tools)를 하나의 파이프라인(pipeline)으로 연결하는 작업을 했습니다. 이론적으로는 간단한 작업이었습니다. 흥미로운 것을 개발하는 회사를 찾고, 연락처를 확보한 뒤, 데모 환경을 구축하는 것이었죠. 하지만 이 단계들을 결합한다는 것은 웹 검색 도구, 인맥 정보 API(people-intelligence API), 그리고 클라우드 배포 도구(cloud deployer)를 연결하는 것을 의미했습니다. 이 세 가지는 서로 다른 인증 모델(auth models)과 서로 다른 응답 형태(response shapes)를 가지고 있었으며, 그 중 어느 것도 서로 통신하도록 설계되지 않았습니다.
처음에는 뻔한 방식인 Python에서 REST 호출을 하고, JSON을 파싱하며, 상태 머신(state machine)을 구축하는 방식을 시도했습니다. 작동은 했지만 취약했습니다. 각 도구마다 고유한 URL 스키마, 고유한 인증, 고유한 재시도 로직(retry logic)을 가지고 있었습니다. 오케스트레이션(orchestration) 코드가 실제 로직보다 열 배는 더 길었습니다.
그다음 저는 다른 방식을 시도했습니다. 각 도구를 로컬 IPC 서비스로 실행하여, 각각 install-then-call 방식으로 작동하게 하고, 딕셔너리(dict)를 전달하는 순수 Python 코드로 접착제(glue) 코드를 작성했습니다. 전체 파이프라인이 약 30줄 만에 완성되었습니다.
패턴: 발견(Discover), 설치(Install), 호출(Call)
핵심 통찰은 모든 도구가 동일한 로컬 계약(local contract) — 즉, JSON 입력, JSON 출력, 설치 시 자동 생성(auto-spawned) — 을 따를 때 체이닝(chain)이 스스로 작성된다는 점입니다. 각 단계는 이전 단계의 출력을 받아 이를 변환하고 앞으로 전달합니다. HTTP 배관 작업(plumbing), 인증 헤더(auth headers), 폴링(polling)이 필요 없습니다.
제가 구축한 파이프라인은 다음과 같습니다. 각 도구는 하나의 카탈로그(catalogue)에 있는 앱이며, 한 번 설치된 후 반복적으로 호출됩니다.
1단계: 검색 — 대상 찾기
모든 파이프라인은 무언가를 찾는 것에서 시작합니다. 저는 오픈 소스 AI 인프라(open-source AI infrastructure)를 연구하는 회사가 필요했습니다. 스크래핑을 하거나 브라우저를 사용하는 대신, 인용(citations)과 함께 구조화된 결과(structured results)를 반환하는 근거 기반 검색 도구(grounded search tool)를 사용했습니다.
pilotctl appstore install io.pilot.cosift
pilotctl appstore call io.pilot.cosift cosift.search '{"q":"open source AI infrastructure companies 2026","k":5}'
응답은 제목, URL, 요약, 그리고 결과별 관련성 점수(relevance score)가 포함된 깔끔한 JSON 형식으로 돌아왔습니다. 파싱해야 할 HTML도, 검사해야 할 속도 제한(rate-limit) 헤더도 없었습니다. 저는 가장 관련성이 높은 검색 결과를 선택했고, 다음 단계에 필요한 모든 것, 즉 회사 이름과 웹사이트를 확보했습니다.
설치는 한 번만 수행하면 됩니다. 그 이후의 모든 검색은 단 한 줄의 call 명령어로 이루어집니다.
2단계: Enrich (강화) — 이름을 연락처로 변환하기
이름은 유용하지만, "무언가를 찾는 것"에서 멈추는 파이프라인은 절반짜리 파이프라인에 불과합니다. 다음 단계는 강화(enrichment)였습니다. 즉, 회사 이름이 주어졌을 때 그들의 인프라를 구축하는 사람, 즉 전문적인 맥락을 가진 실제 인물을 찾는 것입니다.
또 다른 설치와 또 다른 호출이 이어집니다:
pilotctl appstore install io.pilot.sixtyfour
pilotctl appstore call io.pilot.sixtyfour sixtyfour.search '{"query":"head of infrastructure at <company>","limit":3}'
이 명령은 이름, 직함, 회사, LinkedIn, 그리고 신뢰도 추정치(confidence estimate)가 포함된 강화된 프로필을 반환했습니다. 구조적으로는 검색 도구의 출력 형식과 동일하며, 필드만 다를 뿐입니다. 이것이 체이닝(chaining)을 매끄럽게 만드는 속성입니다. 모든 도구는 다음 단계로 전달할 수 있는 딕셔너리(dict)를 반환합니다.
3단계: Deploy (배포) — 데모 환경 실행하기
세 번째 단계는 핵심적인 부분인 보여주기 위한 무언가를 배포하는 것이었습니다. 자신의 도구에 대해 누군가에게 연락할 때, 상대방이 단 한 번의 명령으로 그것을 시도해 볼 수 있다면 큰 도움이 됩니다. 그래서 저는 사전 구성된 데모가 포함된 일회용 마이크로 VM(microVM)을 푸시했습니다:
pilotctl appstore install io.pilot.smol
pilotctl appstore call io.pilot.smol smol.push '{"image":"pilot-demo","net":true,"ttl":3600}'
배포기(deployer)는 공개 URL과 만료 시간인 TTL을 반환했습니다. 이 정보는 강화된 연락처 정보와 함께 메시지 초안에 바로 포함되었습니다.
접착제: 몇 줄의 Python 코드
검색부터 배포까지 전체 체인은 다음과 같이 매우 간단합니다:
import json, subprocess
def call_app(app_id, method, payload):
...
비동기 콜백(async callbacks), 웹훅(webhook) 연결, curl 래퍼(wrappers)가 전혀 필요 없습니다. 각 단계는 딕셔너리를 반환하는 함수 호출입니다. 체인은 그저 함수를 통해 흐르는 데이터일 뿐입니다.
이 방식이 REST-and-Glue 접근법보다 뛰어난 이유
도구들을 체이닝(chaining)하는 표준적인 접근 방식은 다음과 같습니다:
- 각 도구의 REST API 문서 찾기
- 인증(auth), 기본 URL(base URL), 에러 처리(error handling)를 위한 래퍼(wrapper) 작성
- 서비스별로 속도 제한(rate limits) 및 재시도(retries) 처리
- 응답을 공통된 형태(common shape)로 파싱(parse)
- 상태(state)를 수동으로 전달
모든 도구가 동일한 IPC 계약(contract)을 따를 때, 1~4단계는 사라집니다. 한 번 설치하고, 딕셔너리(dict)로 호출하면, 딕셔너리를 돌려받습니다. 오케스트레이션(orchestration) 레이어는 HTTP 응답을 다루는 상태 머신(state machine) 대신, 함수 호출을 순회하는 for 루프가 됩니다.
이는 이론적인 이야기가 아닙니다. 수십 년 전 UNIX 파이프(pipes)가 발견한 것과 동일한 패턴입니다. 공통 형식을 읽고 쓰는 작고 집중된 도구들이 파이프라인(pipelines)으로 구성되는 방식입니다. 차이점은 이 도구들이 단순한 문자 변환이 아니라 실제 기능(웹 검색, 연락처 정보 보강, 클라우드 배포 등)을 가지고 있다는 점입니다.
체이닝이 무너지는 경우 (그리고 그렇지 않은 경우)
단순한 선형 체인(linear chains)은 깔끔하게 작동합니다. 문제는 분기(branching)가 필요할 때 발생합니다 — 예: 검색 → (정보 보강 AND 다시 검색) → 병합(merge) → 배포(deploy). 이는 일반적인 Python으로도 관리할 수 있지만, 오케스트레이션이 명시적으로 변하게 됩니다.
더 큰 함정은 상태(state)입니다. 만약 2단계에서 1단계가 반환하지 않은 데이터(세션 토큰, 속도 제한 초기화 정보 등)가 필요하다면, 다시 도구별 래퍼(wrapper)를 만들어야 하는 상황으로 돌아가게 됩니다. 해결책은 관례(convention)를 정하는 것입니다. 체인의 각 도구는 첫 번째 호출 시 하류(downstream) 도구가 합리적으로 필요할 수 있는 모든 것을 반환해야 합니다. 숨겨진 상태는 없어야 합니다.
핵심 요약
하나의 워크플로우에서 여러 에이전트 도구를 체이닝하는 데 무거운 오케스트레이션 프레임워크가 필요하지는 않습니다. 도구들이 균일한 호출 패턴을 가진 로컬 IPC 서비스라면, 파이프라인은 그저 함수 호출의 연속일 뿐입니다. 한 번 설치하고, JSON으로 호출하고, 출력을 앞으로 전달하면 됩니다.
탐색 단계가 가장 비용이 적게 드는 부분입니다 — pilotctl appstore catalogue를 통해 사용 가능한 모든 도구를 확인할 수 있습니다. 설치는 한 줄이면 충분합니다. 구성(composition)은 여러분의 몫이며, 이는 그저 함수를 통해 흐르는 데이터일 뿐입니다.
만약 에이전트(agents)를 위한 도구를 구축하고 있다면, 이를 로컬 IPC (Inter-Process Communication) 서비스로 배포하는 것을 고려해 보세요. 사용자들은 여러분이 상상도 못 했던 파이프라인(pipelines)에 이 도구들을 체이닝(chaining)할 것이며, 그 과정에서 REST 클라이언트를 전혀 사용하지 않을 것입니다.
직접 시도해 보세요: curl -fsSL https://pilotprotocol.network/install.sh | sh를 실행한 다음, pilotctl appstore catalogue를 입력하여 사용 가능한 모든 항목을 확인하세요. 도구 세 개를 골라 체이닝해 보세요. 예상보다 훨씬 빠르게 작동하는 파이프라인을 갖게 될 것입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기