Introduction
Here’s a second, production-grade agent you can lift into your stack today: an Expense Report Auditor & Reimbursement Agent. It reads a submitted expense, checks policy eligibility, flags issues, and—when allowed—creates a reimbursement. As before, the agent never claims success unless the backend executed the action and returned a receipt.
The Use Case
Employees submit expenses (amount, category, merchant, date, receipt image URL). The agent should verify policy limits, check duplicate submissions, validate receipt presence, and either propose a reimbursement or request corrections. All decisions must cite policy facts; all actions must yield receipts.
Prompt Contract (the agent’s interface)
# file: contracts/expense_auditor_v1.yaml
role: "ExpenseAuditor"
scope: >
Audit a single expense. Use eligible claims for policy facts and prior submissions.
Ask once for missing fields (amount_cents, category, date, merchant, receipt_url).
Propose tool calls; never assert success without a receipt.
output:
type: object
required: [summary, findings, decision, citations, tool_proposals]
properties:
summary: {type: string, maxWords: 60}
findings: {type: array, items: {type: string, maxWords: 18}, maxItems: 8}
decision: {type: string, enum: ["approve","approve_with_adjustment","reject","need_more_info"]}
citations: {type: array, items: {type: string}}
tool_proposals:
type: array
items:
type: object
required: [name, args, preconditions, idempotency_key]
properties:
name: {type: string, enum: [CheckDuplicates, CheckPolicy, CreateReimbursement]}
args: {type: object}
preconditions: {type: string}
idempotency_key: {type: string}
policy_id: "expense_policy.v5.us"
citation_rule: "1-2 minimal-span claim_ids per factual sentence"
decoding:
narrative: {top_p: 0.92, temperature: 0.72, stop: ["\n\n## "]}
bullets: {top_p: 0.82, temperature: 0.45}
Example claims (context shown to the model)
[
{"claim_id":"policy:meal:cap_usd","text":"Meal expenses capped at $75 per person per day.",
"effective_date":"2025-06-01","source_id":"doc:policy_v5","span":"capped at $75"},
{"claim_id":"policy:receipt_required_over_25","text":"Receipts required for any expense over $25.",
"effective_date":"2025-06-01","source_id":"doc:policy_v5","span":"over $25"},
{"claim_id":"policy:no_alcohol_reimbursed","text":"Alcohol is not reimbursable.",
"effective_date":"2025-06-01","source_id":"doc:policy_v5","span":"not reimbursable"},
{"claim_id":"history:merchant:dup_hash:2025-10-04","text":"Expense hash MERCH123-2025-10-04-2599 filed by user U007.",
"effective_date":"2025-10-04","source_id":"sys:expenses","span":"filed by user U007"}
]
Tool Interfaces (typed, with receipts)
# tools.py
from pydantic import BaseModel, Field, HttpUrl
from datetime import date
from typing import Optional, Dict
class CheckDuplicatesArgs(BaseModel):
user_id: str
merchant: str
amount_cents: int
expense_date: date
class CheckPolicyArgs(BaseModel):
category: str
amount_cents: int
attendees: Optional[int] = Field(default=1)
has_receipt: bool
contains_alcohol: bool
class CreateReimbursementArgs(BaseModel):
user_id: str
amount_cents: int
expense_id: str
memo: str
class ToolReceipt(BaseModel):
tool: str
ok: bool
ref: str
message: str = ""
data: Optional[Dict] = None
# adapters.py (demo logic)
from tools import *
from datetime import date
DUP_DB = {("U007","MERCH123",2599,date(2025,10,4)): "exp-abc"} # prior expense key
MEAL_CAP_CENTS = 7500 # $75
def check_duplicates(a: CheckDuplicatesArgs) -> ToolReceipt:
key = (a.user_id, a.merchant, a.amount_cents, a.expense_date)
if key in DUP_DB:
return ToolReceipt(tool="CheckDuplicates", ok=False, ref="dup-found",
message="Duplicate submission", data={"prior_expense_id": DUP_DB[key]})
return ToolReceipt(tool="CheckDuplicates", ok=True, ref="dup-none", message="No duplicate detected")
def check_policy(a: CheckPolicyArgs) -> ToolReceipt:
if a.amount_cents > 2500 and not a.has_receipt:
return ToolReceipt(tool="CheckPolicy", ok=False, ref="pol-receipt", message="Receipt required > $25")
if a.category.lower() == "meal" and a.amount_cents > MEAL_CAP_CENTS * a.attendees:
return ToolReceipt(tool="CheckPolicy", ok=False, ref="pol-meal-cap",
message="Exceeds meal cap", data={"cap_cents": MEAL_CAP_CENTS * a.attendees})
if a.contains_alcohol:
return ToolReceipt(tool="CheckPolicy", ok=False, ref="pol-alcohol", message="Alcohol not reimbursable")
return ToolReceipt(tool="CheckPolicy", ok=True, ref="pol-ok", message="Eligible under policy")
def create_reimbursement(a: CreateReimbursementArgs) -> ToolReceipt:
return ToolReceipt(tool="CreateReimbursement", ok=True, ref=f"rb-{a.expense_id}",
message="Reimbursement created", data={"amount_cents": a.amount_cents})

Join the conversation! Your thoughts help the community grow.