Personal Knowledge Agent 생성기

소개

금번 22기 스타트업실험실을 하면서 AI OS 만들기에서 저만의 Personal Knowledge Agent를 만들고
있었습니다.

지난 시간 작동 절차까지 구현을 했었는데요. 구동 페이지부터 자료수집까지 구현한 내용을 써봅니다.

진행 방법

이번에는 주로 codex 5.5를 사용하여 작업하였습니다.

이 작업 자체는가 원래 단순한 수집이 아닌 사용자의 요청을 이해하고 기존 지식 파이프라인을 도구처럼 사용하는 Personal Knowledge Agent를 만드는 것이었습니다.

구조는 아래와 같습니다.

사용자 요청
  -> Agent Orchestrator
  -> 계획 수립
  -> 도구 선택
  -> 실행
  -> 결과 검증
  -> 승인 요청
  -> 기존 Knowledge Pipeline

이 작업에 있어 중요원칙은 안전한 반자율 에이전트 였습니다.(저는 승인을 하는 방향을 선호합니다)

- 읽기, 검색, 분석은 자동 실행 가능
- raw capture 저장은 자동 실행 가능
- 정제안 생성은 자동 실행 가능
- 최종 Obsidian 구조화 노트 반영은 승인 필요
- 삭제, 덮어쓰기, 구조 변경은 금지 또는 명시 승인 필요
- 원본 자료는 삭제하지 않음
- 개인정보나 개인 자료를 외부로 무단 노출하지 않음

Agent System Prompt는 다음과 같습니다.

논리적이고 이성적인 개인 지식 사서.
원본 삭제 금지.
승인 없이 vault 구조 변경 금지.
승인 없이 Obsidian write 금지.
개인정보 외부 노출 금지.
정제, 분류, 연결은 근거와 함께 수행.

작업 자체가 로컬보다는 주로 사용하는 메모앱들도 있어서 랜딩 페이지를 구현하는 방향으로 작업이 되었습니다.
초기 화면은 좀 직관적이지 않아서 UI/UX를 많이 개선하였고, 에이전트 실행 및 자료 수집 경로를 넣도록 했습니다.

- 로컬 폴더
- UpNote Export
- Notion 페이지
- Notion 데이터소스
- 승인 대기열
- 문서 검색
- 운영 현황

Agent를 구축하랬더니 명령어가 좀 많이 복잡해서 명령도 줄여달라고 했다.

make app을 치거나
/pkm을 치면
백엔드 및 프론트 엔드가 돌아가고 페이지가 뜬다.

Agent Layer는 다음과 같이 구현해줬다.

- `backend/app/services/agent.py`
- `backend/app/api/routes/agent.py`
- `backend/app/schemas/agent.py`
- `backend/app/main.py`
- `backend/tests/test_agent_orchestrator.py`
- `frontend/src/features/agent/AgentPage.tsx`
- `frontend/src/tests/AgentPage.test.tsx`

실제 구동을 하면 Agent는 다음과 같은 도구들을 호출하여 작업을 수행한다.

### search_knowledge

기존 지식 검색.

예시:

```text
agent memory 찾아줘
```

### find_related_notes

특정 문서의 관련 노트 검색. 현재는 context에 `document_id`가 필요하다.

### ingest_web_page

공개 웹 URL을 읽어 raw capture로 저장한다.

예시:

```text
https://example.com 페이지 읽어봐
```

보안 정책:

- localhost 차단
- private IP 차단
- `.local` 차단
- http/https 외 scheme 차단

### ingest_local_folder

일반 로컬 폴더를 수집한다.

예시:

```text
/Users/educalvin7/Documents/notes 폴더 수집해
```

저장 위치:

```text
00_inbox/raw/local_folder/
```

Vault 내부 폴더를 다시 수집하는 것은 차단한다.

### ingest_upnote_export

UpNote export 폴더를 수집한다.

예시:

```text
UpNote export /Users/educalvin7/Downloads/UpNote Export 수집해
```

터미널식 백슬래시 경로도 처리한다.

```text
UpNote export /Users/educalvin7/Downloads/UpNote\ Export 수집해
```

저장 위치:

```text
00_inbox/raw/upnote_export/
```

### ingest_notion_page

Notion 페이지를 수집한다.

예시:

```text
Notion 페이지 https://www.notion.so/... 수집해
```

또는:

```text
Notion 페이지 0123456789abcdef0123456789abcdef 수집해
```

Notion URL 전체를 넣어도 내부에서 32자리 page ID만 추출한다.

### ingest_notion_data_source

Notion 데이터소스 또는 데이터베이스를 수집한다.

예시:

```text
Notion 데이터소스 0123456789abcdef0123456789abcdef 5개 수집해
```

제한 개수는 `5개`, `5건`, `5 pages` 같은 표현에서 읽는다. 숫자가 없으면 기본 20개다. 최대 100개로 제한한다.

### draft_refinement

승인 대기 중인 정제안을 만들거나 조회한다. 실제 구조화 노트 반영은 하지 않는다.

### list_pending_proposals

승인 대기 중인 제안 목록을 조회한다.

### request_approval

삭제, 덮어쓰기, 승인 적용, 구조 변경 등 위험 요청을 막고 승인 필요로 돌린다.

여기서 핵심은 자동화이되 반드시 승인없이는 자료 및 생성되는 자료의 수정을 임의로 하지 않는 것이다.

다음은 실제로 구동하면 뜨는 웹 화면이다.

한국어 웹사이트의 스크린샷
한국어 웹사이트 스크린샷

각 경로를 설정하고 에이전트 실행을 하면 자료를 수집한다.
(다만 아직 더 손을 봐야할 것 같다.)
특히, 노션 page ID와 개발자 포털에서 token key를 받아 연동해야하는게 있어서 금번에 세팅을 했다.
그런 조금의 번거로움을 거치니 수집이 되는 것을 확인하였다.

결과와 배운 점

금번 작업을 하면서 배운 점은

에이전트는 “그럴듯한 답변”을 하면 안 된다.  
에이전트는 어떤 도구를 호출했는지, 무엇을 저장했는지, 승인이 필요한지, 실패했다면 왜 실패했는지를 증거로 남겨야 한다.

그래서 앞으로의 기준은 다음을 설정하고 업그레이드 더 해야겠다.

말만 완료 금지.
tool action 없는 완료 금지.
저장 결과 없는 수집 완료 금지.
검증 없는 성공 주장 금지.

도움 받은 글 (옵션)

22기 스타트업실험실 사례글들과 스터디장님들의 도움

1
2개의 답글

뉴스레터 무료 구독