개발자
WebSocket
API·프로토콜·규칙
온투코웍스의 백엔드는 REST + WebSocket 하나의 API 위에 있습니다. 콘솔이 쓰는 것과 같은 API입니다.
기본 주소 —
https://app.ontocoworks.com/api · 인증은 세션 쿠키(cs_sid, HttpOnly) · 실시간은 wss://app.ontocoworks.com/ws · 모든 응답은 JSON, 오류는 { "error": "code", "message": "…" }1. 인증
| 메서드·경로 | 본문 | 설명 |
|---|---|---|
POST /auth/signup | name, email, password(8자+숫자), ref?, agreeTerms, agreePrivacy | 201. 개인 조직·'나의 방'·비서 자동 생성, 웰컴 캐시. 속도제한 20/시 |
POST /auth/login · /logout | email, password | 세션 쿠키 발급·폐기. 로그인 10/5분(IP+이메일) |
GET /auth/me | 사용자·소속 조직(역할·캐시 잔액)·추천 코드 | |
POST /auth/password/forgot · /reset | email / token, password | 30분 토큰, 재설정 메일 발송 |
POST /auth/verify-email · /verify-email/resend | code(6자리) | 가입 이메일 인증(10분·5회·재발송 30초). GET /auth/me의 user.emailVerified |
GET /auth/google | 구글 OAuth(설정 전 503) |
2. 조직·멤버·초대·캐시
| 메서드·경로 | 권한 | 설명 |
|---|---|---|
POST /orgs · GET /orgs · GET /orgs/:id | 로그인 | 팀 조직 생성 시 스페이스 '일반'·방 '전체' 자동 |
GET /orgs/:id/members · PATCH|DELETE /orgs/:id/members/:userId | member / admin+ | 역할 owner > admin > member > guest. admin 부여는 owner만 |
POST|GET /orgs/:id/invites · GET /invites/:code · POST /invites/:code/accept | admin+ / 공개 / 로그인 | 1회용·다회·이메일 지정·만료. 이메일 지정 시 초대 메일 발송, 응답 mailed |
GET /orgs/:id/cash · POST /orgs/:id/cash/topup-requests · POST …/:rid/decide | member / admin+ / owner | 잔액·원장 / 충전 요청 / 승인·집행(집행 시에만 원장 charge) |
GET /orgs/:id/audit · GET /orgs/:id/usage | admin+ | 통합 행동 로그 / 에이전트·모델·일별 사용량 |
3. 방·메시지·실시간
| 메서드·경로 | 설명 |
|---|---|
GET|POST /orgs/:id/rooms | 스페이스·내 방(안 읽음 수) / 방 생성(channel·dm·group, 초기 멤버) |
GET /rooms/:rid · POST /rooms/:rid/members · DELETE /rooms/:rid/members/:type/:id | 멤버는 사람·에이전트 한 표. 에이전트는 replyPolicy mention|always|never |
GET /rooms/:rid/messages?after=|before=&limit= · POST /rooms/:rid/messages · POST /rooms/:rid/read | 방별 seq 커서. 본문 최대 20,000자 |
WebSocket /ws
// 연결: 같은 쿠키(cs_sid). 무인증·변조 시 401
← {"t":"hello","user":{"id":"…","name":"…"}}
→ {"t":"sub","room":"<roomId>"} // 멤버만. 아니면 {"t":"error","code":"not_room_member"}
← {"t":"subbed","room":"…"}
← {"t":"msg","room":"…","message":{seq, author_type:"user|agent|system", body, meta, …}}
→ {"t":"unsub","room":"…"} · → {"t":"ping"} ← {"t":"pong"}
// 서버가 25초마다 ping 프레임을 보냅니다(프록시 유휴 타임아웃 방지). 끊기면 재접속 후 after=seq 로 갭을 채웁니다.
4. 에이전트
| 메서드·경로 | 설명 |
|---|---|
GET|POST /orgs/:id/agents · PATCH|DELETE /orgs/:id/agents/:aid | name, handle(영소문자·숫자·_), persona, model, permLevel 1~3, maxTokens, status. 삭제=휴지통 |
PUT|GET /orgs/:id/secrets · DELETE /orgs/:id/secrets/:name | 금고(openrouter|anthropic|openai). 쓰기 전용, 목록은 힌트만, 삭제는 owner |
GET /orgs/:id/approvals · POST …/:apid/decide | 승인 게이트 목록·결정 |
발화 규칙 v1
@handle또는@이름지목 → 지목된 에이전트 전원 응답- 방 멤버십
replyPolicy=always→ 1명 응답 - 1:1 방(사람 1 + 에이전트 1) → 지목 없이 응답
- 그 외 침묵.
never·정지·삭제된 에이전트는 어떤 경우에도 침묵
컨텍스트는 방 최근 20건을 정본에서 매번 읽습니다(뇌에 원문 복사 없음). 답글 meta: {trigger, model, provider, key_source, input_tokens, output_tokens, cost_krw, latency_ms}.
5. 캐시 정산 공식
cost_krw = ceil( usage.cost_usd × USD_KRW(1,400) × MODEL_MARGIN(1.3) )
key_source = 'org' → cost_krw = 0 (조직 자체 키, BYOK)
key_source = 'platform' → cash_ledger 에 debit(-cost_krw, ref_type='model_usage')
잔액 ≤ 0 → 응답 대신 시스템 안내(정지). 충전: requested → approved(owner) → executed(owner, 원장 charge)
6. 앱 매니페스트(개요)
앱은 iframe 표면 + 매니페스트 + postMessage로 붙습니다. 매니페스트는 이름·아이콘·진입 URL·provides/consumes 액션·필요 권한·설정 페이지를 선언하고, 방에서 /명령과 #참조로 호출됩니다. 앱 간 연동은 액션 버스를 통해 이루어집니다. 상세 표준(SDK·서명·심사)은 공개 출시와 함께 게시합니다.
7. 측정 방법
- 응답 지연 2.3초: 2026-09-02, 실서버(chatbot.futureinfra.app), 개인 조직 '나의 방'에서 비서에게 "한 문장으로 자기소개" — 사용자 메시지 201 응답부터 에이전트 답글 WebSocket 수신까지. 모델 anthropic/claude-sonnet-5, 327+48 토큰, 차감 ₩3.
- 적대적 검수 105/105: 같은 날, 실서버, 스크립트
test/adversarial.ts. 범위는 §8. - 자동 재기동 5초: api·agent-runtime 프로세스
kill -9후 systemd 재기동 → /health 200까지.
8. 검수 범위(2026-09-02)
- 입력 검증·가입·세션 변조·쿠키 플래그·로그인 열거 방지·속도제한(429)
- 권한 경계: 비멤버 404(존재 비노출), member/admin/owner 계층, 개인 조직·소유자 보호, IDOR(타 조직 방·에이전트·충전)
- 초대(1회용·이메일 지정·경로 조작), 캐시 무결성(최소·음수·소수·승인 순서·이중 집행·원장 합계)
- 메시지(빈/2만자/SQL 메타·동시 8건 seq 고유), 에이전트(핸들·중복·타 조직·프롬프트 주입=키 미노출·집행 거절)
- WebSocket(무인증·변조·비멤버·깨진 프레임·비UUID·미지 op), 금고(값 미노출·owner만 삭제), 프록시(XFF 위조 무효·26MB 413), 정적 8표면
- 복원력: Redis 정지 중 쓰기 201·health 200, 재개 후 팬아웃·에이전트 디스패치 복구, kill -9 자동 재기동