YUS200619's picture
feat: complete invoice exception handler v1.0.0
562f58d
# openenv.yaml
name: Invoice Exception Handler
version: "1.0.0"
description: |
An agent learning environment simulating accounts payable exception handling.
The agent acts as an AP analyst: investigates flagged invoices, applies business
rules, detects fraud signals, makes decisions, and closes cases with an audit trail.
authors:
- name: Moahmmed Yusuf, Nadella Harshith
email: [yusufindian09@gmail.com] [nadellaharshith4@gmail.com]
license: MIT
tasks:
- id: task1_price_variance
name: Price Variance Exception
difficulty: easy
description: |
Office stationery invoice arrives 3.08% above PO. Company tolerance policy
allows +/-2% auto-approval. Agent must detect the variance, verify through
the tolerance rule, confirm verbal approval with procurement, and approve
with a PO amendment request.
max_steps: 18
optimal_score: 1.0
min_passing_score: 0.60
- id: task2_duplicate_tax
name: Duplicate Invoice with Tax Error
difficulty: medium
description: |
Logistics supplier submits INV-2024-891, a duplicate of paid INV-2024-819
(digit transposition: 891 vs 819). Original invoice had wrong GST rate (15%
vs correct 18%) — company overpaid 3,240 INR. New invoice has correct rate.
Agent must detect the duplicate, identify the tax error in the original,
and partially approve only the 3,240 INR tax correction.
max_steps: 20
optimal_score: 1.0
min_passing_score: 0.50
- id: task3_compound_fraud
name: Compound Fraud Signals
difficulty: hard
description: |
IT equipment supplier invoice with four simultaneous fraud signals: bank
account changed via BEC attack (lookalike email domain), GSTIN belongs to
a different entity, 2 of 15 laptops not yet received, and unit price 8.65%
above PO. Agent must find all signals, use the correct communication channel
(phone, not email — which would contact the fraudster), and escalate to legal
and security.
max_steps: 25
optimal_score: 1.0
min_passing_score: 0.40
observation_space:
type: object
description: EnvironmentState Pydantic model
fields:
task_id: {type: string}
step_number: {type: integer}
case_status: {type: string, enum: [open, in_review, decided, routed, closed]}
purchase_order: {type: object, description: "PO with line items and terms"}
invoice: {type: object, description: "Supplier invoice with line items and tax"}
grn: {type: object, description: "Goods receipt — what actually arrived"}
supplier_master: {type: object, description: "Verified supplier record"}
exception_flag: {type: object, description: "Why the system flagged this invoice"}
inspections: {type: array, description: "Fields the agent has inspected"}
checks_run: {type: array, description: "Validation checks completed"}
queries: {type: array, description: "Internal and supplier queries"}
rules_applied: {type: array, description: "Business rules applied"}
decision: {type: string, nullable: true}
routed_to: {type: array}
available_actions: {type: array}
available_checks: {type: array}
available_rules: {type: array}
knowledge_base: {type: array}
cumulative_reward: {type: number}
action_space:
type: object
description: Action with type and params
actions:
inspect_field:
params: {document: string, field: string}
cross_check:
params: {field: string, doc_a: string, doc_b: string}
run_check:
params: {check_name: string}
query_supplier:
params: {question: string, channel: string}
query_internal:
params: {department: string, question: string}
apply_rule:
params: {rule_id: string}
make_decision:
params: {decision: string, reason: string}
route_to:
params: {team: string, notes: string}
close_case:
params: {summary: string}
reward:
range: [-1.0, 1.0]
description: |
Shaped reward at every step. Relevant inspections: +0.01 to +0.14.
Diagnostics revealing issues: +0.08 to +0.18. Correct fixes: +0.08 to +0.30.
Wrong decision on fraud: -0.15 to -0.40. Repeat actions: -0.02 to -0.05.
SLA breach: -0.10.
grading:
method: task_grader
scores:
- score
- diagnosis_score
- investigation_score
- decision_score
- routing_score
- closure_score
- efficiency_score
api:
reset:
signature: "reset(task_id: str | None = None) -> EnvironmentState"
step:
signature: "step(action: Action | dict) -> StepResult"
state:
signature: "state() -> EnvironmentState"
grade:
signature: "grade() -> Dict[str, float]"
http_endpoints:
- path: /reset
method: POST
description: Reset environment, returns EnvironmentState JSON
- path: /step
method: POST
description: Execute action, returns StepResult JSON
- path: /state
method: GET
description: Current state, returns EnvironmentState JSON
- path: /grade
method: POST
description: Grade current episode
- path: /health
method: GET
description: Health check
dependencies:
python: ">=3.10"
packages:
- pydantic>=2.7
- fastapi>=0.111
- uvicorn>=0.29
- gradio>=4.36
- openai>=1.35
- pyyaml>=6.0
docker:
port: 7860
health_check: /health