Give a Mastra Agent a Browser for Logged-in Pages with Firecrawl
Quick Summary
@mastra/browser firecrawl은 Mastra 에이전트에 로그인 페이지를 조작하는 원격 브라우저를 제공하며, thread별 세션과 이름 있는 Firecrawl 프로필로 사용자 격리와 로그인 상태 재사용을 지원한다.
🖼️ 인포그래픽

🖼️ 4컷 인포그래픽

💡 한 줄 요약
@mastra/browser-firecrawl은 Mastra 에이전트에 로그인 페이지를 조작하는 원격 브라우저를 제공하며, thread별 세션과 이름 있는 Firecrawl 프로필로 사용자 격리와 로그인 상태 재사용을 지원한다.
📌 핵심 요약
- FirecrawlBrowser는 AgentBrowser를 확장해 기본 브라우저 도구 16개와 요소 참조(ref)를 유지하면서 Firecrawl Interact 세션에서 실행되므로 로컬 Chromium 설치가 필요 없다. 공개 페이지는 Search·Scrape로 처리하고, 로그인·폼 입력·클릭이 필요한 페이지는 브라우저로 조작한다.
- 에이전트는 browser_snapshot으로 현재 요소 참조를 얻고 입력·클릭 뒤 다시 스냅샷을 확인한다. 참조는 생성된 스냅샷에만 유효하며, 일반 텍스트를 읽으려면 interactiveOnly: false가 필요하다. Mastra의 기본 실행 한도는 5단계이고, 예제는 약 25단계가 필요해 maxSteps: 40을 설정한다.
- 기본값인 scope: 'thread'에서는 thread id마다 별도 브라우저 세션을 만들고 살아 있는 동안 재사용한다. thread id를 생략하면 모든 호출자가 기본 세션과 로그인을 공유한다. ttl은 기본 600초·최대 3600초이고 activityTtl은 기본 300초이며, 세션 만료 뒤 새 세션에는 쿠키가 없다.
- 실행 간 로그인 유지는 firecrawl.profile의 이름 있는 Firecrawl 프로필로 처리한다. 최초 로그인에서 saveChanges: true로 설정하고 브라우저를 닫아 상태를 저장한 뒤, 일반 실행에서는 saveChanges: false로 읽는다. 같은 프로필에 동시에 저장하려는 두 번째 세션은 409 오류로 거부되며, 사용자별 계정에는 사용자별 프로필이 필요하다.
- 저장된 프로필을 이용하면 비밀번호가 모델·트레이스·메모리에 전달되지 않지만, 에이전트가 읽는 로그인 페이지 내용은 모델과 트레이스에 전달된다. 설치에는 관련 Mastra 패키지와 [email protected], FIRECRAWL_API_KEY, 모델 제공자 키, Memory용 저장소가 필요하며 thread당 요청은 한 번에 하나씩 보내고 작업 후 브라우저 세션을 닫는다.
🧩 주요 포인트
- AgentBrowser 도구와 ref 유지 → 기존 조작 방식으로 원격 브라우저를 사용하되, 매 행동 후 스냅샷 갱신과 충분한 maxSteps 설정이 실행 안정성을 좌우한다.
- thread별 세션과 Firecrawl 프로필의 역할 분리 → thread id는 실행 중 브라우저를 격리하고, 프로필은 실행 간 로그인 계정을 결정하므로 두 설정을 함께 설계해야 한다.
- 프로필의 단일 저장 세션 제약과 로그인 페이지 내용 전달 → saveChanges: true는 최초 로그인 저장에 사용하고, 비밀번호 보호와 페이지 내용의 모델·트레이스 전달 범위는 구분해 판단해야 한다.
🧠 상세 정리
1. 공개 페이지 수집을 넘어 로그인 뒤의 작업으로
Juan Pablo Hernandez가 2026년 10월 20일 작성한 이 글은 Mastra 에이전트가 로그인 뒤에 있는 페이지를 이용하도록 FirecrawlBrowser를 연결하는 방법을 설명한다. 공개 상태로 내용이 로드되는 페이지에는 Search와 Scrape가 적합하지만, 공급업체 포털이나 날짜 범위를 고른 뒤 Export를 눌러야 나타나는 보고서에는 입력과 클릭을 수행할 브라우저가 필요하다는 구분에서 출발한다. 예제로 쓰인 Swag Labs는 Sauce Labs의 공개 데모 상점이며, 로그인 없이 /inventory.html에 접근하면 로그인해야 접근할 수 있다는 오류를 반환한다. 재고 내용이 존재하더라도 폼 입력과 클릭, 대기를 거치기 전에는 접근할 수 없다는 점이 브라우저 도입의 근거다. @mastra/browser-firecrawl의 FirecrawlBrowser는 이 브라우저를 Firecrawl Interact 세션에서 실행해 로컬 Chromium 설치와 실행 유지 부담을 없앤다.
2. Mastra 에이전트 연결과 실행 단계 설정
브라우저는 도구나 메모리처럼 Mastra Agent의 browser 필드에 연결하며, 예제는 FIRECRAWL_API_KEY를 받는 FirecrawlBrowser와 Memory를 함께 등록한다. 모델은 openai/gpt-5.6-sol로 지정하고, defaultOptions에 maxSteps: 40을 설정해 호출자가 매번 실행 한도를 전달하지 않아도 되게 한다. Mastra는 기본적으로 5단계 뒤 에이전트를 멈추지만, 예제의 로그인부터 주문 완료까지는 행동마다 스냅샷을 확인하므로 약 25단계가 필요했다. FirecrawlBrowser는 AgentBrowser를 확장하기 때문에 browser_goto, browser_snapshot, browser_click, browser_type 등을 포함한 기본 도구 16개와 같은 요소 참조 방식을 제공한다. 실제 페이지는 Mastra가 Firecrawl API로 요청한 원격 세션에서 실행되고 CDP로 제어되며, Memory는 대화 맥락을, 브라우저 세션은 장바구니 같은 페이지 상태를 유지한다. 두 상태는 호출 시 전달하는 memory의 thread와 resource 설정을 통해 연결된다.
3. 스냅샷과 참조로 로그인부터 주문 확인까지
데모 요청은 standard_user와 secret_sauce로 Swag Labs에 로그인하고 Sauce Labs Backpack을 장바구니에 담은 뒤 Jane Doe와 우편번호 94105로 주문해 확인 문구를 반환하는 작업이다. 에이전트는 browser_goto 다음 browser_snapshot을 호출해 HTML 대신 Username, Password, Login 같은 상호작용 요소와 @e1, @e2, @e3 참조를 받고, 입력과 클릭 후 다시 스냅샷을 읽는다. 참조는 해당 스냅샷에서만 유효하므로 페이지가 바뀌면 새 참조를 사용해야 하며, 로그인 페이지로 되돌아온 경우에는 오류 해제 버튼 때문에 Login의 참조가 @e3에서 @e4로 바뀔 수도 있다. 재고 화면에서는 Backpack 행에 대응하는 Add to cart 버튼을 선택하고, 장바구니와 결제 폼, Continue, Finish에서도 같은 확인 과정을 반복한다. 주문 완료 문구는 일반 텍스트여서 기본 스냅샷에 빠지므로 interactiveOnly: false로 다시 읽어야 하며, 이때 Thank you for your order!와 주문이 발송되었다는 문장을 얻는다. 글은 이 작업을 별도로 작성한 선택자나 페이지 전용 코드 없이 수행하는 예로 제시한다.
4. thread별 세션 격리와 수명 제한
FirecrawlBrowser의 기본 scope는 'thread'이며, 각 Mastra thread가 처음 브라우저 도구를 사용할 때 전용 Firecrawl 세션을 생성하고 이후 호출에서는 살아 있는 세션을 재사용한다. 호출 예제는 memory에 thread: 'ops-alice'와 resource: 'alice'를 전달하며, 서로 다른 thread id를 쓰는 두 사용자는 별도 로그인과 장바구니를 가진 격리된 브라우저를 받는다. 반대로 thread id를 생략하면 모든 호출자가 하나의 기본 세션과 로그인을 공유하고, 의도적으로 전체가 한 브라우저를 쓰려면 scope: 'shared'로 시작 시 생성한 세션을 닫힐 때까지 공유할 수 있다. Firecrawl은 전체 수명인 ttl이 지나거나 유휴 시간인 activityTtl이 지나면 세션을 종료하며, ttl은 기본 600초·최대 3600초이고 activityTtl은 기본 300초다. 따라서 점심 이후 돌아온 thread는 쿠키 없는 새 세션을 받을 수 있고, 별도 프로필이 없다면 다시 로그인해야 한다. thread의 브라우저를 닫을 때는 해당 원격 세션도 삭제된다.
5. 이름 있는 프로필로 실행 간 로그인 유지
thread가 한 실행 안에서 브라우저를 분리한다면, 실행을 넘어 로그인 상태를 이어 가는 역할은 이름 있는 Firecrawl 프로필이 담당한다. 예제는 firecrawl 아래 profile에 name: 'swag-labs-ops'와 saveChanges: true를 넣고 ttl: 600, activityTtl: 120을 설정한다. saveChanges: true는 세션이 닫힐 때 쿠키와 로그인 상태를 프로필에 기록하므로, 다음에 같은 프로필로 연 세션은 로그인된 상태에서 /inventory.html로 바로 이동할 수 있다. 상태 저장은 세션 종료 시 이루어지기 때문에 최초 로그인 작업은 에이전트의 browser_close 또는 코드의 browser.closeThreadSession(threadId) 호출로 브라우저를 닫아 마무리해야 한다. 설정 위치도 구별해야 하는데, 최상위 profile은 AgentBrowser에서 온 로컬 Playwright 사용자 데이터 디렉터리이고 firecrawl.profile은 Firecrawl 측에 저장되는 원격 브라우저용 프로필이다.
6. 프로필 저장 충돌과 계정 공유 범위
같은 Firecrawl 프로필에 상태를 저장할 수 있는 세션은 한 번에 하나뿐이며, 두 번째 세션이 saveChanges: true로 같은 프로필을 열면 세션 또는 프로필 상태와 충돌한다는 409 오류가 발생한다. scope: 'thread'에서 여러 thread가 동시에 실행될 수 있으므로, 각 thread가 같은 프로필에 저장하도록 설정하면 이 제약에 부딪힌다. 글은 최초 로그인 한 번만 saveChanges: true로 수행해 상태를 저장하고, 이후 일반 트래픽은 saveChanges: false로 실행하는 방법을 제시한다. 이 방식에서는 각 thread가 저장된 로그인을 읽어 시작하면서도 프로필 저장 권한을 두고 충돌하지 않는다. 다만 swag-labs-ops를 여는 모든 thread는 동일한 계정으로 로그인하므로 공유 운영 계정에는 적합하지만, 포털 계정이 사용자마다 다르면 portal-${userId}처럼 사용자별 프로필을 만들고 각각 최초 로그인을 수행해야 한다.
7. 비밀번호 보호와 페이지 내용 전달의 경계
글에 나온 standard_user와 secret_sauce는 Sauce Labs가 자체 로그인 페이지에 공개한 데모 자격 증명이며, 실제 포털에서는 자격 증명을 프롬프트에 넣지 말고 저장된 프로필을 사용하라고 설명한다. 사람이나 초기 설정 스크립트가 프로필을 저장할 세션에 비밀번호를 한 번 입력하고, 이후 에이전트는 해당 프로필만 열도록 구성하는 방식이다. 이 구성에서는 비밀번호가 모델이나 트레이스, Memory에 전달되지 않으므로 에이전트의 대화 입력에 비밀번호를 포함하지 않고도 로그인 상태를 재사용할 수 있다. 그러나 로그인 뒤 에이전트가 읽는 페이지 내용은 다른 도구 출력과 마찬가지로 모델과 트레이스에 전달된다는 제한을 명시한다. 따라서 프로필이 제공하는 보호 범위는 비밀번호를 프롬프트와 모델 입력에서 제외하는 데 있으며, 로그인 페이지에서 읽은 내용까지 전달되지 않는다는 뜻으로 확대해서는 안 된다.
8. 설치·저장소 연결과 실행 종료 처리
Firecrawl 팀이 만든 이 제공자는 Mastra 모노레포에 있으며, 설치 명령에는 @mastra/core, @mastra/memory, @mastra/libsql, @mastra/browser-firecrawl과 [email protected]이 포함된다. FIRECRAWL_API_KEY를 설정하고 예제의 openai/... 모델을 쓴다면 OPENAI_API_KEY를, 다른 제공자를 선택한다면 해당 제공자의 키를 준비한다. Memory에는 Mastra 인스턴스의 저장소 제공자가 필요하며 create-mastra로 생성한 프로젝트에는 이미 포함되어 있지만, 그렇지 않은 경우 예제처럼 LibSQLStore를 file:./mastra.db에 연결해 에이전트를 등록한다. 실행 예제는 ops-alice thread로 요청을 보낸 뒤 try/finally의 finally에서 closeThreadSession을 호출해 세션이 TTL까지 열린 채 남지 않도록 한다. 운영 시에는 thread당 요청을 한 번에 하나씩 보내야 하며, 공개 페이지도 필요하면 같은 Firecrawl 키로 Search와 Scrape를 이용할 수 있다. 글은 전체 옵션, 제공자와 스크린캐스트, 세션과 프로필에 관한 추가 설명을 각각 관련 참조 문서에서 확인하도록 안내한다.
🧾 핵심 주장 / 시사점
- 원격 브라우저는 로컬 Chromium 관리 부담을 줄이지만, 세션 수명과 종료 처리는 여전히 필요하다. 특히 프로필 저장이 세션 종료 시 이루어지므로 브라우저 닫기는 자원 정리와 로그인 상태 보존을 함께 좌우한다.
- 브라우저 세션의 격리와 로그인 계정의 격리는 별개다. 서로 다른 thread id로 브라우저를 나누더라도 같은 Firecrawl 프로필을 사용하면 같은 계정으로 접근하므로, 사용자별 계정 요구는 프로필 구성에 반영해야 한다.
- 스냅샷을 반복해 읽는 방식은 변경된 요소 참조와 실제 페이지 상태를 확인하는 근거가 되지만 실행 단계도 늘린다. 약 25단계가 필요한 예제는 Mastra의 기본 5단계 한도를 작업 흐름에 맞게 조정해야 하는 이유를 보여 준다.
✅ 액션 아이템
- 로그인·폼 입력·클릭이 필요한 작업에 FirecrawlBrowser를 적용하고, 매 행동 후 browser_snapshot 확인과 작업에 맞는 maxSteps 설정을 반영한다.
- 호출마다 thread id를 지정하고, 사용자별 계정에는 사용자별 Firecrawl 프로필을 연결하며, 최초 로그인은 saveChanges: true로 저장한 뒤 일반 실행은 saveChanges: false로 운영한다.
- 저장된 프로필로 비밀번호의 모델·트레이스·메모리 전달을 피하고, 로그인 페이지 내용의 전달 범위를 확인하며, thread당 요청을 하나씩 보내고 작업 후 브라우저 세션을 닫는다.
❓ 열린 질문
- 적용할 작업은 공개 페이지의 Search·Scrape로 충분한가, 아니면 로그인·폼 입력·클릭을 위해 FirecrawlBrowser가 필요한가?
- Firecrawl 프로필은 공유 계정으로 사용할 것인가, 사용자별 계정에 맞춰 사용자별 프로필로 구성할 것인가?
- 로그인 페이지 내용이 모델과 트레이스에 전달되는 범위는 해당 작업의 데이터 처리 요구에 부합하는가?