참조
Skill + DB Query Plugin 패턴
AisOpsFlow에서 자연어 DB 질의를 안전하게 지원하기 위한 권장 설계입니다.
Skill + DB Query Plugin 패턴
이 문서는 다음 세 가지를 함께 도입하는 권장 설계를 설명합니다.
- Core 안의
skillmanifest 계층 - 안전한 DB 접근을 담당하는
db-queryplugin - 자연어 요청을 구조화된 질의 계획으로 바꾸는
natural-language-to-queryskill
왜 이 패턴이 필요한가
사용자가 다음처럼 물을 수 있게 하려는 목적입니다.
- “최근 24시간 실패 주문 보여줘”
- “오늘 heartbeat 놓친 runner 수 알려줘”
- “실패 job 이 10개 넘는 tenant 목록 보여줘”
하지만 LLM이 임의 SQL을 직접 실행하게 두면 위험합니다.
안전한 경로는 다음과 같습니다.
- 자연어 요청이 Core로 들어옴
- Core가 적절한 skill을 선택
- LLM이 구조화된 query intent 생성
- Core가 정책 검증 후
planned_job으로 변환 - Runner가 DB plugin 호출
- plugin이 제한된 read-only 질의 실행
- Core가 결과 표와 요약을 반환
역할 분리
Skill
skill은 실행기가 아니라 제어 평면의 판단 자산입니다.
책임:
- 요청이 DB 질의인지 분류
- filter, 집계, 시간 범위, limit 추출
- 허용된 datasource 선택
- 승인 필요 여부 판단
- 가능하면 raw SQL 대신 구조화된 query intent 생성
Core
Core는 정책과 오케스트레이션 계층을 유지합니다.
책임:
- skill 선택
- 스키마 정보와 datasource 메타데이터 제공
- LLM 출력 검증
- 출력 결과를
planned_job으로 변환 - 실행 전 정책 적용
- decision trace 와 감사 로그 저장
Runner
Runner는 실행 경계를 유지합니다.
책임:
- planned job 실행
- 내부 HTTP/JSON 계약으로 plugin 호출
- timeout, retry, 네트워크 제어 적용
Plugin
plugin은 실제 DB 접근을 수행합니다.
책임:
- 내부 인증 헤더 검증
- datasource allowlist 강제
- read-only 동작 강제
- 제한된 질의 실행
- 결과를 표준 형태로 정규화
권장 skill manifest
권장 파일 위치:
core/skills/natural-language-to-query.yaml
예시:
api_version: skill/v1
id: natural-language-to-query
display_name: Natural Language to Query
description: 안전한 read-only DB 질문을 구조화된 질의 계획으로 변환합니다.
mode: plan
action_kind: db
default_risk: read_only
allowed_targets:
- planned_job
supported_plugins:
- postgres-query
- mysql-query
requires_approval:
prod: true
non_prod: false
constraints:
allow_raw_sql: false
max_limit: 200
require_time_range_for_large_tables: true
require_datasource_allowlist: true
output_schema: db_query_intent/v1권장 skill 출력 형식
LLM은 구조화된 JSON만 반환하는 것이 좋습니다.
{
"intent": "db_read_query",
"datasource": "orders-prod-ro",
"driver": "postgres",
"target": {
"table": "orders"
},
"select": ["id", "status", "created_at"],
"filters": [
{"field": "status", "op": "eq", "value": "FAILED"},
{"field": "created_at", "op": "gte", "value": "now-24h"}
],
"sort": [
{"field": "created_at", "direction": "desc"}
],
"limit": 50,
"risk": "read_only",
"requires_approval": true,
"rationale": "운영 데이터소스이며 고객 영향 가능성이 있는 데이터입니다."
}그 다음 Core가 이것을 다음 중 하나로 변환합니다.
- 검증된 SQL
- plugin 전용 구조화 질의 payload
둘 중에서는 두 번째가 더 바람직합니다.
권장 planned_job 형태
이 부분은 현재의 LLM plan 흐름과 맞추는 것이 좋습니다.
{
"workflow_id": "llm-ad-hoc-db",
"kind": {
"tag": "JobDb",
"contents": {
"driver": "postgres",
"dsn_ref": "orders-prod-ro",
"query": "select id, status, created_at from orders where status = $1 and created_at >= now() - interval '24 hours' order by created_at desc limit 50",
"params": ["FAILED"],
"query_timeout_seconds": 15,
"allowlist_tag": "read"
}
}
}향후 제품이 확장되면 이 use case 에는 JobPlugin 변형이 더 깔끔할 수 있습니다.
권장 DB plugin API
권장 plugin 이름:
postgres-querymysql-query- 필요하면 통합형
db-query
권장 endpoint:
POST /query/read
요청:
{
"trace_id": "tr_123",
"tenant_id": "default",
"datasource": "orders-prod-ro",
"driver": "postgres",
"statement": "select id, status, created_at from orders where status = $1 limit 50",
"params": ["FAILED"],
"timeout_seconds": 15,
"max_rows": 50
}응답:
{
"ok": true,
"columns": ["id", "status", "created_at"],
"rows": [
[101, "FAILED", "2026-03-14T10:00:00Z"]
],
"row_count": 1,
"truncated": false,
"duration_ms": 42
}POST /query/explain
정책 검토나 디버깅용으로 선택적으로 둘 수 있습니다.
GET /healthz
plugin readiness 확인용 기본 health endpoint 입니다.
보안 모델
필수 제어:
- v1 에서는 read-only credential만 사용
- datasource allowlist
- table/view allowlist
- row limit 강제
- timeout 강제
- multi-statement 금지
- DDL/DML 금지
- 로그에 secret 값 남기지 않기
- 모든 요청에 signed internal header 적용
강력 권장:
- 직접 테이블보다 승인된 view 사용
- tenant 별 datasource 매핑
- 민감 컬럼 결과 마스킹
- trace ID, datasource, row count 를 포함한 query audit log
natural-language-to-query 흐름
- 사용자가 자연어로 질문
- Core가
natural-language-to-query선택 - Core가 다음 컨텍스트 제공
- tenant
- environment
- datasource catalog
- 허용된 table/view
- schema 힌트
- LLM이 구조화된 query intent 반환
- Core가 다음을 검증
- datasource 허용 여부
- read-only 여부
- row limit 적절성
- env/approval 정책
- Core가 이를
planned_job으로 변환 - Runner가 DB plugin 으로 dispatch
- plugin이 실행 후 정규화된 결과 반환
- Core가 다음을 렌더링
- 결과 표
- 짧은 자연어 요약
승인 정책
초기 권장 규칙:
- prod DB 실행은 전부 승인 필요
- write intent 는 v1 에서 전부 거부
- datasource 를 결정할 수 없는 요청은 거부
- row/timeout 한도를 넘는 요청은 거부
권장 v1 범위
우선 출시:
- PostgreSQL read-only
- datasource allowlist
- 구조화된 filter, sort, limit, aggregate count
- 결과 표 + 요약
후순위:
- write query
- 자유 SQL 모드
- 임의 스키마 간 join
- 최종 사용자용 schema discovery
- spreadsheet export
왜 AisOpsFlow에 잘 맞는가
이 패턴은 현재 제품 경계와 잘 맞습니다.
- skill은 판단
- Core는 검증과 정책
- Runner는 통제된 실행
- plugin은 외부 시스템 접근
이 분리를 유지하면 LLM을 유용하게 쓰면서도 DB superuser처럼 행동하게 만들지 않을 수 있습니다.