Matrix
Client-Server API를 통한 페더레이션 Matrix 프로토콜. 인바운드는 롱 폴링 데몬으로 동작하며, HTTP webhook 진입점은 없습니다.
🟡 아웃바운드 준비 완료, 인바운드는 롱 폴링 데몬으로 동작합니다. Matrix는 페더레이션 구조이므로 단일 webhook URL이 존재하지 않습니다. Minara는
/sync데몬을 실행하여 이벤트를 Agent로 스트리밍합니다. 일반 텍스트 룸만 지원하며, 종단간 암호화 (E2EE) 룸은 이 버전에서 지원되지 않습니다.
제공 기능
- 아웃바운드 텍스트: Client-Server API를 통해 전송합니다.
PUT /_matrix/client/v3/rooms/{roomId}/send/m.room.message/{txnId}요청에Authorization: Bearer <access_token>과{msgtype:"m.text", body}를 포함합니다. - 인바운드: 롱 폴링 데몬.
MESSAGING_MATRIX_INBOUND=1로 설정하면 Minara는GET /sync?since=<batch>&timeout=30000루프를 시작합니다. 이벤트는MATRIX_DEFAULT_ROOM_ID에 해당하는 룸의 메시지만 필터링됩니다. (codex-round-1 보안 수정 사항으로, 데몬은 참여한 모든 룸에서 이벤트를 emit하지 않습니다.) - 커서 디스크 저장.
<dataDir>/matrix-sync.json에 커서를 저장하므로, 재시작 시 기존 히스토리를 재생하지 않고 마지막next_batch부터 재개합니다. - 텍스트 전용. 이미지 및 파일 이벤트는 무시됩니다.
- 텍스트 길이 제한: 65,000자 (Matrix 자체 상한선).
설정
1. Matrix 계정 생성 또는 준비
matrix.org, 자체 Synapse, Dendrite 등 어떤 homeserver든 사용할 수 있습니다. Matrix 클라이언트(Element, Cinny 등)로 한 번 로그인합니다.
2. 장기 유효 access token 발급
Element에서 복사하는 방법이 가장 간단합니다.
- Element 데스크톱 또는 웹: 설정 → 도움말 및 정보 → Access Token ("Advanced" 항목 아래에 숨겨져 있으며, 펼쳐서 확인합니다.)
- 또는 curl을 사용합니다.
응답으로curl -X POST -H 'Content-Type: application/json' \ -d '{"type":"m.login.password","user":"@bot:example.org","password":"..."}' \ https://matrix.example.org/_matrix/client/v3/login{access_token, user_id, ...}가 반환됩니다.
다음 값을 저장합니다.
MATRIX_HOMESERVER(URL, 예:https://matrix.org)MATRIX_ACCESS_TOKEN(bearer 토큰)MATRIX_USER_ID(예:@bot:matrix.org)
3. 대상 룸 참여
봇 계정으로 Agent가 모니터링할 룸에 참여합니다.
룸 ID를 확인합니다. (Element: 룸 → 설정 → 고급 → "Internal room ID")
!abc:matrix.org 형식으로 표시됩니다. 이 값을 MATRIX_DEFAULT_ROOM_ID로 저장합니다.
4. Minara 설정
minara auth messaging add
# 목록에서 `matrix`를 선택하고 homeserver URL, access token,
# user id, default room id를 입력합니다.또는 환경 변수를 직접 설정합니다.
MATRIX_HOMESERVER=https://matrix.org
MATRIX_ACCESS_TOKEN=syt_...
MATRIX_USER_ID=@bot:matrix.org
MATRIX_DEFAULT_ROOM_ID=!abc:matrix.org5. 인바운드 활성화 (선택 사항)
MESSAGING_MATRIX_INBOUND=1이 값을 설정하면 Agent 시작 시 롱 폴링 데몬이 함께 실행됩니다. 이 플래그가 없으면 Matrix는 푸시 전용으로 동작합니다.
6. 테스트
minara auth messaging test matrix/sync 동작 방식 (롱 폴링 데몬)
데몬은 백그라운드에서 실행되며, homeserver에 대해 롱 폴링 요청을 반복합니다.
GET /sync?timeout=30000&since=<next_batch>&filter={"room":{"timeline":{"types":["m.room.message"]}}}homeserver는 새 이벤트가 도착하거나 30초 타임아웃이 만료될 때까지 연결을 유지한 후, 이벤트와 새로운 next_batch 커서를 반환합니다.
세 가지 안전 장치가 적용됩니다.
-
첫 번째 sync에서 히스토리를 버립니다. 신규 설치 시 커서가 없으므로
/sync는 룸의 전체 타임라인을 반환합니다. 데몬은 이 초기 배치를 버리고next_batch토큰만 저장합니다. 이를 통해 첫 실행 시 오래된 메시지가 재생되는 것을 방지합니다. -
룸 범위 필터.
MATRIX_DEFAULT_ROOM_ID에 해당하는 룸의 이벤트만 Agent에 전달됩니다. 이 필터가 없으면 봇이 참여한 모든 룸에서 응답이 트리거될 수 있어, 공유 공간에서 개인정보 및 범위 문제가 발생할 수 있습니다. -
자기 루프 방지.
sender === MATRIX_USER_ID인 이벤트는 필터링됩니다. 봇이 발송한 메시지가/sync를 통해 라운드트립하더라도 인바운드 트리거가 되지 않습니다.
재연결: 데몬은 네트워크 오류 발생 시 공유
daemon-runner를 통해 지터가 포함된 지수 백오프(1초 → 30초)를 사용합니다.
제한 사항 및 주의 사항
- 종단간 암호화 미지원. 데몬은
m.room.encrypted이벤트를 무시합니다. 일반 텍스트 룸만 사용하십시오. olm / matrix-rust-sdk를 활용한 E2EE 지원은 대규모 작업이 필요한 향후 과제입니다. - 페더레이션 핸드셰이크 없음. 봇은 Matrix 클라이언트로 동작하므로, 참여하지 않은 룸의 이벤트는 수신할 수 없습니다.
- Bearer는 헤더로 전달. Matrix의
?access_token=쿼리 방식은 더 이상 사용되지 않습니다. Minara는Authorization: Bearer를 사용합니다. - 대역폭. 롱 폴링은 24시간 HTTP 연결을 유지합니다. 대부분의 homeserver에서는 문제가 없지만, 방화벽 및 로드 밸런서 설정에서 유휴 연결이 약 60초 이내에 끊기지 않도록 주의하십시오.
문제 해결
"데몬이 시작되지 않음"
MESSAGING_MATRIX_INBOUND가 설정되지 않은 경우입니다.1로 설정한 후 재시작합니다.
"데몬에서 이벤트가 수신되지 않음"
- 봇이
MATRIX_DEFAULT_ROOM_ID룸에 참여하지 않은 경우입니다. Element에서 확인하거나GET /joined_rooms로 재확인합니다. - 해당 룸이 암호화되어 있는 경우입니다. 일반 텍스트 룸만 사용하십시오.
"시작 시 오래된 메시지가 모두 재생됨"
<dataDir>/matrix-sync.json이 없거나next_batch가 null인 경우입니다. 데몬을 중지하고 파일을 삭제한 후 재시작합니다. 삭제 후 첫 번째 sync에서 히스토리가 올바르게 버려집니다.
"아웃바운드에서 401 오류 (M_UNKNOWN_TOKEN)"
- access token이 만료되었거나 취소된 경우입니다. 위의 로그인 절차에 따라 새 토큰을 발급합니다.
참조
- 환경 변수:
MATRIX_*,MESSAGING_MATRIX_INBOUND - 아웃바운드:
apps/agent/src/messaging/matrix.ts - 인바운드 데몬:
apps/agent/src/messaging/inbound/matrix-daemon.ts - 데몬 러너:
apps/agent/src/messaging/inbound/daemon-runner.ts - Client-Server API 사양: spec.matrix.org / latest / client-server-api