Sebastian Angeltvedt's website

LovAgent - agentic search for tax and accounting

I remember when most coding tools relied on RAG to gather the sufficient context for their task. When the models got good enough, we shifted towards using multistep tool-calling to do it instead. I saw that nobody had tried doing the same for Norwegian legal agents, so I experimented with it.

Screenshot of LovAgent interface showing a chat about an invoice
Screenshot of LovAgent interface showing a chat about an invoice

I’ve set up a live demo at lovagent.angeltvedt.net.

While agentic search is much slower than RAG, I found it more thorough. Especially on tasks involving a “complete picture” or an overview. For example, if one were to ask a RAG-system for an overview of all the deadlines a sole proprietor has to be aware of, it would most likely miss some. However, when the model can use tools to search, the likelihood of a complete response dramatically improves.

RAG and agentic search are not mutually exclusive though, and I think there is massive speed and effectiveness gains to be had by creating a hybrid solution. LovAgent currently does not do this.

Dataset

I put a lot of effort into building the dataset as complete as possible. When Lovdata finally made the consolidated laws and regulations of Norway open, that started to make this project possible. But laws and regulations alone are not sufficient. There are also standards, manuals, rates, etc. To make it a little easier, I chose to focus my efforts within one niche: accounting and tax. I currently have four sources:

  • Laws and regulations from Lovdata
  • Standards from NRS.
  • Handbooks from Skatteetaten (Tax Administration)
  • Information about NS 4102 (Norwegian Standard Charts of Accounts)

NRS exclusively publishes their standards in PDF, so I had to use OCR models to extract the text. I found that Qwen3 VL 235B A22B Instruct was the cheapest model that provided satisfactory accuracy.

This is by no means exhaustive. The biggest and most important omission is court decisions. These are sadly not publicly available.

These sources are not actively updated, so they may become outdated.

LLM Model

I tested tons of different models. At first I assumed the best performers at agentic benchmarks would be the best fit. However, I quickly found out that many of these models are seemingly not capable of talking Norwegian. Some were also way too expensive. I found that Minimax-M2.1 struck a good balance between capability and price, while still being pretty good at Norwegian! Gemini 3 Flash was also a good contender, even slightly better than Minimax, but much more expensive.

Web App

The web app uses React on the frontend, with a Go server at the backend.

The streaming from OpenRouter is done at the server side, and clients merely subscribe to this when viewing the session. This creates the best UX as you can leave the session while it’s generating, and is a common pattern of LLM chat apps.

The rendering was a bit tricky. Rendering markdown live from a stream is harder than I first thought. You can’t just use a run-of-the-mill markdown parser, as it can’t progressively and optimistically build elements and only update the DOM with new content. The de-facto standard for this right now seems to be streaming-markdown, and I based the internal parser on this.