Travel Expense Prep Agent

Concur reconciliation & assembly assistant: a local agent that matches receipts to the corporate-card feed, itemizes hotel folios, classifies expense types and cost centers, asks one batched round of questions, and emits a per-trip prep pack — leaving receipt capture to Concur's native email intake and submission to the operator.

Status: current — reviewed & accepted Rev 3: after independent review + peer review Author: idea-to-spec loop (attended run) Reviewer of record: operator (corporate employee, technical, runs local agents) Updated: 2026-07-04 Research: research report (F1–F7, C1–C4)
Decision

Build a local agent that does the thinking — reconcile, itemize, classify, assemble — outside Concur and hands the operator a finished per-trip prep pack to transcribe and submit. No Concur write API is required for v1; no browser automation, ever; unattended submission is permanently out of scope. An IT-approved API app that assembles the draft report inside Concur is the defined upgrade path, not a prerequisite.

TL;DR

Build a local agent that takes over the two things that actually consume the operator's hours on travel expenses — matching receipts to the corporate card feed (including hotel folio itemization) and assembling the report content — while leaving receipt capture to Concur's native email intake and leaving submission to the operator. Per trip, the agent ingests receipts from two operator-controlled channels (Outlook forwarding rules, one-tap iOS Shortcut), reconciles them against a card-transaction export, itemizes folios, classifies expense types and cost centers, asks one batched round of questions for anything uncertain, and emits a prep pack that reduces the operator's in-Concur work to a fraction of today's time — transcription from the pack plus the submit click (relative time bar in AC7; the ≤ 15-minute absolute target is flagged, FA7). No Concur write API is required for v1; no browser automation, ever; unattended submission is permanently out of scope. An IT-approved API app that assembles the draft report inside Concur is the defined upgrade path, not a prerequisite.

Why

The problem, where the hours actually go, and the evidence behind the design.

Problem

The operator spends hours per trip (1–2 trips/month) on expense reports in SAP Concur. Research (F1, F7) shows capture — getting a receipt image into Concur — is largely solved by Concur's native channels (email intake, mobile app, card feed). The grill confirmed the hours go elsewhere (Q1):

1. Reconciliation

Matching each receipt to its corporate-card transaction, spotting charges with no receipt and receipts with no charge, and itemizing hotel folios (room vs tax vs parking vs meals).

2. Assembly

Picking expense types and cost centers and building the report line by line inside Concur.

No off-the-shelf product the operator can adopt unilaterally closes this gap (F7): Concur replacements (Expensify, Emburse, Ramp) are not adoptable where Concur is mandated, and Concur's own assistive features (ExpenseIt, e-receipts) are tenant-gated and still leave matching/assembly manual. Meanwhile, every agent write path into Concur beyond email is either IT-gated (API, F2) or banned (browser automation, Q3/F3). So the correct target is: an agent that does the thinking (reconcile, itemize, classify, assemble) outside Concur, and hands the operator a finished answer to transcribe and submit.

Research Inputs

This spec is grounded in a bounded research report; findings are cited as F1–F7 and constraints as C1–C4 throughout.

InputWhat It ProvesLink
Research report (F1–F7, C1–C4)Capture is natively solved by Concur; write paths beyond email are IT-gated or policy-risky; the un-solved hours are reconciliation and assembly; constraints C1–C4 bound the design.Automating Travel Receipt Reimbursement into SAP Concur
Web spot-check addendum (2026-07-04)The two findings the architecture leans on hardest are de-staled: F1a verified-email intake (verified) and F2 company-admin-gated API (verified).Report addendum
Grill record (Q1–Q7)Operator answers that shaped every load-bearing decision in this spec.Grill Record

What

Goals, non-goals, the operating contract, and the acceptance criteria that gate delivery.

Goals

Non-Goals

Proposed Behavior (Operating Contract)

Inbound channels (capture + visibility)

  1. Email receipts: operator-owned Outlook rules forward matching messages to BOTH the tenant's Concur intake address and the agent's mailbox (Q5, F4b). Concur gets the image natively; the agent gets full visibility for matching. No Graph app consent required (assumed blocked, FA1).
  2. Photo receipts: a one-tap iOS Shortcut per receipt sends the photo to BOTH the Concur intake address and the agent (Q4, F5). Same dual-delivery principle; no camera-roll access.
  3. Card feed: the operator exports/copies the trip's unassigned card transactions from Concur's "Available Expenses" view once per trip (manual, low volume per C4; format per FA3). The agent never logs into Concur to fetch them.

Processing (the actual value)

  1. Extract structured data from every ingested receipt (vendor, date, amount, currency, tax, line items where present).
  2. Reconcile: match each receipt to a card transaction with tolerance for known deltas (tips, FX conversion, pending-vs-posted amounts, date offsets). Flag in both directions: card charges with no receipt, and orphan receipts with no charge (Q6). Out-of-pocket receipts are detected and routed to their own reimbursement section rather than flagged as errors. Payment-method hints come from exactly three places: an "out-of-pocket" toggle on the iOS Shortcut, per-vendor defaults in the operator's mapping file, and batched-review answers; email receipts default to corporate card unless a hint says otherwise. Foreign-currency out-of-pocket receipts keep their original currency and amount in the pack, and rate handling (Concur applies the tenant's rate at entry) is surfaced in the batched review rather than converted silently.
  3. Itemize hotel folios into the tenant's Concur categories (room rate, taxes, parking, meals, internet, other), with lines summing to the folio total (Q6).
  4. Classify each line with expense type and cost center using an operator-maintained mapping file (vendor/category → expense type, project → cost center). Anything below confidence threshold goes to the held queue, not into the pack (Q7).
  5. Batched review: one interactive Q&A round per trip resolving all held items (ambiguous matches, unknown expense types, missing receipts the operator may still have). Reconciliation against the card feed doubles as the capture-gap detector: a charge with no receipt means a receipt never got forwarded/photographed.

Output — the prep pack (per trip)

  1. A single document containing, in Concur entry order:
    • reconciliation table: card transaction ↔ receipt ↔ expense type ↔ cost center ↔ amount, one row per report line;
    • hotel folio itemization blocks ready to transcribe;
    • out-of-pocket section (own reimbursement lines);
    • exceptions: unmatched charges, orphan receipts, and items the operator chose to exclude, each with the decision recorded;
    • a completion checklist (receipts visible in Available Receipts, totals tie out).
  2. The operator opens Concur, builds the report from the pack (receipts already waiting in Available Receipts via native intake), reviews, and submits. Target ≤ 15 minutes (aspirational, FA7).

Upgrade path (v2, gated on IT approval — see Rollout): with an IT-approved OAuth app (F2), steps 9–10 change shape: the agent creates the draft report and entries via Concur's Expense APIs and the prep pack shrinks to a review sheet. The Q2 contract is unchanged: the operator still reviews and submits.

Acceptance Criteria

IDCriterionEvidence Expectation
AC1Setup verification, both real message shapes: (a) a receipt image emailed from the operator's verified address appears in Concur Available Receipts and reaches the agent mailbox via the Outlook rule; (b) a real vendor confirmation (HTML body, no attachment) processed by the Outlook rule is accepted by Concur intake and received by the agent — verifying that the rule's forward-vs-redirect behavior presents a sender Concur's verified-address check accepts.Recorded setup checklist with screenshots/message IDs for both message shapes at both destinations; note of which rule action (forward or redirect) passed the sender check.
AC2One-tap capture: the iOS Shortcut, invoked on a single receipt photo, delivers it to both Concur intake and the agent without any camera-roll scan.Shortcut definition (shows share-sheet input, no library query) + the test photo present in both destinations.
AC3Full-coverage reconciliation: for a real trip, every card transaction in the supplied export is either matched to a receipt or listed as an unmatched charge, and every ingested receipt is either matched, classified out-of-pocket, or listed as an orphan — with a misrouting cross-check: no card transaction is left unmatched while a receipt that plausibly matches it (same vendor/date/amount within the tolerance windows) sits in the out-of-pocket or orphan sections.The trip's prep pack: reconciliation table + exceptions section jointly account for 100% of transactions and receipts; totals tie out to the export; cross-check output shows zero plausible matches hidden across sections.
AC4Folio itemization: each hotel folio in the trip is itemized into the tenant's categories with lines summing to the folio total (± rounding).Itemization block in the prep pack; arithmetic check against the folio image.
AC5Out-of-pocket path, both directions: a receipt with no card transaction and an out-of-pocket payment hint lands in the out-of-pocket section, not in exceptions; and the AC3 cross-check confirms no card-paid receipt is misrouted into out-of-pocket (which would hide a real card match).Prep pack for a trip (or injected test receipts, one per direction) showing correct routing both ways.
AC6No silent guessing: every line in the pack below the configured confidence threshold appeared in the batched Q&A before entering the pack; the pack contains no unresolved held items. The threshold is operator-configurable with a conservative default (see Architecture); a zero/disabled threshold fails this criterion as vacuous.Held-queue log for the trip cross-referenced against pack lines, plus the configured threshold value recorded; zero pack lines flagged low-confidence-unreviewed.
AC7Time win (relative): operator's in-Concur time (open report → submit) is ≤ 25% of the phase-0 pre-agent baseline, on 2 consecutive real trips using the pack. The absolute ≤ 15-minute target remains aspirational until the operator sets it as a bar (FA7).Operator-recorded timings for both trips plus the phase-0 baseline and per-trip line volume; reduction computed; absolute time noted against the 15-minute aspiration.
AC8Containment: the agent's only interaction with Concur is outbound email to the tenant intake address; no stored Concur credentials, no browser automation, no Concur API calls in v1; and the agent has no photo-library API access (photos enter only via the Shortcut, completing AC2's agent-side proof).Code/config inspection (including absence of photo-library access) + outbound network/audit listing for a processed trip.

How

Implementation design, the grill decisions behind it, flagged assumptions, risks, and rollout.

Architecture

Local agent on the operator's machine (C2). Components:

Setup (one-time)

Verify tenant intake address and verified-email registration (FA2); register the operator's sending addresses; build the Shortcut; create Outlook rules; write the initial expense-type/cost-center mapping; confirm a workable card-export method (FA3).

Grill Record

Conducted after research, per the loop. Each answer traces to what it changed in this spec.

#QuestionAnswer (decision)What It Changed
Q1Kill question: Concur natively covers capture — where do the hours actually go, and should this be built at all?Build it, aimed at reconciliation (receipt↔card matching, folio itemization) and classification/assembly — not capture. Use Concur native intake for capture.Entire framing: Why section, G1, non-goal "re-implementing capture", behavior steps 4–9.
Q2End-state contract: unattended submit, draft-then-submit, or capture-only?Agent assembles a complete draft; operator reviews and clicks submit. Unattended submission of the financial attestation is off the table permanently.Non-goal #1 (permanent), behavior step 10, unchanged contract in the v2 upgrade path.
Q3Write path: pursue API access? Is browser automation of the SSO'd session acceptable?API access will be requested but is 50/50 and months away; browser automation is banned regardless. v1 must deliver value with no Concur write API.The prep-pack architecture itself (v1 has no API dependency, C1), non-goal #2, AC8, Rollout gating.
Q4Photo channel: iCloud library scan, per-receipt iOS Shortcut, or manual dump?One-tap iOS Shortcut per receipt; no whole-library scanning.Inbound channel 2, non-goal #3, AC2.
Q5Mailbox access: Graph delegated consent vs Outlook forwarding rules?Assume user app consent is blocked (flag it). Operator-owned Outlook rules forward matching mail to BOTH Concur intake and the agent's mailbox.Inbound channel 1, FA1, FA5 (agent-mailbox placement), AC1.
Q6Depth: full reconciliation or capture-and-classify?Full reconciliation — match receipts to card feed, flag unmatched/orphans in both directions, itemize folios. Out-of-pocket items get their own path.G1, G5, behavior steps 5–6, AC3–AC5, the card-export requirement (FA3).
Q7Error tolerance: hold-and-ask or best-guess?Hold uncertain items; one batched review per trip. Never guess silently — wrong lines cause finance resubmit cycles.G2, behavior step 8, held-queue design in Architecture, AC6.

Independent review and peer review raised two additional load-bearing questions the operator has not yet answered: (1) may receipt/folio contents be sent to a cloud LLM API, or must extraction run on a local model? — recorded as flagged assumption FA6; (2) is the ≤ 15-minute absolute in-Concur time a hard bar or an aspiration, given the pack still requires manual transcription? — recorded as FA7, with AC7's binding bar made relative to the phase-0 baseline. Per the loop rules neither is defaulted silently. One smaller operator question remains open alongside it — whether trips are international — but behavior step 5 is defined regardless of the answer (original currency preserved; rate handling surfaced in the batched review, never converted silently), so it constrains tuning, not the contract. Filing the v2 OAuth-app request is resolved: assigned to the operator in phase 0.

Flagged Assumptions

Named, unverified; each has a verification step in Rollout phase 0.

Risks

Rollout

PhaseScopeExit Criteria
Phase 0 — verify (no code)Confirm FA1–FA7 against the live tenant and policy: send a test receipt image AND a rule-forwarded vendor confirmation to the intake address, check Available Receipts, attempt a card-transaction export, read the acceptable-use/DLP policy for mailbox placement, local data-at-rest, and cloud-LLM use (FA5, FA6). Record one pre-agent trip's in-Concur time AND its line volume (report lines + folio sub-lines) as the AC7 baseline; operator then decides whether ≤ 15 min absolute becomes a bar (FA7). Operator files the v2 OAuth-app request with IT now, so the months-long approval clock (Q3) runs in parallel with all phases.AC1 evidence recorded, FA3 method chosen, FA6 and FA7 resolved, baseline logged, IT request submitted.
Phase 1 — capture plumbingOutlook rules + iOS Shortcut + agent mailbox ingest.AC1, AC2.
Phase 2 — reconciliation coreExtraction, matching, folio itemization, out-of-pocket routing, held queue, batched review, prep-pack render.AC3–AC6 on one real trip.
Phase 3 — measureTwo consecutive real trips end-to-end.AC7, AC8.
v2 (gated, not scheduled)If IT approves an OAuth app (Q3, F2), add API-based draft-report assembly; operator review/submit contract (Q2) unchanged.Reopen trigger: IT approval lands.

Why Not

Rejected alternatives and the reasoning behind each.

Alternatives Rejected

AlternativeWhy Not
Browser automationBanned by the operator regardless of API status (Q3); independently fragile and policy-risky against an SSO'd financial system of record (F3).
Wait for API access first50/50 odds, months of delay (Q3). The prep pack delivers the reconciliation/assembly win now; the API only changes who types the result into Concur.
Scan the iCloud photo libraryOperator rejected whole-library scanning outright (Q4); one tap per receipt is an acceptable cost at this volume (C4).
A capture-focused agent (auto-OCR-and-upload)Capture is already solved natively by Concur (F1); the hours are in reconciliation and assembly (Q1). Rebuilding capture adds risk without addressing pain.
Unattended submissionExpense submission is a personal financial attestation; the industry pattern is auto-draft + human confirm (F6), and the operator ruled it out permanently (Q2).
Expensify/Ramp/EmburseWhole-system replacements; Concur is corporately mandated (F7).