The Approval Engine
Approvals in AI GO are not an "approvals module" — they are an interceptor sitting on the data write path. Which means: whether data arrives from a Custom App, the REST API, or the AI assistant, approvals apply. There is no route around them.
How it works
In a typical system, creating a leave request or purchase order writes immediately. AI GO differs:
- Write interception — once an administrator enables an approval workflow on a table, writes to it are intercepted
- Assignment — the platform derives qualified approvers from the workflow definition, notifies them, and creates an approval request
- Approval callback — when every stage passes, the platform executes the originally intercepted operation, including all the business engines it cascades into (invoicing, stock deduction, journal entries)
A rejection at any stage returns the record to draft for revision and resubmission.
The three write types are intercepted differently
| Operation | Interception behavior |
|---|---|
| Insert | The record is held pending and takes effect on approval |
| Update | Not executed. The payload is held and applied automatically on approval |
| Delete | Not executed. Performed automatically on approval |
The distinction matters: updates and deletes are not written and then rolled back — they simply do not run. The caller receives a pending-approval exception carrying a request identifier.
Callers should not retry — retrying only creates duplicate requests. Catch the exception and tell the user the change was submitted for approval.
Configuring a workflow
Entry point: Dashboard → System & Operations → Approval Workflow Engine. Requires system.admin.
1. Choose the target
Select the table the workflow applies to (sales orders, leave requests, vendor bills, and so on). One table can have only one active workflow.
2. Trigger conditions
Approvals can be required only under specific conditions — "purchase orders above 100,000 require manager sign-off", for instance. Anything below the threshold passes straight through, so you don't manufacture unnecessary approval load.
Conditions can also route to different flows based on record field values.
3. Define stages
Create ordered stages (department manager first, finance director second). Each stage can specify:
- Whether it is required
- Approval type — one approver suffices, or all listed approvers must sign (parallel approval)
4. Define qualified approvers
Each stage specifies approver eligibility, with three rule types:
| Rule | Notes |
|---|---|
| Specific user | A named account |
| Role | Everyone holding that role (all finance managers, say) |
| Dynamic department manager | Resolved from the requester's department manager, with a configurable number of levels upward |
Dynamic department manager is the most practical — org changes don't require revisiting workflow definitions.
Integrating into a Custom App
The approval SDK lets you build approvals directly into an application so users never switch to the Dashboard.
Server side
def execute(ctx):
# The triggering user's own queue
pending = ctx.approval.list_pending()
# A record's approval state, with per-stage detail
status = ctx.approval.get_record_status('sale_orders', order_id)
# Approve / reject as the triggering user
ctx.approval.approve(line_id, comment='Verified')
ctx.approval.reject(line_id, comment='Amount does not match the quote')
# Cancel a request (requester only, while pending)
ctx.approval.cancel(request_id, reason='Re-evaluating')
Front end
src/approval.ts provides the matching front-end methods — enough to assemble an approval panel showing history, accepting a comment, and approving or rejecting in one click.
Identity binding
The approval SDK is bound to user identity, which sets it apart from the other SDKs:
list_pending()returns the triggering user's own queue, not the organization'sapprove()verifies the triggering user is a qualified approver for that stage and refuses otherwise- Calls without a platform user identity (such as schedules) are rejected
You cannot use an application's privileges to approve on someone else's behalf.
Integrating via API
External systems can integrate the full mechanism:
GET /api/v1/approvals/record/{res_model}/{res_id}
POST /api/v1/approvals/{request_line_id}/approve
POST /api/v1/approvals/{request_line_id}/reject
POST /api/v1/approvals/{request_id}/retry
Status query returns each stage's state, approver name, comment, and timestamp, or empty if no approval was initiated.
Approve takes an approval line identifier and a comment. The system verifies eligibility; the final stage triggers the callback automatically.
Reject resets the record to draft for revision and resubmission.
Retry callback is for the case where approval fully passed but the callback failed for external reasons. An administrator can retry it manually. A failed callback does not roll the approval state back — it is an independent remediation.
Common design patterns
Tell users "submitted for approval", not "failed"
def execute(ctx):
try:
ctx.db.update('sale_orders', order_id, {'state': 'sale'})
return ctx.response.json({'status': 'updated'})
except Exception as e:
if 'approval' in str(e).lower():
return ctx.response.json({
'status': 'pending_approval',
'message': 'Change submitted for approval; it will apply once approved'
})
raise
Show approval state in lists
Batch-query with get_record_status and surface "stage 2 of 2 — finance director" directly in the list, so users don't have to open each record.
A manager's task panel
Use list_pending() to build a to-do block on the application's home screen. This is the approval SDK's highest-value use — managers never log into a separate system to sign off.
Boundaries and caveats
- One workflow per table — use conditional routing rather than multiple workflows when different paths are needed
- Ordering relative to business engines — callbacks run after approval, so invoicing, stock deduction, and journal entries happen at approval time, not at submission
- Scheduled writes — approval guards still apply; the approval UI shows the requester as "API"
- Auditing — every approval decision is fully recorded, including approver, timestamp, and comment