Skip to content

IgloooNOR/nmai-2026-tripletex

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 

Repository files navigation

NM i AI 2026 — Tripletex AI Accounting Agent

Team: Fenrir's Byte
Challenge: Tripletex — AI Accounting Agent
Competition: NM i AI 2026 (Norway's National AI Championship)

consider buying me a coffee: https://buymeacoffee.com/iglooo

What I Built

A fault-tolerant AI accounting agent that accepts natural-language task prompts (in 7 languages) and executes them against the Tripletex v2 REST API. The agent handles 30+ distinct accounting task types — from creating employees and invoices to year-end closing and ledger analysis.

Architecture

POST /solve
     │
     ▼
┌─────────────────────┐
│   PDF/File Parser   │  ← base64 decode, Gemini vision extract
└─────────────────────┘
     │
     ▼
┌─────────────────────┐
│   LLM Router        │  ← Gemini 2.5 Flash classifies task + extracts JSON data
│   (ROUTER_PROMPT)   │
└─────────────────────┘
     │ task_type + data
     ▼
┌─────────────────────┐      ┌──────────────────────────┐
│ Deterministic       │─────▶│ 21 hardcoded handlers    │
│ Handler dispatch    │      │ (create_employee, invoice,│
│                     │      │  travel_expense, etc.)    │
└─────────────────────┘      └──────────────────────────┘
     │ handler returns False
     ▼
┌─────────────────────┐
│ LLM Fallback        │  ← ReAct loop, up to 35 iterations
│ (tripletex_api_call │     Gemini decides which API calls to make
│  tool)              │
└─────────────────────┘
     │
     ▼
  {"status": "completed"}

Key Design Decisions

LLM Router → Deterministic → Fallback layering: Most tasks hit a deterministic Python handler (fast, accurate, no token waste). If the handler fails or the task is too complex, the LLM fallback loop takes over with full API access.

fix_call() interceptor: All API calls pass through a normalisation function that corrects common LLM mistakes — POST → PUT on action endpoints, body → query params for /:payment, /:invoice, /:deliver, etc.

get_vat_type() with directional matching: Norwegian VAT has both sales (utgående) and purchase (inngående) types at the same percentage. I built keyword matching that distinguishes direction per call site, extended with multilingual keywords (befreit, exento, fradrag, libéré).

ensure_bank_account(): Tripletex refuses to generate invoices without a registered bank account. Every invoice-creating handler calls this first to set a valid MOD11 Norwegian account number on ledger account 1920, also setting isInvoiceAccount: true.

File context pipeline: PDFs are decoded and passed as _file_ctx (readable text) into handler data, enabling regex scraping for occupation codes, bank account numbers, and other fields that LLMs sometimes miss.

Deterministic Handlers (21)

Handler Task
create_employee Full onboarding: dept, employment details, standard time, occupation code
create_customer Customer with address
create_supplier Supplier registration
create_product Product catalogue
create_department Department creation
create_invoice Multi-line invoice with per-line VAT
register_payment Full payment using amountOutstanding
reverse_payment Negative payment reversal
supplier_invoice AP voucher with purchase VAT, PDF attachment
create_credit_note Credit note via /:createCreditNote
create_travel_expense Per-diem loop + costs, deliver
delete_travel_expense Travel expense deletion
create_project Project with manager
project_hours_invoice Timesheet + invoice
project_milestone Fixed-price project + partial invoice
project_lifecycle Full lifecycle: customer→PM→project→timesheets→supplier cost→invoice
currency_payment Agio/disagio exchange rate adjustments
post_voucher Manual voucher with VAT auto-detection
create_dimension Accounting dimensions + linked voucher
process_salary Salary split (base + bonus) with employee tags
year_end_closing Depreciation + prepaid reversal + tax provision
ledger_analysis Cross-period expense comparison, top-3 project creation

Tech Stack

  • Runtime: Python 3.11, FastAPI, uvicorn
  • AI: Google Gemini 2.5 Flash via Vertex AI
  • Infrastructure: Google Cloud Run (europe-west1)
  • Auth: Tripletex Basic Auth (0:<session_token>) via competition proxy

Running Locally

pip install fastapi uvicorn requests google-genai
export GCP_PROJECT_ID=your-project
uvicorn main:app --host 0.0.0.0 --port 8000

Repository Structure

main.py          # Full agent (~2400 lines) — router, handlers, fallback, API client
README.md        # This file
REPORT.md        # Detailed challenge report
LICENSE          # MIT

License

MIT — see LICENSE

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages