본문으로 건너뛰기

Tool

Tool(도구)은 Fascia에서 백엔드 연산의 기본 구성 요소입니다. 각 Tool은 하나의 실행 가능한 서버 로직 단위를 나타내며, API 엔드포인트, 웹훅 핸들러, 크론 작업에 해당합니다. Tool은 전적으로 구조화된 스펙으로 정의되며, 실행은 불변의 Execution Contract(실행 계약)를 따릅니다.

Tool 스펙 구조

Tool 스펙은 다음 구성 요소를 포함합니다:

FieldDescription
namecamelCase 형식의 고유 식별자 (예: createReservation, processPayment)
version변경 시마다 증가하는 불변 버전 번호
descriptionTool의 기능에 대한 사람이 읽을 수 있는 설명
triggerTool이 호출되는 방식 (HTTP, webhook, cron, queue)
input예상 입력 페이로드를 정의하는 JSON Schema
output응답 형식을 정의하는 JSON Schema
flow실행 로직을 정의하는 Flow 그래프 (노드와 엣지)
policies이 Tool에 적용되는 Policy 스펙 참조 목록
auth인증 및 인가 설정
riskLevelRisk Engine이 부여하는 등급: green, yellow, red
concurrencyStrategy동시 호출 처리 방식
idempotencyKey중복 호출을 방지하기 위한 멱등성 키 표현식

트리거 유형

트리거는 Tool이 호출되는 방식을 결정합니다:

TriggerDescriptionUse Case
httpHTTP를 통해 tool.call(name, payload)로 호출API 엔드포인트, 폼 제출
webhook외부 서비스 콜백으로 호출결제 확인, 서드파티 알림
cron스케줄에 따라 호출일간 보고서, 주기적 정리, 반복 청구
queue메시지 큐 이벤트로 호출 (향후 지원)비동기 처리, 이벤트 기반 워크플로우

인증 설정

모든 Tool은 인증 요구사항을 지정합니다:

  • required -- Tool 호출에 인증이 필요한지 여부. 공개 Tool(상태 페이지 등)은 false로 설정할 수 있습니다.
  • allowedRoles -- Tool을 호출할 수 있는 역할. RBAC(역할 기반 접근 제어)를 따르며, admin, staff, customer 등의 역할을 지정합니다.

인증 검사는 Execution Contract의 2단계에서 수행됩니다. 인가되지 않은 요청은 비즈니스 로직이 실행되기 전에 거부됩니다.

리스크 등급

모든 Tool은 Flow 패턴을 기반으로 Risk Engine이 리스크 등급을 부여합니다:

LevelMeaningDeployable?
Green안전한 패턴만 사용 -- 트랜잭션 내 Entity 작업, 무제한 쿼리 없음배포 가능
Yellow경고 패턴 감지 -- 상태 전이 내 외부 호출, Retry 설정 누락확인 후 배포 가능
Red위험 패턴 -- 원시 쓰기(raw write), 트랜잭션 누락, 롤백 없는 결제차단

Red 등급 Tool은 어떤 상황에서도 배포할 수 없습니다. 문제를 먼저 해결해야 합니다. 전체 분류 기준과 자동 수정 제안은 리스크 규칙 레퍼런스를 참고하세요.

예시: processPayment Tool

{
"name": "processPayment",
"version": 1,
"description": "Process a payment for a confirmed reservation",
"trigger": { "type": "http", "method": "POST", "path": "/payments/process" },
"input": {
"type": "object",
"properties": {
"reservationId": { "type": "string", "format": "uuid" },
"amount": { "type": "number", "minimum": 0 },
"paymentMethod": { "type": "string", "enum": ["card", "bank_transfer"] }
},
"required": ["reservationId", "amount", "paymentMethod"]
},
"output": {
"type": "object",
"properties": {
"paymentId": { "type": "string" },
"status": { "type": "string" },
"processedAt": { "type": "string", "format": "date-time" }
}
},
"auth": {
"required": true,
"allowedRoles": ["admin", "staff", "customer"]
},
"flow": {
"startNode": "validate-reservation",
"nodes": [
{
"id": "validate-reservation",
"type": "Read",
"config": { "entity": "Reservation", "filter": { "id": "input.reservationId" } }
},
{
"id": "check-status",
"type": "Assert",
"config": { "expression": "reservation.status == 'confirmed'", "message": "Reservation must be confirmed" }
},
{
"id": "tx-start",
"type": "Transaction",
"config": { "action": "begin" }
},
{
"id": "create-payment",
"type": "Write",
"config": { "entity": "Payment", "action": "create" }
},
{
"id": "tx-end",
"type": "Transaction",
"config": { "action": "commit" }
},
{
"id": "charge",
"type": "Payment",
"config": { "provider": "stripe", "action": "charge" }
}
],
"edges": [
{ "from": "validate-reservation", "to": "check-status" },
{ "from": "check-status", "to": "tx-start" },
{ "from": "tx-start", "to": "create-payment" },
{ "from": "create-payment", "to": "tx-end" },
{ "from": "tx-end", "to": "charge" }
]
},
"policies": ["requireTransaction", "paymentRollback"],
"riskLevel": "yellow",
"idempotencyKey": "concat(input.reservationId, '-', input.amount)"
}

이 Tool은 예약(reservation)을 조회하고, confirmed 상태인지 검증한 후, 트랜잭션 내에서 결제 레코드를 생성하고, 트랜잭션 경계 밖에서 결제 서비스를 호출합니다. 외부 결제 호출이 트랜잭션 커밋 이후에 배치된 것은 의도적입니다 -- 트랜잭션이 롤백되더라도 이미 처리된 결제를 자동으로 되돌릴 수 없기 때문입니다. idempotencyKey는 동일한 예약과 금액에 대한 중복 결제를 방지합니다.