Phase 2 integration tests verify that data passes correctly between agents and that the orchestration layer handles agent handoffs without data loss or schema mismatch. All tests run in sandbox. IDs continue from the Phase 1 sequence.
ID
Scenario
Input
Expected Output
Pass Criteria
T15
Handoff: Agent 1 passes PASS verdict to Agent 2
Agent 1 completes T01 scenario and emits output payload to the orchestration layer
Agent 2 receives payload with all required fields: claim_id, amount, merchant, currency, receipt_url, policy_verdict=PASS.
Agent 2 input schema validated. All required fields present and correctly typed. No null values in mandatory fields.
T16
Handoff: Agent 1 FAIL verdict does not trigger Agent 2
Agent 1 emits FAIL verdict with flag reason
Orchestration layer routes to Gmail chase flow. Agent 2 is not invoked. Agent 2 logs show no execution event.
Agent 2 execution count remains zero for this claim. Gmail chase payload dispatched. Claim held in 'awaiting receipt' status.
T17
Handoff: Agent 2 passes Xero draft record ID to Agent 3
Agent 2 completes T08 scenario and emits output payload
Agent 3 receives payload with xero_draft_id, employee_id, department, amount, and manager_slack_id populated.
Agent 3 input schema validated. xero_draft_id is a valid non-null string. manager_slack_id resolves to a known Slack user in the test workspace.
T18
Approval: Agent 3 finalises Xero record on manager approval
Manager clicks Approve in Slack (sandbox); Agent 3 receives webhook callback
Xero record status updated from draft to authorised. Gusto sandbox reimbursement line created. Confirmation Gmail sent to test employee address.
Xero sandbox record status equals 'AUTHORISED'. Gusto sandbox shows new reimbursement line with correct amount and employee ID. Gmail delivery confirmed via sandbox SMTP log.
T19
Gusto reimbursement line creation
Approved Xero record with amount=$85.00, employee_id=EMP-009 (sandbox)
Gusto sandbox API call POST /v1/employees/EMP-009/reimbursements returns HTTP 201. Reimbursement amount=$85.00 in next payroll cycle.
HTTP 201 received. Reimbursement record ID returned and logged. Amount matches approved claim amount. Payroll cycle date field populated.
T20
Gmail confirmation email: correct content and recipient
Approved claim; employee email=test-employee@[YourCompany.com]; payroll date=next Friday
Gmail sends confirmation email to test-employee@[YourCompany.com] with subject 'Your expense claim has been approved' and payroll date in body.
Email delivered to sandbox inbox. Subject line matches template. Payroll date string appears in body. No other recipients in To or CC fields.
T21
Full sequential run: compliant claim from submission to Gusto
Employee submits compliant Expensify claim in sandbox; all three agents execute in sequence
Claim passes Agent 1 policy check, GL coded by Agent 2, approved via Slack by Agent 3, Xero record authorised, Gusto line created, confirmation email sent.
All six downstream outputs present and correct. Total elapsed time from trigger to final Gmail under 3 minutes in sandbox. Zero manual interventions required.
T22
Full sequential run: non-compliant claim from submission to finance admin flag
Employee submits over-limit Expensify claim; amount $450.00, category Meals
Agent 1 returns FAIL. Gmail chase or rejection email sent. Agents 2 and 3 not invoked. Finance admin notified with flag reason.
Agents 2 and 3 show zero execution events for this claim. Gmail notification sent. Finance admin Slack alert or email received in sandbox.
Edge-case tests target boundary conditions that are most likely to cause silent failures or data corruption in a production environment. Each scenario is assigned an E-series ID.
ID
Scenario
Input
Expected Output
Pass Criteria
E01
Duplicate submission: same claim submitted twice by employee
Employee submits identical Expensify claim (same amount, merchant, date) twice within 10 minutes
Deduplication check triggers on second submission. Second claim flagged as probable duplicate. Finance admin alerted. First claim continues processing normally.
Second claim receives status 'duplicate-flagged'. Only one Xero draft record created. Finance admin receives duplicate alert message.
E02
Missing employee mapping: submitter not in manager assignment table
Expensify claim submitted by employee ID EMP-099 (not in department-manager mapping table)
Agent 3 cannot resolve manager_slack_id. Claim held with status 'manager-unresolved'. Finance admin notified to assign manager manually.
No Slack message sent to an incorrect manager. Finance admin notification sent with employee ID and claim details. Claim status set to 'manager-unresolved'.
E03
Expensify webhook delivery failure: payload not received by orchestration layer
Expensify fires webhook; orchestration layer returns HTTP 500
Expensify retries webhook up to three times per its default retry policy. If all retries fail, claim appears in Expensify with no processing status. FullSpec alerting fires within 15 minutes.
FullSpec monitoring alert triggered within 15 minutes of first failed delivery. Claim not silently dropped. Retry attempts logged.
E04
Xero API rate limit hit during bulk submission
10 expense claims submitted simultaneously in Expensify (simulating month-end batch)
Orchestration layer queues Xero API calls with exponential back-off. All 10 claims eventually processed. No claims dropped. No duplicate Xero records.
All 10 Xero sandbox records created. No HTTP 429 errors propagate as failures. Queue depth and retry counts visible in orchestration logs.
E05
Slack unavailable: API returns HTTP 503 during approval routing
Agent 3 attempts to send Slack approval message; Slack API returns HTTP 503
Retry logic executes up to three times at 60-second intervals. After third failure, fallback Gmail approval email sent to manager. Claim status updated to 'slack-fallback'.
Fallback Gmail sent to manager's email address. Claim status equals 'slack-fallback'. Three Slack retry attempts logged before fallback triggered.
E06
Manager approval timeout: no response after 48 hours
Slack approval message sent; 24-hour reminder sent; still no response after simulated 48-hour window
Claim escalated to finance manager (secondary approver). Escalation Slack message and Gmail sent. Claim status updated to 'escalated'.
Escalation message sent to finance manager contact. Original manager's 24-hour reminder confirmed as already sent. Claim status equals 'escalated'.
E07
GL mapping table returns multiple possible codes: ambiguous merchant
Passing claim; merchant='Amazon', which maps to both Office Supplies (GL 430) and IT Equipment (GL 610)
Agent 2 selects the highest-frequency match from historical mapping. Flags the record with 'Multiple GL codes possible' for finance admin review. Draft Xero record created with selected code.
Xero draft record created. Flag field contains 'Multiple GL codes possible' with both candidate codes listed. Finance admin notified.
E08
Gusto API rejects reimbursement: employee not on active payroll
Approved claim for employee EMP-045; Gusto returns HTTP 422 'Employee not found or inactive'
Reimbursement line not created. Finance admin notified with error detail. Claim status updated to 'reimbursement-failed'. Xero record remains authorised.
No Gusto reimbursement record created. Finance admin notification contains HTTP 422 detail and employee ID. Xero record status unchanged (authorised).