Skip to content

Accounts Payable

Accounts Payable is a starter pack: a typed APContext, tuned signal extractors, and a default rule pack for vendor-payment workflows. It is a fast start for an AP agent, not a prerequisite for enforcement. You supply the context as a typed object on each process_invoice write, and the Novarch engine reasons over the full session, not just the single action, when it applies the AP rule pack.

If your workflow does not produce signals like domain_similarity_to_canonical, you do not need this pack to get enforcement. Use GenericContext and author rules over the evidence you have. The typed pack is opinionated by design.

from novarch.verticals.ap import APContext

APContext fields

APContext is the typed context for the AP / vendor-payment vertical. Every field below exists on the Pydantic model; values are validated at the write boundary.

What this pack expects

The pack is tuned for vendor-payment fraud, so it asks for more than identity:

  • Identity (required, shown to the operator as evidence): vendor_id, vendor_name, invoice_id, amount, payment_method, approval_threshold.
  • Pack signals (required, because the bundled rules read them): vendor_in_master_db, domain_similarity_to_canonical, off_cycle, agent_confidence.
  • Optional enrichment (defaulted; supply more to sharpen which rules fire): vendor_first_seen_days_ago, vendor_bank_change_days_ago, amount_z_score_vs_vendor_history, exception_ticket, urgency_language_detected, submitted_off_hours.

If you cannot produce the required pack signals, that is the cue to use GenericContext instead.

Identity (required for evidence display)

FieldTypeMeaning
vendor_idstrThe vendor’s stable identifier.
vendor_namestrHuman-readable vendor name.
invoice_idstrThe invoice this payment settles.
amountfloat (≥ 0.0)Payment amount.
payment_method"ach" | "wire" | "check"Settlement rail. Validated to one of these three literals.
approval_thresholdfloat (> 0.0)The per-action approval ceiling for this vendor / payment.

Vendor identity & legitimacy

FieldTypeMeaning
vendor_in_master_dbboolWhether the vendor exists in the canonical vendor master.
vendor_first_seen_days_agoint | None (≥ 0)Age of the vendor relationship in days. None means a pre-existing relationship established before the audit window.
domain_similarity_to_canonicalfloat (0.0–1.0)1.0 is an exact match against the canonical vendor domain or name; lower values indicate a homograph / look-alike.

Payment instrument integrity

FieldTypeMeaning
vendor_bank_change_days_agoint | None (≥ 0)Days since the vendor’s bank details last changed. None means no recorded bank change in the window (treated as no signal).

Amount & threshold anomaly

FieldTypeMeaning
amount_z_score_vs_vendor_historyfloat | NoneHow far this amount deviates from the vendor’s historical baseline. None means no baseline (cold-start vendor).

Timing & cadence

FieldTypeMeaning
off_cycleboolWhether the payment falls outside the vendor’s normal billing cadence.
exception_ticketstr | NoneFinance exception-ticket reference for off-cycle payments. Format EXC-NNNN (literal EXC- + four digits). Missing, empty, or mis-formatted on an off-cycle payment is an AP-4 kill. On-cycle payments leave this None.
urgency_language_detectedbool (default False)At least one urgency marker (“wire today”, “pay immediately”, “urgent”, “ASAP”, …) was found in the inbound vendor communication. A behavioral BEC signal.
submitted_off_hoursbool (default False)The invoice arrived outside the vendor’s normal business hours (weekend, late evening, very early morning). This is a pure wall-clock timing anomaly, distinct from off_cycle. A behavioral BEC signal.

Agent reasoning quality

FieldTypeMeaning
agent_confidencefloat (0.0–1.0)The agent’s own stated confidence in this action.

Cross-action evidence

FieldTypeMeaning
referenced_prior_action_idslist[str] (default [])Action IDs this action explicitly references. This is relational metadata, not a signal value.

Wiring it up

You attach the context to a write tool through the context_builder= argument of @augur.tool. The builder runs when the write fires; it receives the tool’s call arguments and returns the APContext.

from novarch import augur
from novarch.verticals.ap import APContext
def build_invoice_context(invoice: dict) -> APContext:
return APContext(
vendor_id=invoice["vendor_id"],
vendor_name=invoice["vendor_name"],
invoice_id=invoice["invoice_id"],
amount=invoice["amount"],
payment_method=invoice["payment_method"], # "ach" | "wire" | "check"
approval_threshold=invoice["approval_threshold"],
vendor_in_master_db=invoice["vendor_in_master_db"],
vendor_first_seen_days_ago=invoice.get("vendor_first_seen_days_ago"),
domain_similarity_to_canonical=invoice["domain_similarity_to_canonical"],
vendor_bank_change_days_ago=invoice.get("vendor_bank_change_days_ago"),
amount_z_score_vs_vendor_history=invoice.get("amount_z_score"),
off_cycle=invoice["off_cycle"],
exception_ticket=invoice.get("exception_ticket"),
urgency_language_detected=invoice.get("urgency_language_detected", False),
submitted_off_hours=invoice.get("submitted_off_hours", False),
agent_confidence=invoice["agent_confidence"],
)
@augur.tool(
kind="write",
action_type="process_invoice",
context_builder=lambda invoice: build_invoice_context(invoice),
)
def process_invoice(invoice: dict) -> dict:
# Reaches here only after the Novarch engine returns a pass verdict.
return pay(invoice)

Read tools (@augur.tool(kind="read")) buffer into the pending action; the process_invoice write drains that buffer, materializes the Action with this APContext, and gates on the Novarch engine’s verdict before the body runs.

AP rule pack

Three rules ship with the AP vertical. They are plain-English statements the Novarch engine applies to the whole session.

  • AP-1 · BEC Pattern (BLOCKED): Blocks payments that fit a business-email-compromise fingerprint: three or more converging behavioral signals (recent bank change, near-threshold amount, off-hours submission, urgency language, off-cycle timing). The sending domain matching, vendor-in-master and high agent confidence do not rescue it: a compromised mailbox produces all three.
  • AP-2 · Unverified Bank Change (PAUSED): Pauses a payment when the vendor’s bank details changed inside the last 30 days and nothing in the session evidences a callback confirming the change, so an operator can decide whether the verification happened off the record.
  • AP-4 · Off-Cycle Without Exception Ticket (BLOCKED): Blocks any off-cycle payment that does not reference a Finance exception ticket (EXC-NNNN), regardless of vendor identity, amount, or domain match.

Rule bodies are editable in plain English by the workflow owner; these descriptions summarize the shipped defaults.