guard() API
guard() is the core API. It wraps any function with runtime safety.
TypeScript
import { guard } from 'fuze-ai'
// Basic — all defaults from fuze.toml
const search = guard(async (query: string) => {
return await vectorDb.search(query)
})
// With options
const search = guard(
async (query: string) => {
return await vectorDb.search(query)
},
{
maxRetries: 5,
timeout: 10_000,
maxCost: 0.50,
}
)
// Side-effect with compensation
const sendEmail = guard(
async (to: string, body: string) => {
return await ses.sendEmail(to, body)
},
{
sideEffect: true,
compensate: async (result) => {
await ses.recallEmail(result.messageId)
},
}
)Python
from fuze_ai import guard
# Basic
@guard
def search(query: str):
return vector_db.search(query)
# With options
@guard(max_retries=5, timeout=10_000, max_cost=0.50)
def search(query: str):
return vector_db.search(query)
# Side-effect with compensation
@guard(side_effect=True, compensate=recall_email)
def send_email(to: str, body: str):
return ses.send_email(to, body)Options
All options are optional. Defaults come from fuze.toml.
| Option | Type | Default | Description |
|---|---|---|---|
maxRetries | number | 3 | Max retry attempts for this function |
timeout | number | 30000 | Timeout in milliseconds |
maxCost | number | 1.00 | Max cost in USD for this call |
maxTokens | number | undefined | Max tokens for this call |
maxIterations | number | 25 | Hard iteration cap for this call |
onLoop | 'kill' | 'warn' | 'skip' | 'kill' | Behavior when a loop is detected |
model | string | undefined | Model identifier for cost estimation |
estimatedTokensIn | number | undefined | Estimated input tokens (used for pre-flight cost checks) |
estimatedTokensOut | number | undefined | Estimated output tokens (used for pre-flight cost checks) |
sideEffect | boolean | false | Whether this call has real-world consequences |
compensate | Function | undefined | Rollback function called on failure |
Return value
guard() returns a new function with the same signature. Call it exactly as you would the original.
const guardedSearch = guard(originalSearch)
// Same signature, same return type
const results = await guardedSearch('my query')Guard events
When Fuze intervenes, it throws typed errors:
import { BudgetExceeded, LoopDetected, GuardTimeout } from 'fuze-ai'
try {
await guardedSearch('query')
} catch (err) {
if (err instanceof BudgetExceeded) {
// Budget ceiling hit
}
if (err instanceof LoopDetected) {
// Loop pattern detected
}
if (err instanceof GuardTimeout) {
// Per-call timeout exceeded
}
}| Error | Thrown when |
|---|---|
BudgetExceeded | Cost ceiling reached for the call or run |
LoopDetected | Repeated output pattern detected |
GuardTimeout | The guarded function exceeded its timeout |
createRun() API
createRun() creates a scoped run context that shares budget and loop state across multiple steps. Use it when a single logical task spans several guarded calls and you want aggregate limits to apply.
import { createRun, guard } from 'fuze-ai'
const run = createRun({ maxCost: 2.00, maxIterations: 50 })
const search = guard(async (q: string) => vectorDb.search(q), { run })
const summarize = guard(async (docs: string[]) => llm.summarize(docs), { run })
// Both steps share the same budget and loop state
const docs = await search('climate policy')
const summary = await summarize(docs)Each call within the run draws from the shared maxCost and maxIterations budgets. If any step pushes the run over its ceiling, a BudgetExceeded error is thrown.
Timer cleanup
Fuze properly cleans up internal setTimeout timers on successful execution using a .finally(() => clearTimeout(timer)) pattern. This means:
- No resource leaks -- timers are cleared whether the guarded function resolves or rejects.
- Safe for long-running processes -- you can wrap thousands of calls without accumulating dangling timers.
- No manual cleanup is required on the caller's side.