# How DeskcommCRM Enforces AI Guardrails to Prevent Hallucinated Prices and Unsafe Tool Calls

> DeskcommCRM enforces AI guardrails to prevent hallucinated prices and unsafe tool calls. Learn how its dual-layer system validates monetary promises and blocks unauthorized tool executions before they happen.

- Repository: [Rafael Melgaço/DeskcommCRM](https://github.com/melgarafael/DeskcommCRM)
- Tags: how-to-guide
- Published: 2026-09-13

---

**DeskcommCRM implements a deterministic dual-layer guardrail system inside its agent-engine package that validates monetary promises against organizational tables and blocks unauthorized tool calls before execution, forcing the LLM to regenerate compliant outputs.**

DeskcommCRM embeds a rigorous validation layer within the *agent-engine* package to stop large language models from generating fabricated pricing or executing harmful operations. The system combines regex-based promise extraction in [`lib/agent-engine/guardrails/promise/engine.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/agent-engine/guardrails/promise/engine.ts) with strict tool-call interception via [`lib/agent-engine/agent/tool-breaker.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/agent-engine/agent/tool-breaker.ts), ensuring every AI response adheres to business rules and security policies. These guardrails operate deterministically between the LLM and external systems, creating an auditable checkpoint for all AI-generated content and actions.

## How the Promise Guard Validates Monetary Outputs

The **Promise Guard** acts as a deterministic filter that scans every LLM-generated message for monetary expressions—prices, discount percentages, and installment counts—before the text reaches the end user. Located in [`lib/agent-engine/guardrails/promise/engine.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/agent-engine/guardrails/promise/engine.ts), this guard extracts numerical commitments using locale-aware regular expressions and validates them against organization-specific thresholds stored in Supabase.

### Regex-Based Extraction of Prices and Discounts

The `extractPromises()` function employs three targeted regular expressions to identify Brazilian Real (R$) monetary values and related terms within the candidate message:

```typescript
const RE_PRICE_RS = /R\$\s*(\d{1,3}(?:\.\d{3})+(?:,\d{2})?|\d+(?:,\d{2})?)/gi;
const RE_DISCOUNT_PREFIX = /desconto\s+(?:de\s+)?(\d{1,3})\s*(?:%|por\s*cento)/gi;
const RE_INSTALLMENTS_PREFIX = /\b(?:parcel\w*|dividid\w*\s+em|em(?:\s+at[ée])?)\s+(\d{1,3})\s*(?:x\b|vezes\b)/gi;

```

The engine normalizes extracted strings into cent integers via `moneyToCents()` and compiles them into a `DetectedPromise[]` array. Each entry carries a `kind` discriminator (`'price'`, `'discount'`, or `'installments'`) and a numeric `value`, creating a structured representation of every financial commitment implied in the text.

### Table-Driven Compliance Checks

The `decidePromise()` function loads the organization’s **PromiseTable**—containing `minPriceCents`, `maxDiscountPercent`, and `maxInstallments`—and performs a short-circuiting validation loop. When a value violates configured limits, the guard immediately returns a structured rejection:

```typescript
if (p.kind === 'price' && table.minPriceCents !== undefined && p.value < table.minPriceCents) {
  return { allow: false, code: 'promise_out_of_table', reason: 'o preço está fora da tabela do playbook...' };
}

```

This rejection prevents hallucinated discounts (e.g., "20% off" when the maximum is 10%) or impossible installment plans from reaching customers.

## How the Tool-Breaker Guard Sanitizes Tool Calls

The **Tool-Breaker Guard** intercepts every outbound `toolCall` request emitted by the LLM, ensuring that only vetted integrations execute with safe arguments. Implemented in [`lib/agent-engine/agent/tool-breaker.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/agent-engine/agent/tool-breaker.ts), this guard functions as a mandatory middleware between the agent and external APIs, database RPCs, or webhook dispatchers like WAHA.

### Whitelist Enforcement and Argument Validation

When the LLM requests a tool invocation, the breaker performs two sequential checks. First, it validates the tool name against a static allow-list defined in [`lib/agent-engine/guardrails/tool-allowlist.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/agent-engine/guardrails/tool-allowlist.ts) (e.g., `["sendMessage", "createLead", "fetchCatalog"]`). Second, it inspects the JSON payload for disallowed patterns, including raw secrets, file-system path traversals, or malformed URLs.

If either check fails, the guard returns a `ToolCallError` object containing a deterministic `code` and human-readable `reason`. The LLM receives this error as a system instruction to retry without the prohibited operation, effectively neutralizing attempts at prompt injection or unauthorized data exfiltration.

## Feedback Loop Implementation

Both guardrails integrate with DeskcommCRM’s API layer through standardized response wrappers defined in [`lib/api/wrappers.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/api/wrappers.ts). The `fail()` helper serializes guardrail rejections into a consistent payload that the LLM consumes as a correction signal.

### Structured Rejection Responses

When the Promise Guard detects a violation, it returns a `PromiseDecision` object that routes through the API wrapper:

```typescript
import { decidePromise } from '@/lib/agent-engine/guardrails/promise/engine';
import { getPromiseTable } from '@/lib/agent-engine/db/repository';

async function handleAgentMessage(msg: string, orgId: string) {
  const table = await getPromiseTable(orgId);
  const decision = decidePromise({ candidate: msg, table });

  if (!decision.allow) {
    return fail(decision.code, decision.reason, 422);
  }
  // Proceed with safe message
}

```

Similarly, the Tool-Breaker uses `breakToolCall()` to gate execution:

```typescript
import { breakToolCall } from '@/lib/agent-engine/agent/tool-breaker';

async function processToolCall(toolName: string, args: any) {
  const verdict = breakToolCall(toolName, args);
  if (!verdict.allow) {
    return fail(verdict.code, verdict.reason, 403);
  }
  return await actualToolDispatcher(toolName, args);
}

```

This architecture ensures that violations never reach downstream systems; instead, the LLM receives immediate, actionable feedback to correct its output.

## Summary

- **Promise Guard** in [`lib/agent-engine/guardrails/promise/engine.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/agent-engine/guardrails/promise/engine.ts) uses regex extraction (`extractPromises()`) and table lookups (`decidePromise()`) to block hallucinated prices and unauthorized discounts.
- **Tool-Breaker** in [`lib/agent-engine/agent/tool-breaker.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/agent-engine/agent/tool-breaker.ts) enforces an allow-list and argument sanitization to prevent unsafe external calls.
- Both systems return structured rejections via [`lib/api/wrappers.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/api/wrappers.ts), creating a feedback loop that forces the LLM to retry with compliant values.
- The guardrails reference organization-specific configurations loaded from Supabase via [`lib/agent-engine/db/repository.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/agent-engine/db/repository.ts), enabling per-tenant policy enforcement.

## Frequently Asked Questions

### How does the promise guard handle different currency formats?

The current implementation focuses on Brazilian Real (R$) using locale-specific regex patterns that recognize dot-thousand separators and comma-decimal notation (e.g., `R$ 1.234,56`). The `moneyToCents()` helper normalizes these into integer cent values for consistent comparison against the `PromiseTable` thresholds, though the architecture supports extension for additional currency formats.

### Can organizations customize the validation thresholds?

Yes. The `getPromiseTable()` function in [`lib/agent-engine/db/repository.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/agent-engine/db/repository.ts) loads organization-specific limits from Supabase, including `minPriceCents`, `maxDiscountPercent`, and `maxInstallments`. Each tenant maintains independent thresholds, allowing different sales playbooks to enforce distinct pricing floors or promotional caps without code changes.

### What happens when the LLM attempts an unauthorized tool call?

The Tool-Breaker intercepts the request before execution and returns a `ToolCallError` with an HTTP 403 status via the `fail()` wrapper. The LLM receives this error as a system message instructing it to retry without the prohibited tool, ensuring that only whitelisted operations (such as `sendMessage` or `createLead`) ever reach external APIs.

### Is the guardrail layer deterministic?

Absolutely. Unlike probabilistic LLM outputs, the guardrails in [`promise/engine.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/promise/engine.ts) and [`tool-breaker.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/tool-breaker.ts) execute deterministic regex matches and strict equality checks against static allow-lists. This determinism guarantees that identical inputs always produce identical validation results, creating an auditable security boundary between the AI and business-critical operations.