Skip to main content
The primary usage patterns for QWED-Tax are the TaxPreFlight auditor for intent-based checks and the QWEDTaxMiddleware for intercepting AI-generated payroll payloads.

TaxPreFlight

The TaxPreFlight class routes a transaction intent to the guards required for its action. Every intent must declare a supported action and include a complete, verifiable claim for that action — TaxPreFlight fails closed and blocks execution whenever the payload is missing required fields, contains non-numeric or non-finite values, or references an unsupported action.
TaxPreFlight is fail-closed. An intent that is empty, not a dict, uses an unsupported action, or does not contain a complete verifiable claim is blocked by default — it never silently passes through.
from qwed_tax.verifier import TaxPreFlight

# 1. Initialize
preflight = TaxPreFlight()

# 2. Capture Intent (from AI Agent)
intent = {
    "action": "hire",
    "worker_type": "1099",  # LLM Decision
    "worker_facts": {
        "provides_tools": True,       # Fact: We gave them a laptop
        "reimburses_expenses": True,  # Fact: We pay for travel
        "indefinite_relationship": True,
    },
}

# 3. Audit
report = preflight.audit_transaction(intent)

# 4. Enforce
if not report["allowed"]:
    print(f"BLOCKED: {report['blocks']}")
    # Do NOT call Gusto/Stripe API
else:
    print(f"Verified. Checks run: {report['checks_run']}")
    # call_gusto_api()

Supported actions

Every intent must include an action field. TaxPreFlight normalizes the action (trims whitespace, lowercases, and replaces spaces with underscores) before routing. If the action is missing, not a non-empty string, or not in the supported set, the intent is blocked with a report that lists every supported action.
ActionPurposeRequired claim fields
hireWorker classification (W-2 vs 1099)worker_type, worker_facts.provides_tools, worker_facts.reimburses_expenses, worker_facts.indefinite_relationship
economic_nexusUS sales-tax nexus checkstate, sales_data.amount, sales_data.transactions, tax_decision
trade_taxTrader set-off or capital gainsloss_head, offset_head, loss_amountorasset_type, dates.buy, dates.sell, claimed_rate
corporate_actionRelated-party loans or startup valuationslender_type, borrower_role, interest_rate, market_rateorinvestment_round="convertible_note" plus investment_amount, cap_price, discount, next_round_price
remit_moneyInternational remittance (LRS/TCS)remittance_amount_usd, purpose, fy_usage
expense_claimInput Tax Credit eligibilityexpense_category, amount, tax_paid
pay_invoiceWithholding / TDS on vendor paymentservice_type, amount, ytd_payment
The following legacy action names are accepted and canonicalized automatically:
AliasCanonical action
hire_workerhire
worker_classificationhire
sales_tax_checkeconomic_nexus
sales_tax_assessmenteconomic_nexus

Fail-closed routing

audit_transaction returns allowed=False whenever routing cannot produce a complete verifiable claim. The three blocking conditions are:
preflight.audit_transaction({})
# {
#   "allowed": False,
#   "action": None,
#   "blocks": ["TaxPreFlight requires a non-empty intent payload with an explicit action."],
#   "checks_run": []
# }
The report always echoes the canonical action (after alias resolution) in the action field and an empty checks_run list when the intent was rejected before any guard executed.

Intent fields reference

audit_transaction returns a report with the following fields:
allowed
boolean
true only when every selected guard passes. Treat any false as a hard block.
action
string | null
The canonical action the intent resolved to (for example, "hire"). When the caller submits an unsupported action, this echoes back the raw value they sent; when the payload is entirely missing or empty, it is null.
blocks
string[]
One or more human-readable block reasons when allowed is false.
checks_run
string[]
Names of the guards that actually executed (for example, ["worker_classification"]). Empty when the intent was rejected before any guard ran.
advisories
string[]
Optional advisory messages emitted by guards (for example, required TDS deduction amounts).

Redacting block reasons in untrusted contexts

report["blocks"] contains human-readable diagnostics that may echo back fields from the original intent — including worker facts, nexus sales figures, remittance purposes, or vendor service types. Treat these strings as internal-only: log them to your audit trail, but do not render them verbatim in end-user surfaces, demo output, or any context where a downstream consumer could infer protected payroll or customer data. In example and demo scripts bundled with qwed-tax (examples/verify_tax_expansion.py), outcomes are printed as high-level pass/fail only and verification details are intentionally redacted:
def _print_outcome(label: str, report: dict, allowed_text: str, blocked_text: str) -> None:
    """Print a safe high-level outcome without echoing raw block reasons."""
    print(f"{label}: {allowed_text if report['allowed'] else blocked_text}")
    if report["allowed"]:
        return

    print("   Verification details intentionally redacted.")
Mirror this pattern when surfacing preflight results outside a trusted audit boundary.

Supported actions

Every intent must set action to one of the supported values below. Actions are normalized (trimmed, lowercased, spaces converted to underscores) before routing, and the listed aliases are accepted for backwards compatibility.
ActionAliasesRuns
hirehire_worker, worker_classificationClassificationGuard
economic_nexussales_tax_check, sales_tax_assessmentNexusGuard
trade_taxSpeculationGuard, CapitalGainsGuard
corporate_actionRelatedPartyGuard, ValuationGuard
remit_moneyRemittanceGuard
expense_claimInputCreditGuard
pay_invoiceTDSGuard
Any other action (including missing, empty, or non-string values) is blocked with a message listing the supported actions.

Required fields per action

Each action requires a complete claim shape. If any listed field is missing, null, or empty, the transaction is blocked before guards run — no guard is invoked with partial inputs.
ActionRequired fields
hireworker_type, worker_facts.provides_tools, worker_facts.reimburses_expenses, worker_facts.indefinite_relationship
economic_nexusstate, sales_data.amount, sales_data.transactions, tax_decision
trade_tax (trader set-off)loss_head, offset_head, loss_amount
trade_tax (capital gains)asset_type, dates.buy, dates.sell, claimed_rate
corporate_action (loans)lender_type, borrower_role, interest_rate, market_rate
corporate_action (valuation)investment_round, investment_amount, cap_price, discount, next_round_price
remit_moneyremittance_amount_usd, purpose, fy_usage
expense_claimexpense_category, amount, tax_paid
pay_invoiceservice_type, amount, ytd_payment
For trade_tax and corporate_action, at least one of the claim shapes above must be fully present. Providing trigger fields for a claim but omitting any of its required fields is treated as an incomplete claim and fails closed. Startup valuation (corporate_action) additionally only runs when investment_round == "convertible_note"; other rounds are blocked with an explicit message.

Numeric inputs must be finite

Guards that work with money — RemittanceGuard and TDSGuard — reject non-numeric, NaN, and infinite values. The surrounding audit_transaction call surfaces these as block reasons so an upstream LLM cannot smuggle through a malformed number.
report = preflight.audit_transaction({
    "action": "pay_invoice",
    "service_type": "PROFESSIONAL_FEES",
    "amount": float("inf"),
    "ytd_payment": 0,
})
# report["allowed"] = False
# report["blocks"] contains:
#   "TDS verification requires finite invoice_amount and ytd_payment values."
| `worker_type` | `str` | ClassificationGuard |
| `worker_facts` | `dict` | ClassificationGuard |
| `state` | `str` | NexusGuard |
| `sales_data` | `dict` (`amount`, `transactions`) | NexusGuard |
| `tax_decision` | `str` | NexusGuard |
| `loss_head` | `str` | SpeculationGuard |
| `loss_amount` | `float` | SpeculationGuard |
| `offset_head` | `str` | SpeculationGuard |
| `asset_type` | `str` | CapitalGainsGuard |
| `dates` | `dict` (`buy`, `sell`) | CapitalGainsGuard |
| `claimed_rate` | `str` | CapitalGainsGuard |
| `lender_type` | `str` | RelatedPartyGuard |
| `borrower_role` | `str` | RelatedPartyGuard |
| `interest_rate` | `float` | RelatedPartyGuard |
| `market_rate` | `float` | RelatedPartyGuard |
| `investment_round` | `str` | ValuationGuard (when `"convertible_note"`) |
| `investment_amount` | `str` | ValuationGuard |
| `cap_price` | `str` | ValuationGuard |
| `discount` | `str` | ValuationGuard |
| `next_round_price` | `str` | ValuationGuard |
| `remittance_amount_usd` | `float` | RemittanceGuard |
| `purpose` | `str` | RemittanceGuard |
| `fy_usage` | `float` | RemittanceGuard |
| `expense_category` | `str` | InputCreditGuard |
| `amount` | `float` | InputCreditGuard, TDSGuard |
| `tax_paid` | `float` | InputCreditGuard |
| `service_type` | `str` | TDSGuard |
| `ytd_payment` | `float` | TDSGuard |

### Capital gains date validation

For `action="trade_tax"`, the capital-gains route requires both `dates.buy` and `dates.sell` along with `asset_type` and `claimed_rate`. If any required field is missing, the transaction is blocked with a field-level diagnostic:

```python
report = preflight.audit_transaction({
    "action": "trade_tax",
    "asset_type": "equity",
    "dates": {"buy": "2024-01-01"},  # sell missing
    "claimed_rate": "20"
})
# report["allowed"] = False
# report["blocks"] = [
#   "Action 'trade_tax' is missing required fields for capital_gains: dates.sell."
# ]

TDS advisories now block

When action="pay_invoice" requires a TDS deduction, the transaction is blocked and the required deduction is surfaced in both advisories and blocks. The agent must re-issue the payment net of TDS before execution can proceed:
report = preflight.audit_transaction({
    "action": "pay_invoice",
    "service_type": "PROFESSIONAL_FEES",
    "amount": 50000,
    "ytd_payment": 0,
})
# report["allowed"] = False
# report["advisories"] = ["TDS Required: Deduct 5000.00 from payment."]
# report["blocks"] = [
#     "Invoice payment requires TDS deduction of 5000.00 before execution."
# ]

Example: unsupported action

report = preflight.audit_transaction({"action": "do_everything"})
# report["allowed"] = False
# report["action"] = "do_everything"
# report["blocks"] = [
#     "TaxPreFlight requires a supported action. Supported actions: "
#     "corporate_action, economic_nexus, expense_claim, hire, "
#     "pay_invoice, remit_money, trade_tax."
# ]

TaxVerifier

The TaxVerifier class provides jurisdiction-scoped access to guards. Initialize with "US" or "INDIA" to load the appropriate guard set.
from qwed_tax.verifier import TaxVerifier

# US jurisdiction
us_verifier = TaxVerifier(jurisdiction="US")
result = us_verifier.verify_us_payroll(entry=payroll_entry)

# India jurisdiction
india_verifier = TaxVerifier(jurisdiction="INDIA")
result = india_verifier.verify_india_crypto(
    losses={"VDA": Decimal("-5000")},
    gains={"BUSINESS": Decimal("10000")}
)

# Deposit rate verification (India)
result = india_verifier.verify_india_deposit(
    age=65,
    base_rate=Decimal("7.00"),
    claimed_rate=Decimal("7.50"),
    senior_premium=Decimal("0.50")
)
JurisdictionAvailable methods
USverify_us_payroll(entry) — runs PayrollGuard gross-to-net check
INDIAverify_india_crypto(losses, gains) — runs CryptoTaxGuard set-off check
INDIAverify_india_deposit(**kwargs) — runs DepositRateGuard FD rate check
The US verifier also includes a TaxPreFlight instance accessible via us_verifier.preflight for intent-based auditing.

QWEDTaxMiddleware (Gusto interceptor)

The QWEDTaxMiddleware intercepts AI-generated payroll payloads before they reach execution APIs like Gusto. It validates the payload schema using Pydantic models and then runs deterministic gross-to-net verification.
from qwed_tax.middleware.gusto_interceptor import QWEDTaxMiddleware

middleware = QWEDTaxMiddleware()

# Simulate an AI-generated payroll payload
ai_payload = {
    "payroll_entry": {
        "employee_id": "E001",
        "gross_pay": "5000.00",
        "taxes": [
            {"name": "Federal Income Tax", "amount": "800.00"},
            {"name": "Social Security", "amount": "310.00"}
        ],
        "deductions": [
            {"name": "401k", "amount": "250.00", "type": "PRE_TAX"}
        ],
        "net_pay_claimed": "3640.00"
    }
}

decision = middleware.process_ai_payroll_request(ai_payload)

Response format

{
  "status": "VERIFIED",
  "message": "AI tax logic mathematically verified. Safe to execute.",
  "execution_permitted": true,
  "validated_payload": { ... }
}
status
string
VERIFIED or BLOCKED.
execution_permitted
boolean
Whether the payload is safe to forward to the execution API.
risk
string
Risk code when blocked: TAX_LOGIC_HALLUCINATION, INVALID_PAYLOAD, or VERIFIER_ERROR.
reason
string
Human-readable explanation of why the payload was blocked.
validated_payload
object
The validated payload (JSON-serialized) when execution is permitted.

Standalone guard usage

You can also use specific guards individually found in qwed_tax.jurisdictions and qwed_tax.guards.
from qwed_tax.jurisdictions.us.payroll_guard import PayrollGuard

pg = PayrollGuard()
result = pg.verify_fica_tax(gross_ytd=180000, current_gross=5000, claimed_ss_tax=310)
print(result.message)
# -> "FICA Error: Expected $68.20, Claimed $310. Limit logic failed? (Hit Limit this period...)"

TypeScript SDK

Run compliance checks proactively in the browser or frontend.
npm install @qwed-ai/tax
import { TaxPreFlight } from '@qwed-ai/tax';

const result = TaxPreFlight.audit({
  action: "hire",
  worker_type: "1099",
  worker_facts: {
    provides_tools: true,
    reimburses_expenses: true,
    indefinite_relationship: true,
  },
});

if (!result.allowed) {
   alert("Compliance Block: " + result.blocks.join(", "));
}