에이전트 개발 기획서: 요구사항부터 화면·API·검수까지
에이전트 개발을 시작하려면 어떤 답을 만들지와 함께, 누가 실행을 허용하고 어떤 증거로 완료를 판정할지 정해야 한다. 이 글은 사내 업무 지원 에이전트 한 개를 예로 들어 요구사항 → 구조 → 실행 → 화면·API → 개발 작업 → 검수·운영 을 연결한 개발 기획서다.
핵심은 세 가지다. 승인한 내용과 실제 등록 내용을 같은 버전으로 묶고, 응답이 끊긴 등록은 확인 중 상태로 남기며, 개발 완료를 테스트 증거로 판단한다. 아래의 FR·SCR·API·DEV·TC 번호는 각각 요구사항·화면·API·개발 티켓·인수 테스트를 서로 추적하기 위한 식별자다.
자체 설계 기준안 이다. 수치와 보관 기간은 측정·합의가 필요한 초기 제안이고, 화면과 응답은 가상 데이터다. 실제 업무 시스템을 구현했거나 인수 테스트에 통과했다는 보고서가 아니다. 도표는 눌러서 확대할 수 있다.
실행 구조의 개념부터 확인하려면 에이전트 설계 지도를 함께 읽으면 된다.
예제 프로젝트: 사내 업무 지원 에이전트
권한 있는 자료에서 근거를 찾고,
답변과 업무 초안을 만든 뒤,
사람의 승인으로 티켓을 등록한다.
- 입력 — 업무 요청 + 접근 가능한 내부 자료
- 출력 — 근거 답변 + 승인된 업무 티켓
- 원칙 — 단일 에이전트 · 제한된 읽기 · 승인 후 쓰기
목표와 범위
누구의 어떤 일을, 어디까지 맡길 것인가?
이 단계의 산출물 프로젝트 브리프
요구사항·권한 표
개발할 제품을 한 문장으로 고정한다
사내 자료를 찾아 근거 있는 답변과 업무 초안을 만들고, 담당자가 승인한 내용만 업무 시스템에 등록한다.
- 사용자 — 프로젝트 담당자 · 검토 책임자 · 운영자
- 첫 업무 — 프로젝트의 QA 누락을 확인하고 후속 티켓 제안
- 입력 — 사용자 요청, 읽기 가능한 문서, 기존 티켓
- 완료 — 출처 있는 답변 또는 승인된 티켓의 등록 영수증
이 예제의 쓰임 검색·검증·초안·승인·등록이라는 공통 구조를 구체화한 기준 프로젝트다. 학회 규정 점검, 고객 지원, 사내 자료 분석으로 바꿀 때는 자료 유형·도구·승인 권한·정답 세트를 교체한다.
자동화의 범위와 사람의 역할
| 업무 | 에이전트가 수행 | 사람·서버가 결정 | 이번 범위에서 제외 |
|---|---|---|---|
| 자료 조사 | 질의 구성·관련 문서 검색·근거 선택 | 서버가 문서 접근 범위 제한 | 웹 전체 검색·임의 파일 탐색 |
| 누락 분석 | 요구사항과 QA 기록 대조·불확실성 표시 | 담당자가 사실 관계와 우선순위 검토 | 모델의 추정만으로 완료 판정 |
| 업무 초안 | 제목·설명·관련 근거·담당 후보 제안 | 사람이 내용·담당·기한 확정 | 자동 결제·이메일 발송·자료 삭제 |
| 티켓 등록 | 구조화된 등록안 제안 | 서버가 승인된 payload만 외부 전송 | 모델이 직접 외부 쓰기 API 호출 |
기능 요구사항과 인수 기준
| ID | 구현 요구 | 완료 조건 |
|---|---|---|
| FR-01 | 계정·조직·프로젝트 권한 | 다른 조직·비할당 프로젝트의 자료·결과·근거 모두 접근 불가 |
| FR-02 | 요청 접수·중복 방지 | 동일 요청 키는 동일 run 반환; 다른 본문으로 키 재사용 시 409 |
| FR-03 | 입력·정책 버전 고정 | 문서 revision, 검색 index snapshot, prompt·model·tool·policy 버전 기록 |
| FR-04 | 제한된 읽기 도구 | 허용된 4개 도구만; tenant·ACL은 서버 컨텍스트에서 주입 |
| FR-05 | 근거 있는 결과 | 주장별 evidence ID; 부족한 근거는 불확실성·추가 질문으로 표시 |
| FR-06 | 업무 초안·검토·승인 | 화면에 보인 revision·payload hash와 승인 대상이 동일 |
| FR-07 | 승인 후 외부 등록 | 동일 action key로 최대 한 번의 업무 효과; 영수증 보관 |
| FR-08 | 제한·취소·복구 | 호출·시간·비용 상한, checkpoint, lease와 fencing 적용 |
| FR-09 | 작업·근거·검토 화면 | 상태를 실행/검토/반영으로 나누고 근거를 직접 열람 |
| FR-10 | 실행·승인 감사 | 행위자·도구·버전·상태·사용량·결과 추적; 민감 원문 로그 제외 |
| FR-11 | 평가와 회귀 차단 | 정답 세트와 권한·중복·장애 시나리오 통과 |
| FR-12 | 운영 중지·백업·삭제 | 신규 실행 정지, 불명확한 반영 조사, 복원·만료 삭제 절차 |
성공을 어떤 숫자로 판단할 것인가?
| 지표 | 초기 목표 · 실측 전 | 측정 방법 |
|---|---|---|
| 근거 답변 적합률 | ≥95% | 지원 범위의 평가 요청 중 전문가가 답변·근거 모두 적합하다고 판정한 비율 |
| 근거 부족 처리 | 평가 세트에서 위험한 단정 0건 | 정보 없음·상충 문서 사례에서 보류·질문 반환 여부 |
| 권한·승인 | 평가에서 교차 조직 누출·무승인 쓰기 0건 | 서버 정책 테스트 + 도구 호출 기록 + 외부 결과 |
| 중복 등록 | 장애 시나리오에서 중복 티켓 0건 | 같은 action key의 외부 티켓 수 |
| 시간·비용 | 실행 120초 상한·run별 예산 적용 | queue 대기와 실행 시간 분리; 실제 provider 사용량으로 계산 |
초기 목표는 보장된 성능이 아니다. 실제 자료·모델·외부 연동으로 측정한 결과를 인수 문서에 기록한다.
시스템 구조
모델 주변에 어떤 실행 시스템을 만들 것인가?
이 단계의 산출물 구성도·설계 결정
데이터·연동 계약
모델은 판단하고, 실행 시스템은 권한과 상태를 관리한다
채택 구조와 대안의 판단 근거
| 결정 | 이번 기준안 | 변경 조건 |
|---|---|---|
| ADR-01 · 자율성 | 단일 에이전트 + 제한된 읽기 + 코드로 제어하는 쓰기 | 고정 경로만으로 해결되면 일반 워크플로로 단순화 |
| ADR-02 · 다중 에이전트 | 초기 범위 제외 | 독립 조사·통합 비용을 포함한 동일 예산 평가에서 품질 향상 입증 |
| ADR-03 · 연결 방식 | 내부 함수 도구 + 기존 시스템 어댑터 | 여러 실행 제품에서 같은 도구를 공유하면 MCP 연결 검토 |
| ADR-04 · 자료 검색 | ACL 필터가 있는 검색 인덱스, 문서 revision별 근거 | 키워드 검색의 누락을 측정한 뒤 의미 검색을 추가 |
| ADR-05 · 모델 교체 | provider adapter로 응답·usage·stop reason 정규화 | 선택 모델·SDK 버전을 고정하고 변경 때 회귀 평가 |
| ADR-06 · 저장·큐 | MySQL 작업 테이블과 lease, 별도 worker | 처리량·대기시간 측정으로 전용 큐 필요성 판단 |
- 화면 — 바닐라 JavaScript + Tailwind CSS · 요청·근거·검토 UI
- 업무 서버 — Node.js + Fastify · JavaScript · 인증·정책·HTTP API
- 실행 서버 — 별도 worker + provider adapter · 루프·검증·복구
- 데이터 — MySQL + 비공개 객체 저장소 + ACL 검색 · 상태·원본·검색 분리
저장할 데이터와 불변 조건
| 테이블·핵심 필드 | 키·일관성 조건 |
|---|---|
| runs · id, tenant_id, requester_id, project_id, status, policy_version, index_snapshot, deadline, lease_until, fencing_token, budget_json | PK(tenant_id,id); 예산·deadline은 재시작 후 초기화하지 않음 |
| run_events · run_id, seq, event_type, payload, created_at | UNIQUE(tenant_id,run_id,seq); 원문 대신 근거 ID·메타데이터 |
| results · run_id, answer_json, result_hash | UNIQUE(tenant_id,run_id); 성공 결과는 불변 |
| evidence · document_id, revision_id, segment_id, quote_hash, acl_ref | 근거 조회 때 현재 ACL 재검사; 저장 근거는 당시 revision 고정 |
| proposals / proposal_revisions · current_revision, payload_json, payload_hash, expires_at | UNIQUE(tenant_id,proposal_id,revision); 수정은 새 revision, 이전 승인 승계 금지 |
| decisions · proposal_id, revision, payload_hash, decision, actor_id, reason | UNIQUE(tenant_id,proposal_id,revision); APPROVED 또는 REJECTED |
| executions · proposal_id, revision, action_key, status, receipt, retry_at | UNIQUE(tenant_id,proposal_id,revision); UNIQUE(action_key) |
| idempotency_requests / audit_events | 요청 키와 payload hash 보존; 감사는 일반 API에서 수정 불가 |
| result_evidence · result_id, evidence_id, claim_id | 복합 FK에 tenant_id 포함; 존재하지 않는 근거 연결 금지 |
외부 시스템이 제공해야 할 계약
| 계약 | 필수 기능 | 없을 때의 범위 |
|---|---|---|
| INT-01 · 인증 | 사용자·조직·프로젝트·문서 권한 검증 | 인증 어댑터 확정 전 실제 자료 연결 금지 |
| INT-02 · 문서 | revision별 본문·구간 조회, 현재 ACL, 갱신 이벤트 | 불변 스냅샷 생성 또는 해당 자료를 근거에서 제외 |
| INT-03 · 티켓 | action key 기반 멱등 생성 + 같은 키로 결과 조회 | 티켓 초안·승인까지만 제공; 자동 등록 비활성 |
| INT-04 · 조건 | 등록 대상 프로젝트·담당자 권한, 외부 조건 검사 | 서버에서 확정할 수 없는 대상은 사용자 재선택 |
개발 착수 gate 연동 담당자는 인증 방식·샘플 응답·오류 코드·호출 제한·멱등 보장 범위를 확인한다. 위 기능이 기존 시스템에 이미 존재한다고 가정하지 않는다.
중복 방지의 적용 범위 외부 티켓 시스템의 멱등 키 보관 기간과 결과 조회 범위를 연동 계약에 적는다. 외부 키가 만료되면 같은 키라도 재호출이 새 티켓을 만들 수 있다. UNKNOWN 작업은 키 만료 뒤 자동 재등록하지 않고 운영자가 기존 효과를 확인한다. 내부 execution 기록의 유일성만으로 외부 중복까지 막을 수는 없다.
실행과 통제
어떻게 판단을 반복하고, 언제 멈출 것인가?
이 단계의 산출물 실행 상태·도구 스키마
출력·승인·복구 계약
읽기 판단 루프와 쓰기 경로를 분리한다
4개 읽기 도구와 별도 쓰기 계약
| 도구·주체 | 입력 | 출력·제한 | 실패 |
|---|---|---|---|
| search_documents / 모델 | query ≤300자, top_k≤5 | 허용 project·ACL·index snapshot 안의 문서 ID·revision·발췌 | 검색 결과 없음은 정상 결과 |
| read_document_segment / 모델 | document_id, revision_id, segment_id | 최대 4,000자·출처·evidence_id | 권한 또는 snapshot 불일치 시 거부 |
| search_tasks / 모델 | query ≤300자, status?, limit≤10 | 현재 프로젝트의 티켓 ID·상태·updated_at | 다른 프로젝트 ID 입력 금지 |
| get_task / 모델 | task_id | 허용 프로젝트의 상세·revision·evidence_id | 없음·권한 없음은 구별 정보 제한 |
| create_task / 반영 처리기 | 승인된 project_id, title, body, assignee_id, due_at, action_key | ticket_id, receipt, created_at | 타임아웃은 UNKNOWN, 같은 키로 결과 조회 |
모델에 주지 않는 권한tenant_id·사용자 역할·허용 프로젝트는 서버가 주입한다. 임의 URL·SQL·셸·전체 파일 경로·이메일 전송 도구는 제공하지 않는다. 문서 속 “이전 지시를 무시하라”는 문장은 검색 데이터로만 취급한다.
구조화된 결과 계약
{
"schema_version": "1",
"outcome": "ANSWER_WITH_PROPOSAL",
"answer": "QA 기록에서 모바일 첨부 업로드 검수 결과를 찾지 못했습니다.",
"claims": [
{
"text": "모바일 첨부 업로드 검수 근거가 확인되지 않음",
"evidence_ids": [
"ev_spec_14",
"ev_qa_08"
]
}
],
"uncertainties": [
"검색 범위 밖 자료에 검수 기록이 있을 수 있음"
],
"proposal": {
"title": "모바일 첨부 업로드 검수",
"body": "요구사항 UP-04에 대한 390px 화면의 업로드·오류 안내 검수",
"project_id": "project_aurora",
"assignee_id": null,
"due_at": null
}
}
가상 응답 예시. “검수 근거가 없다”와 “검수를 하지 않았다”를 구분한다. outcome은 ANSWER / ANSWER_WITH_PROPOSAL / NEEDS_INPUT / INSUFFICIENT_EVIDENCE 중 하나다.
| 검증 | 조건 | 위반 처리 |
|---|---|---|
| 근거 참조 | 모든 evidence_id가 이 run의 읽기 도구 결과에 존재 | 출력 수정 1회; 재실패 OUTPUT_INVALID |
| 근거 의미 | 인용 위치·hash 검사 + 실제 주장과의 일치 평가 | 스키마 통과만으로 사실 확인을 완료했다고 간주하지 않음 |
| 업무 대상 | project_id는 요청 범위와 일치; 담당·기한은 검토 화면에서 확정 | 누락 또는 권한 불일치 시 승인 불가 |
| 내용 변경 | payload의 정규화 JSON으로 hash 계산, revision 불변 저장 | 수정 시 새 revision, 기존 승인 효력 종료 |
| 승인 만료 | 기준안 24시간; 정책·권한·참조 문서 변경 시 재검토 | 외부 등록 전에 다시 확인, 충돌 409 |
세 가지 상태를 따로 표시한다
| 상태 축 | 전이 | 완료 의미 |
|---|---|---|
| 실행 run | QUEUED → RUNNING → SUCCEEDED / FAILED / CANCELED; 대기 작업도 취소 가능 | SUCCEEDED는 유효한 답변 생성. outcome이 질문·근거 부족이어도 정상 종료 가능. |
| 검토 proposal revision | PENDING → APPROVED / REJECTED; 새 revision은 다시 PENDING | 승인은 화면에 표시된 특정 payload의 승인 |
| 반영 execution | PENDING → SENDING → APPLIED / FAILED / UNKNOWN | APPLIED만 외부 영수증으로 실제 등록 확인 |
| 미확정 복구 | UNKNOWN → 키 조회 → APPLIED 또는 확정 부재 후 PENDING | 3회 조회 후에도 불명확하면 UNKNOWN 유지·운영 조사. 새 키 등록 금지. |
| 제한·장애 | 구현 규칙 |
|---|---|
| 기본 예산 | run 전체 모델 6회·도구 16회·누적 입력 24,000 / 출력 4,000 tokens·실행 120초. queue 대기는 별도. |
| 중단·취소 | 취소 플래그 확인 후 새 호출 중지. 결과 저장과 취소는 CAS로 최종 상태 하나만 확정. |
| worker 복구 | lease 45초·heartbeat 10초; 재claim마다 fencing_token 증가. 이전 worker의 저장 거부. 총 attempts≤2. |
| 재시도 | 읽기 일시 오류 최대 1회; 출력 수정 1회; 모두 job 누적 예산·deadline에 포함. 권한 오류는 재시도 금지. |
| 비용 예약 | 호출 전에 최대 예상 비용 예약; usage로 정산. 응답 유실 시 예약액을 유지해 복구 중 예산을 중복 사용하지 않음. |
| 외부 쓰기 | 승인·권한·revision 확인 후 outbox 저장. action key 유지. 외부 멱등 계약이 없으면 자동 등록을 출시하지 않음. |
복구 용어 lease는 한 worker가 작업을 맡는 유효기간이고, fencing token은 재할당 전 worker의 늦은 저장을 거부하는 증가 번호다. Outbox는 등록 의도를 DB 트랜잭션에 함께 저장하고, 별도 처리기가 외부로 전달하는 방식이다. 외부 효과의 중복 방지에는 앞서 정한 멱등 계약이 함께 필요하다.
화면과 인터페이스
화면의 한 동작이 어떤 서버 계약으로 이어지는가?
이 단계의 산출물3개 화면 명세
12개 HTTP API
SCR-01 · 요청, 진행, 근거 답변
| 번호 | 동작·상태 | 서버 계약·검수 |
|---|---|---|
| 01 · 범위 | 로그인 사용자가 접근 가능한 프로젝트만 선택. 선택 변경 시 이전 요청과 결과 구분 | FR-01 / API-01 / TC-02 |
| 02 · 접수 | 요청 10~4,000자. 전송 중 중복 버튼 잠금; 서버는 Idempotency-Key로 중복 방지 | FR-02 / API-01 / TC-03 |
| 03 · 진행 | 실제 단계 이벤트·최근 갱신 시각 표시. 임의 진행률 % 표시 금지. 3초 폴링, 숨긴 탭은 중지 | FR-08 / API-03·04·05 / TC-07 |
| 04 · 결과 | 답변·근거 부족·추가 질문을 구분. 실패를 빈 답변처럼 표시하지 않음 | FR-05 / API-06 / TC-01·04 |
| 05 · 근거 | 원문 revision·문단·인용 표시. 현재 권한이 없으면 본문·파일 URL 숨김 | FR-09 / API-07 / TC-02·05 |
| 06 · 초안 | proposal이 있을 때만 검토 진입. 답변만 있는 경우 최종 결과로 종료 | FR-06 / API-09 / TC-06 |
SCR-02 · 실행할 내용 자체를 검토한다
| 번호 | 입력·동작 규칙 | 오류·검수 |
|---|---|---|
| 01 · 버전 | proposal_id·revision·payload_hash 표시. 승인 API는 세 값의 일치를 확인 | 이미 수정·검토됐으면 409; 새 내용 재조회 |
| 02 · 수정 | 제목 5~120자, 설명 20~4,000자, 허용 담당자, ISO 기한. 수정 저장은 새 revision 생성 | API-08; 승인된 revision을 덮어쓰지 않음 |
| 03 · 근거 | 검토자가 근거 원문과 최신성 확인. 변경 문서·권한 회수 시 재검토 안내 | TC-05; 등록 직전 서버도 현재 권한·revision 재검사 |
| 04 · 결정 | 검토자 역할만 승인·반려. 반려 사유 10~1,000자. 자기 승인 허용 여부는 조직 정책으로 확정 | API-10; 동시 결정은 1개만 저장 |
| 05 · 등록 | 승인과 등록은 두 동작. 같은 revision의 기존 execution이 있으면 재사용 | API-11·12; UNKNOWN일 때 새 등록 버튼 금지 |
SCR-03 · 실행 이력과 운영 조사
| 작업 | 실행 | 검토 | 반영 |
|---|---|---|---|
| RUN-1042 · QA 누락 조사 | 완료 | 승인 | 등록 완료 |
| RUN-1043 · 정책 질의 | 완료 | 대상 없음 | 대상 없음 |
| RUN-1044 · 개선 업무 | 완료 | 승인 | 확인 중 |
| 번호 | 표시·권한 | 연결 |
|---|---|---|
| 01 · 목록 | 본인·허용 프로젝트의 작업만. 필터는 URL query 유지; cursor 20개씩 | API-02 / FR-01·09 |
| 02 · 상태 | 실행·검토·반영을 별도 열로 표시. UNKNOWN을 실패 또는 성공으로 단정하지 않음 | API-12 / FR-07 |
| 03 · 조사 | action key·확인 시각·영수증 표시. 운영자의 직접 새 키 재전송은 금지 | TC-08·09 / FR-12 |
| 04 · 기록 | 단계·오류 코드·사용량 등 메타데이터. 운영자에게 원문 권한을 자동 부여하지 않음 | API-04 / FR-10 |
화면 공통 규칙
| 상태 | UI 규칙 |
|---|---|
| 로딩·빈 결과 | 마지막 데이터와 갱신 시각 유지. 아직 결과가 없으면 대기 상태와 취소 동작 제공. |
| 권한 없음 | 다른 조직 ID의 존재·제목·근거를 노출하지 않음. 민감 대상은 404로 통일. |
| 통신 오류 | 작성 중 요청·반려 사유 보존. 재전송은 기존 요청 키 사용. |
| 모바일 | 390px에서 좌우 패널을 상하 배치. 표·구조도만 내부 가로 스크롤. |
| 접근성 | 모든 실제 버튼·링크 키보드 접근, 포커스 표시, modal 포커스 복원, 오류와 입력 연결. |
| 긴 실행 | 백그라운드 탭 폴링 중지. 돌아오면 현재 상태 다시 조회. 서버 작업은 화면 종료와 무관하게 지속. |
HTTP API 계약 · /api/v1
| ID · 메서드 | 경로·핵심 요청 | 결과·조건 |
|---|---|---|
| API-01 · POST | /runs · request, project_id, parent_run_id? + Idempotency-Key | 202 새 run / 200 같은 요청 재사용. tenant는 세션에서 결정. |
| API-02 · GET | /runs · project_id?, status?, cursor?, limit≤20 | 허용 범위 items,next_cursor. 최신 요청 순. |
| API-03 · GET | /runs/:id | status,stage,result_id?,proposal_id?,cancel_requested,version |
| API-04 · GET | /runs/:id/events · after_seq, limit≤100 | events,last_seq,has_more. 원문·비밀 키 제외. |
| API-05 · POST | /runs/:id/cancel · expected_version | 202 취소 요청 / 200 이미 취소 / 409 다른 종료 상태 |
| API-06 · GET | /results/:id | answer,claims,evidence_ids,uncertainties,proposal_id? |
| API-07 · GET | /evidence/:id | 문서·revision·구간·원문. 현재 ACL 재확인. |
| API-08 · POST | /proposals/:id/revisions · base_revision,payload + Idempotency-Key | 201 새 revision / 기존 revision 충돌 409. SENDING·UNKNOWN 동안 수정 금지. |
| API-09 · GET | /proposals/:id | current_revision,payload,payload_hash,decision,expires_at |
| API-10 · POST | /proposals/:id/decisions · revision,payload_hash,decision,reason + Idempotency-Key | 201 결정 / 동일 키 200 / 버전·기존 결정 충돌 409 |
| API-11 · POST | /proposals/:id/executions · revision,payload_hash + Idempotency-Key | 202 등록 대기 / 200 기존 실행. 승인·만료·권한·근거 버전 검사. |
| API-12 · GET | /executions/:id | status,action_key,receipt?,last_error_code,checked_at |
WRITE REQUEST
API-10 · 승인
{
"revision": 2,
"payload_hash": "sha256:…",
"decision": "APPROVED",
"reason": "근거와 담당자·기한을 확인함"
}
ERROR CONTRACT
공통 충돌 응답
{
"error": {
"code": "PROPOSAL_REVISION_CONFLICT",
"message": "등록안이 변경되었습니다.",
"retryable": false
},
"trace_id": "trace_1042"
}
공통 API 규칙 로그인은 same-origin 보안 세션 쿠키, 쓰기 요청에는 CSRF 검증을 적용한다. 요청 키는 tenant·actor·route 범위에서 24시간 보존하며 payload hash가 다르면 409다. 401 세션 만료 / 403 역할 부족 / 404 비공개 대상 / 409 충돌 / 422 입력 오류 / 429 제한 / 503 의존 서비스 장애로 구분한다.
API 요청 키를 24시간 보관한다는 규칙과 업무 등록 중복 방지는 별개다. 요청 키가 만료돼도 같은 proposal revision의 execution을 재사용해야 한다. 등록 결과를 확정하지 못한 작업의 키·영수증·조사 기록은 일반 요청 키와 함께 지우지 않는다.
개발 작업과 산출물
어떤 순서로 구현하면 실제 기능이 이어지는가?
이 단계의 산출물 모듈 구조·개발 티켓
수직 기능·완료 정의
책임이 분리된 모듈 구조
| 모듈 | 책임 | 완료 기준 |
|---|---|---|
| RunService | 요청·권한 검증, 멱등 키, run 접수·취소 | 중복 요청·취소 경합 테스트 |
| AgentRunner | context 구성, 모델/도구 반복, 예산, checkpoint | 제한 초과·재시작 후 카운터 유지 |
| ToolRegistry | JSON Schema 검증, 허용 도구와 범위 주입 | 범위 밖 인자·지시 주입으로 권한 확대 불가 |
| EvidenceValidator | 근거 ID·문서 revision·인용 hash 확인 | 없는 근거 참조·다른 run의 근거 거부 |
| ProposalService | 불변 revision, payload 정규화·hash, 검토 결정 | 변경안의 재승인·동시 결정 하나만 저장 |
| ExecutionPublisher | 승인 확인, Outbox claim, 멱등 등록·조회 | 성공 후 타임아웃에도 외부 티켓 1개 |
| AuditRepository | 행위·상태·버전·사용량 기록 | 추적 가능하며 비밀 키·원문 로그 없음 |
서버에서 강제할 두 개의 트랜잭션
TRANSACTION A
결과를 완성한다
근거·출력 검증 → result와 근거 관계 저장 → 필요 시 proposal revision 1 생성 → run SUCCEEDED. 전부 성공하거나 전부 롤백한다.
TRANSACTION B
등록할 내용을 고정한다
현재 proposal row 잠금 → 승인·revision·hash·유효기간 확인 → execution/outbox 생성 → audit. 외부 HTTP 호출은 commit 뒤 수행한다.
async function publish(executionId) {
const action = await claimExecution(executionId);
await recheckAccessAndApproval(action);
// 저장된 승인 payload만 사용. 모델 재호출 없음.
try {
const receipt = await taskAdapter.create({
payload: action.approvedPayload,
idempotencyKey: action.actionKey
});
await markApplied(action, receipt);
} catch (error) {
// 전송 여부를 확정할 수 없으면 실패로 단정하지 않음.
await recordFailureOrUnknown(action, error);
}
}
설계 의사 코드. 실제 구현은 claim lease·fencing, 외부 오류 분류, 만료·권한 재검사, UNKNOWN 조회 복구를 포함해야 한다.
단계별 개발 티켓
- M1 · 계약과 데이터 — 권한·문서 버전·외부 멱등 계약을 먼저 검증
- M2 · 끝까지 이어지는 기능 — 요청 → 읽기 → 근거 답변을 실제 자료로 연결
- M3 · 승인과 등록 — 검토 화면 → Outbox → 외부 영수증
- M4 · 평가와 인수 — 장애·권한·복원까지 확인 후 운영 전환
| 티켓 · 담당 | 작업·산출물 | 선행 조건 | 인수 |
|---|---|---|---|
| DEV-01 · 기획/연동 | 프로젝트 브리프·권한표·INT-01~04 계약과 샘플 응답 | 착수 | 외부 능력 확인·제외 범위 확정 |
| DEV-02 · 백엔드 | DB migration·tenant FK·세션·멱등 저장 | DEV-01 | TC-02·03 |
| DEV-03 · 도메인/QA | 문서 fixture·정답·권한 매트릭스·평가 세트 | DEV-01 | 정답 검토자 서명·hash 고정 |
| DEV-04 · 백엔드 | 자료 snapshot·4개 읽기 도구·검색 ACL | DEV-02 | TC-02·04·05 |
| DEV-05 · AI/백엔드 | provider adapter·runner·budget·lease·결과 검증 | DEV-03·04 | TC-01·04·07·10 |
| DEV-06 · 프런트 | SCR-01·03 요청·상태·근거·이력, API-01~07 | DEV-02·05 | TC-01·11 |
| DEV-07 · 풀스택 | SCR-02 수정·승인·충돌, API-08~10 | DEV-05·06 | TC-05·06 |
| DEV-08 · 연동/백엔드 | API-11·12·Outbox·멱등 생성·결과 조회 | DEV-01·07 | TC-08·09 |
| DEV-09 · QA/도메인 | 고정 세트 반복 평가·보안·경합·장애 검수 | DEV-03~08 | 모든 P0 gate |
| DEV-10 · 운영 | 경보·중단·복원·만료 삭제·배포 runbook | DEV-08·09 | TC-12·인수 기록 |
일정 산정 방식 자료·외부 API 계약이 확정된 후 DEV 티켓별 구현·검수·연동 대기 시간을 추정한다. 팀 규모를 모른 채 확정 주차를 약속하지 않는다. 완료율은 작성한 코드 양이 아니라 각 티켓의 인수 증거로 판단한다.
AI 개발자에게 전달할 작업 카드
작업 ID: DEV-07
목표: 승인 대상과 실제 등록 payload가 항상 일치한다.
변경 범위: ProposalService, API-08~10, SCR-02
입력: proposal_id, base_revision, payload, actor context
규칙: 수정은 새 revision / 승인 승계 금지 / tenant 서버 주입
실패: 409 버전 충돌 / 403 역할 부족 / 422 입력 오류
금지: 모델에게 승인 권한 부여, 승인 payload 덮어쓰기
검증: TC-05, TC-06 / 경합 결과와 DB 행 수 첨부
제출: 변경 코드, migration 여부, API 예시, 검수 증거, 남은 제약
인수할 파일 묶음
| 산출물 | 필수 내용 |
|---|---|
| 개발기획서·화면 명세 | FR·SCR·API·TC ID, 문서 버전, 변경 이력, 미확정 사항 |
| 소스·배포 설정 | 실행 방법, 서버 secret 목록, dependency lock, rollback 경로 |
| DB·API 계약 | migration·복원 절차, JSON Schema, 요청·응답·에러 예시 |
| 에이전트 패키지 | 프롬프트·도구·모델·정책 버전, 예산·종료 규칙 |
| QA·평가 보고서 | fixture hash, 결과·실패 분석, 증거 캡처·로그, 재검수 결과 |
| 운영 runbook | 경보, 일시 중단, UNKNOWN 조사, 백업 복원, 보관·삭제 |
검수와 운영 전환
무엇을 확인해야 “개발 완료”라고 말할 수 있는가?
이 단계의 산출물 인수 테스트·평가 보고서
출시 gate·운영 절차
요구사항에 연결된 12개 인수 시나리오
| ID · 요구사항 | 입력·상황 | 기대 결과 | 제출 증거 |
|---|---|---|---|
| TC-01 · FR-05·09 | 명확한 정답·근거가 있는 QA 요청 | SUCCEEDED, 출처가 주장에 연결, proposal은 근거와 일치 | 입력·결과 JSON·근거 화면 |
| TC-02 · FR-01·04 | 다른 조직 ID·회수된 문서 권한·범위 밖 도구 요청 | 읽기·근거·결과·등록 모두 차단; 자료 존재도 비노출 | 역할별 요청·응답·도구 기록 |
| TC-03 · FR-02 | 같은 요청 키로 동시에 10회 전송, 이어서 다른 본문 전송 | run 1개; 다른 본문은 409 | 요청 키 hash·DB count |
| TC-04 · FR-04·05 | 지시 주입 문서·없는 근거 ID·상충 자료 | 권한 확대 없음; 잘못된 출력 수정 1회; 부족하면 질문·보류 | fixture·검증 오류·최종 outcome |
| TC-05 · FR-03·06 | 승인 후 문서·정책·담당 권한 변경 또는 초안 수정 | 변경된 내용은 재검토; 이전 승인으로 등록 불가 | revision·hash·409/403 기록 |
| TC-06 · FR-06 | 두 검토자가 같은 revision을 동시에 승인·반려 | 결정 하나만 저장. 같은 요청 재전송은 결과 재사용 | 결정 행 수·동시 요청 로그 |
| TC-07 · FR-08 | 반복 도구 요청·deadline 초과·완료 직전 취소 | run 예산 내 종료; 취소/완료 중 하나만 확정 | 카운터·시간선·최종 상태 |
| TC-08 · FR-07 | 등록 성공 직후 응답 유실 | UNKNOWN → action key 조회 → APPLIED; 티켓 1개 | 외부 영수증·호출 횟수 |
| TC-09 · FR-07 | 같은 등록 요청 10회, UNKNOWN 중 재클릭 | execution 1개; 새 action key 생성 없음 | outbox unique·외부 티켓 수 |
| TC-10 · FR-08·10 | worker 종료·lease 만료·이전 worker 복귀 | 새 fencing_token만 쓰기 가능; 누적 예산 유지 | claim·checkpoint·거부 이벤트 |
| TC-11 · FR-09 | 키보드·390px·통신 오류·숨긴 탭 복귀 | 근거 탐색·입력 보존·포커스 복원·현재 상태 갱신 | 화면 캡처·접근성 QA |
| TC-12 · FR-10·11·12 | 평가 회귀·운영 중지·백업 복원·만료 삭제 | gate 통과; 신규 claim 0; 복원 hash 일치; 만료 자료 접근 불가 | 평가표·복원 기록·감사·삭제 증거 |
평가를 세 층으로 나눈다
| 평가 항목 | 기준안 |
|---|---|
| 고정 세트 60건 | 정상 답변 20 / 근거 부족·상충 10 / 지시 주입 10 / 권한 경계 10 / 승인·외부 장애 10 |
| 반복·분모 | 각 3회, 총 180회. 답변 적합률은 정상·부족 사례 30×3=90회 중 ≥86회 적합. 나머지는 정책 gate로 별도 집계. |
| 정답 검수 | 도메인 담당자 2인이 답변·근거·허용 행동을 합의. 모델 grader는 보조이며 단독 인수 판정 금지. |
| 데이터 분리 | 개발용 세트와 held-out 인수 세트 분리. 실패를 수정한 뒤 인수 세트에만 맞추지 않도록 새 표본 추가. |
| 출시 차단 | 관측한 교차 조직 누출·무승인 등록·중복 티켓·위험한 허위 단정이 하나라도 있으면 출시 보류. |
| 변경 후 재검수 | 모델·프롬프트·도구 스키마·권한 정책·검색 방식 변경마다 해당 gate 회귀 평가. |
실제로 제출할 QA 결과 형식
| 필드 | 작성 예시 · 가상 사례 |
|---|---|
| 문서·대상 | QA-RUN-014 / TC-08 / build abc123 / model·policy 버전 |
| 입력·사전 조건 | 승인 proposal rev2, 외부 생성 성공 후 응답 유실 fixture |
| 재현 절차 | 등록 요청 → 응답 유실 주입 → 상태 조회 → action key 조사 |
| 기대 / 실제 | 기대: UNKNOWN→APPLIED, 티켓 1개 / 실제: 테스트 수행 후 기록 |
| 증거 | UI 캡처, redacted HTTP 응답, outbox 행, 외부 영수증 링크 |
| 결함·조치 | 심각도 / issue ID / 원인 / 변경 사항 / 영향 API |
| 재검수·인수 | 수정 버전 / 재검수 결과 / 검수자 / 인수 일시 |
운영 기준과 비용 산정
| 항목 | 초기 운영안 · 합의 후 확정 |
|---|---|
| 동시성·대기 | 전체 worker 2개·조직당 1개; queue 상한 100. 초과 429 + Retry-After; 조직별 공정 claim. |
| 관측·알림 | queue age, run 실패율, 근거 부족률, 토큰·비용, UNKNOWN 등록 수. queue 5분·UNKNOWN 3회 미확정 시 알림. |
| 비용 | run 비용 = 각 모델 호출의 과금 항목별 사용량×적용 단가의 합 + 도구·검색 비용. 실패·재시도도 포함하고 캐시 등 단가가 다른 항목은 구분한다. 단가는 선택 모델의 확인일과 함께 별도 설정. |
| 월 예산 | 예상 월 비용 = 월 run 수×실측 평균 run 비용 + 저장·검색·서버. 평균과 P95를 분리해 예산 상한 결정. |
| 로그·보관 | 메타데이터 중심 로그. 임시 추출 24h / 결과·근거 snapshot 90일 / 감사 180일 제안. 업무 계약에 맞춰 확정. |
| 백업·복원 | 일일 암호화 백업, RPO 24h·RTO 4h 목표. 격리 복원과 외부 영수증 대조로 실제 달성 여부 확인. |
| 키·파일 | 서버 secret으로 모델·연동 키 관리. 원문 비공개 저장, 다운로드마다 현재 ACL 검사. |
장애 발생 시 행동과 출시 판단
| 상황 | 즉시 행동 | 재개 조건 |
|---|---|---|
| 모델·도구 오류 급증 | 신규 run·claim 일시 중단, 버전·오류 분류 | 고정 세트와 샘플 run 확인 |
| 권한·자료 누출 의심 | 영향 자료 접근 차단, trace로 범위 확인 | 정책 수정·영향 조사·권한 테스트 통과 |
| 등록 여부 불명확 | 해당 execution UNKNOWN 유지, 같은 action key 결과 조회 | 영수증 확인 또는 확정 부재. 새 키 생성으로 해결 금지. |
| worker 장애 | lease 만료 후 제한된 재claim, 누적 예산 유지 | fencing·checkpoint 검증 |
| rollback·복원 | 이전 검증 버전 복구, DB 읽기 호환·outbox 상태 확인 | 이미 등록된 티켓 재생성 없음·복원 hash 일치 |
출시 완료 조건 TC-01~12 통과, 품질·정책 gate 충족, INT-01~04 검증, 치명·높음 결함 0, 운영 복원 증거, 업무 책임자의 인수 기록이 모두 필요하다. 이 문서는 수행할 검수 기준이며 테스트 통과 보고서가 아니다.
착수 전에 담당자가 확정할 결정
| 미확정 항목 | 현재 제안 | 결정 책임·시점 |
|---|---|---|
| 첫 적용 업무·자료 | 한 프로젝트의 QA 누락 조사 | 제품 책임자 / M1 |
| 승인 권한·자기 승인 | 검토자 역할 필요, 자기 승인 여부는 조직 정책 | 업무 책임자 / M1 |
| 자료·티켓 연동 | revision·ACL·action key·결과 조회 계약 | 연동 담당자 / M1 |
| 모델·사용 데이터 조건 | adapter 사용, 평가 통과 모델·버전 고정 | 보안·AI 담당자 / M2 전 |
| 예산·보관·SLA | 문서의 초기값을 실제 표본으로 측정·조정 | 운영 책임자 / M4 전 |
평가 수치의 해석 90회 중 86회 적합은 약 95.6%로, 이 평가 세트의 합격 기준이다. 전체 실제 업무에서 같은 비율을 보장하지 않으며, 같은 사례의 반복 실행도 서로 독립인 표본이라고 단정할 수 없다. 실패 유형과 새 업무 표본을 함께 확인한다.
추적 로그도 별도로 설정한다. SDK의 자동 추적에는 모델·도구의 입력과 출력이 포함될 수 있다. 민감 데이터 수집 설정과 exporter의 전송 대상을 확인하고, 이 기획서의 원문 비기록 정책에 맞춰 제외·마스킹한다. 실행 추적 기능만으로 변경 불가능한 업무 감사 기록이 완성되는 것은 아니다. 공식 참고: Agents SDK Tracing
설계 근거와 적용 범위
공식 자료의 원칙을 적용한 자체 개발안이다. 아래 API·제한값·화면·인수 조건은 제품의 공식 사양이 아니다. 화면은 가상 데이터로 만든 설계 예시이며, 이 글에 실제 자료 검색·티켓 생성 백엔드가 구현되어 있지는 않다. 공식 문서 확인: 2026.09.20.
- Anthropic · Building effective agents — 고정 워크플로와 에이전트의 구분, 단순한 구조에서 시작하는 원칙.
- Anthropic · Writing tools for agents — 도구의 목적·입출력 설계와 실제 작업을 통한 평가.
- OpenAI · Human-in-the-loop — 사람의 승인과 실행 재개를 다루는 공식 구현 참고.
- OpenAI · Tracing — 실행 기록과 도구 호출을 관측하는 공식 구현 참고.