Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developer.kodexa.ai/llms.txt

Use this file to discover all available pages before exploring further.

Validation rules on a Data Definition produce data exceptions when the rule fails. Exceptions stay open until a reviewer fixes the underlying value, marks the exception resolved, or marks it as overridden. A well-built task template uses those exceptions to drive the action toolbar — a reviewer cannot click Approve while the data they’re approving is broken. This recipe walks through the two flavours of the gate: any open exception and open exceptions only on specific attribute paths.

The problem

A naive task template ships with an Approve action that always appears enabled. Reviewers can click it whenever they want, regardless of whether their open exceptions actually got fixed. The task transitions to approved, the activity plan moves on, and a downstream system gets bad data.

The pattern

Two action properties control the gate:
PropertyTypeEffect
onlyEnabledIfNoOpenExceptionsbooleanDisable the action while any open exception exists on the task.
onlyEnabledIfNoOpenExceptionsForPathsTaxonPathRef[]Disable the action while open exceptions exist on any of the listed taxon paths. Other open exceptions are ignored. Each entry is { taxonomySlug, taxonPath }.
Both live under metadata.actions[].properties in the task template YAML. They are evaluated in the UI against the current document’s exception set whenever it changes — there is no extra round trip to the server.
Use onlyEnabledIfNoOpenExceptionsForPaths when only some of the exceptions matter for the action. A reviewer might be allowed to send a document for re-extraction while a low-priority field is still flagged, but should never be allowed to approve a final invoice while the total line is in exception.
The action editor in Studio renders onlyEnabledIfNoOpenExceptionsForPaths as a polished picker with taxonomy filtering, path search, group-taxon support, and a custom-path fallback for paths not in any bound taxonomy — no need to type slugs by hand.

Block any open exception

The simplest gate. If anything is broken anywhere in the document, the button is disabled.
metadata:
  actions:
    - uuid: approve-action
      type: approve
      label: "Approve"
      properties:
        targetStatus: approved
        statusSlug: approved
        icon: check
        color: green
        keybind: "a"
        onlyEnabledIfNoOpenExceptions: true

Block only on specific taxon paths

When some attributes are critical and others are not, list the critical paths. Exceptions on any other field stop being a blocker.
metadata:
  actions:
    - uuid: approve-action
      type: approve
      label: "Approve"
      properties:
        targetStatus: approved
        statusSlug: approved
        icon: check
        color: green
        keybind: "a"
        onlyEnabledIfNoOpenExceptionsForPaths:
          - { taxonomySlug: invoice-taxonomy, taxonPath: invoice/invoice_number }
          - { taxonomySlug: invoice-taxonomy, taxonPath: invoice/total_amount }
          - { taxonomySlug: invoice-taxonomy, taxonPath: invoice/vendor_name }
The action is disabled while any of invoice_number, total_amount, or vendor_name has an open exception. A complaint about, say, invoice/notes is treated as advisory and does not block the button.
The path is the full taxon path as it appears in the Data Definition (parent group plus child name, separated by /). Use the same path you would use in a formula or selection-option expression.
The legacy plain-string form (["invoice/invoice_number", "invoice/total_amount"]) is still accepted by the platform — entries are normalized to { taxonomySlug: "", taxonPath: "..." } at runtime — but the object form is preferred and is what the Studio editor saves. Mixing both forms in the same list is supported during a migration.

Pairing with a “Reject” action

Reviewers usually need an escape hatch. A Reject button that does not check for exceptions lets them route a hopelessly broken document to a different team without first fixing every field by hand.
metadata:
  actions:
    - uuid: approve-action
      type: approve
      label: "Approve"
      properties:
        targetStatus: approved
        statusSlug: approved
        icon: check
        color: green
        keybind: "a"
        onlyEnabledIfNoOpenExceptionsForPaths:
          - { taxonomySlug: invoice-taxonomy, taxonPath: invoice/invoice_number }
          - { taxonomySlug: invoice-taxonomy, taxonPath: invoice/total_amount }

    - uuid: reject-action
      type: reject
      label: "Reject"
      properties:
        targetStatus: rejected
        statusSlug: rejected
        icon: close
        color: red
        keybind: "r"
        # No exception gate — reviewer can always reject.
In an activity plan the next step can branch on which action was clicked, so the rejected document can be routed to a remediation queue without ever mixing into the approved-document flow.

Recipe summary

  1. Add validationRules to the Data Definition for every field that must be clean before approval. See Validation and Conditional Formatting.
  2. On the approve action in the task template, set onlyEnabledIfNoOpenExceptionsForPaths to the list of paths you actually care about.
  3. Keep the reject action ungated so a reviewer can always escape.
  4. Test by raising an exception on a non-listed path — the approve button must stay enabled.

Next: take ownership

Gating the action keeps bad data from being approved. The next recipe — Take-ownership pattern — keeps good data from being silently un-approved by an AI agent or event subscription that runs after the reviewer has already accepted it.