Skip to main content

Tool

A Tool is the fundamental building block for backend operations in Fascia. Each Tool represents a single executable unit of server logic -- equivalent to an API endpoint, webhook handler, or cron job. Tools are defined entirely through structured specs, and their execution follows the immutable Execution Contract.

Tool Spec Structure

A Tool spec includes the following components:

FieldDescription
nameUnique identifier in camelCase (e.g., createReservation, processPayment)
versionImmutable version number, incremented on each change
descriptionHuman-readable description of what the Tool does
triggerHow the Tool is invoked (HTTP, webhook, cron, queue)
inputJSON Schema defining the expected input payload
outputJSON Schema defining the response format
flowThe Flow graph (nodes and edges) that defines execution logic
policiesReferences to Policy specs that govern this Tool
authAuthentication and authorization configuration
riskLevelAssigned by the Risk Engine: green, yellow, or red
concurrencyStrategyHow concurrent invocations are handled
idempotencyKeyExpression for deduplicating repeated calls

Trigger Types

The trigger determines how a Tool is invoked:

TriggerDescriptionUse Case
httpCalled via tool.call(name, payload) over HTTPAPI endpoints, form submissions
webhookInvoked by an external service callbackPayment confirmations, third-party notifications
cronInvoked on a scheduleDaily reports, periodic cleanup, recurring billing
queueInvoked by a message queue event (future)Async processing, event-driven workflows

Auth Configuration

Every Tool specifies its authentication requirements:

  • required -- Whether authentication is needed to invoke the Tool. Public Tools (like a status page) can set this to false.
  • allowedRoles -- Which roles can invoke the Tool. Roles follow RBAC (Role-Based Access Control), such as admin, staff, or customer.

The auth check occurs at step 2 of the Execution Contract. Unauthorized requests are rejected before any business logic runs.

Risk Levels

Every Tool is assigned a risk level by the Risk Engine based on its flow patterns:

LevelMeaningDeployable?
GreenSafe patterns only -- Entity actions within transactions, no unbounded queriesYes
YellowWarning patterns detected -- external calls in transitions, missing retry configYes, with acknowledgment
RedUnsafe patterns -- raw writes, missing transactions, payment without rollbackBlocked

Red-level Tools cannot be deployed under any circumstances. The issues must be resolved first. See the risk rules reference for the full classification criteria and auto-fix suggestions.

Example: 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)"
}

This Tool reads a reservation, asserts it is in the confirmed status, creates a payment record within a transaction, and then calls the payment provider outside the transaction boundary. The external payment call is placed after the transaction commit -- this is intentional, because if the transaction rolled back, an already-charged payment could not be undone automatically. The idempotencyKey prevents duplicate charges for the same reservation and amount.