Running LLM Agents in Production for Accounting Automation

digits · Finance · 2025 · source Agentic: yes · promotional bias: low · source-backed · extracted with prompt 0.5.6 (schema v2)

Generated from extraction.json — do not edit by hand. Every claim cites verbatim source evidence; stated means the quote directly asserts the claim, implied means it supports it indirectly.

Problem

Domain: Accounting automation with production LLM agents

Digits needed to run LLM agents for bookkeeping and accounting workflows such as vendor hydration, onboarding simplification, and natural-language financial questions, while preserving production permissions, reliability, observability, memory, guardrails, and non-Python backend constraints.

Constraints:

Architecture

Digits evolved from a simple 100-200 line agent loop into a production agent platform. Agents start with an objective, call tools, and answer user or background tasks, but production adds an LLM proxy for model switching and fallbacks, curated API-to-tool schemas over existing permissioned services, Phoenix-based observability, memory services for short- and long-term preferences, guardrails and LLM-as-judge checks, and human review when confidence is low.

Diagram confidence: reconstructed (reconstructed from prose).

flowchart LR
  A["Accounting workflow request"] --> B["Agent loop"]
  B --> C["LLM proxy"]
  B --> D["API tool adapter"]
  D --> E["Permissioned backend APIs"]
  B --> F["Memory service"]
  B --> G["Guardrail evaluator"]
  B --> H["Phoenix observability"]
  G --> I["Human review path"]
  H --> I
  I --> A
Drag to pan · scroll or use +/− to zoom · reconstructed from the source's described component topology

Components

Component Role Interacts with
Accounting workflow request Vendor hydration, onboarding inference, or book-question task that needs agentic execution. Agent loop
Agent loop Objective-driven LLM loop that plans, calls tools, and produces a response or action. LLM proxy, API tool adapter, Memory service, Guardrail evaluator, Phoenix observability
LLM proxy Routes calls across model providers and supplies fallback behavior when providers fail. Agent loop
API tool adapter Converts curated backend APIs/RPC definitions into JSON schemas that agents can call. Permissioned backend APIs
Permissioned backend APIs Existing Digits services with authorization and business logic already built in. API tool adapter
Memory service Compresses interaction history into short-term and long-term preferences. Agent loop
Guardrail evaluator Checks responses for reasonableness, confidentiality, harm, and task-specific policies. Human review path
Phoenix observability Traces prompts, tool calls, responses, latency, costs, and guardrail outcomes. Agent loop, Human review path
Human review path Escalates uncertain outputs to users, captures feedback, and updates the system. Accounting workflow request

Data flow

A vendor, onboarding, or financial-question task enters an agent loop. The agent routes model calls through an LLM proxy, plans and calls curated API-backed tools, observes prompts/tool calls/latency/cost through Phoenix, optionally consults memory, and passes outputs through guardrails or human review. High-confidence classifications can ship automatically, while lower-confidence ones are surfaced to users for correction and learning.

3 supporting quotes
“there's an LLM and you have a loop and it starts with an objective. Uh, the LLM makes some tool calls and at some point it gives you a response.”transcript, stated
“we use um a our existing APIs and use then the tools to connect with them. And the big diff the big benefit of that is those existing APIs already have per permissioning built in.”transcript, stated
“we have an average of like 96% um acceptance rate on those things and only like 3% of uh questions actually bubble up to the end user”transcript, stated

Why this architecture

Digits kept the agent loop simple but surrounded it with production infrastructure. Existing APIs preserved permissions, a proxy handled provider choice and outages, observability made multi-tool behavior debuggable, memory compressed learned preferences, and guardrails/human review prevented low-confidence or unsafe outputs from silently reaching users.

3 supporting quotes
“We didn't wanted to reimplement our entire like uh backend stack just to make it a gentic.”transcript, stated
“replace your LLM calls with an actual LLM proxy because then it allows you the switching between the different use cases but also gives you the fallback option”transcript, stated
“So agent observability is key”transcript, stated

Models used: LLMs · LLM-as-judge · Phoenix · Memory tools

Scale

Alternatives considered (roads not taken)

Use a full agent framework directly

Rejected because: Framework dependencies increase audit and security complexity, and Python decorators did not fit Digits' Kotlin/Golang production stack.

“they come with a ton of dependencies. So in our use in in our use case we have to go through various audits for security etc. So they increase the complexity drastically.”transcript, stated

Manually define every tool schema

Rejected because: Manual tool definitions do not scale beyond a handful of tools.

“for every tool you would write what is my schema what is the objective um what does this tool want and what does the tool provide that is extremely timeconuming.”transcript, stated

Expose all backend RPCs as tools

Rejected because: Raw RPC definitions were noisy, so Digits curated the API surface and converted selected APIs to JSON schema.

“we can use those RPCs and that was extremely noisy. There's a lot of code in those RPC definitions that does not directly apply to the definition of the tools”transcript, stated

Store raw LLM outputs as memory

Rejected because: Concatenated outputs are storage, not compressed preference memory.

“Uh storage is not memory and memory is not storage.”transcript, stated

Patterns

tool-use-orchestration (orchestration)

Digits connects agents to curated existing APIs through tool schemas so agents can act inside permissioned accounting systems.

“we use um a our existing APIs and use then the tools to connect with them.”transcript, stated
“we use like um the inflection or introspect to convert our APIs into a JSON schema and then most tools or most frameworks understand the JSON schema”transcript, stated

fallback-degradation (reliability)

An LLM proxy allows model switching and fallback when a provider is down, preserving agent service levels.

“replace your LLM calls with an actual LLM proxy because then it allows you the switching between the different use cases but also gives you the fallback option”transcript, stated
“OpenAI is not always up or cloud is not always up. So you always need a fallback solution to for your agents to run at a high SLI rate.”transcript, stated

agent-memory (memory)

Digits distinguishes memory from raw storage and uses compressed short-term and long-term preference summaries.

“memory tools use um they basically compress all the existing information.”transcript, stated
“long-term memory is if you preserve those preferences over time in in some sort of a different database or could be a relational database or a graph database”transcript, stated

observability-tracing (operations)

Phoenix traces prompts, model calls, tool calls, latency, cost, and guardrail outcomes for chaotic multi-tool agent runs.

“So agent observability is key”transcript, stated
“when we make an agent call you see the different um tool calls on the left hand side and then you also see like the individual prompts that go out to our model or like um to our tools.”transcript, stated

guardrails-io-filtering (safety-quality)

Digits uses LLM-as-judge checks and policy guardrails before showing outputs to users.

“Does this make sense? Is this reasonable? Um do we reveal any confidential information here? Is it harmful to anybody? etc.”transcript, stated
“we replace our initial response with a guardrail because it's another block where we want where we want to stop this entire process”transcript, stated

human-in-the-loop-gate (governance)

Low-confidence classifications are surfaced to users for confirmation or correction instead of being shipped silently.

“if we're less confident then we show this bubble up bubble this up to the user.”transcript, stated
“Can you tell us if this is right or wrong? And if they immed if they give us the feedback immediately the system learns.”transcript, stated

Tradeoffs

Agent framework adoption

Chose direct implementation around existing APIs over heavy framework dependency stack.

Rationale: The core loop is small, while framework dependencies and Python assumptions were costly for Digits' audited Kotlin/Golang environment.

“from our perspective it was much simpler to implement it directly.”transcript, stated
“the the core loop itself is 200 lines of code.”transcript, stated

Tool integration surface

Chose curated API-to-JSON-schema tools over all raw RPC definitions or fully manual tools.

Rationale: Raw RPCs were noisy and manual schemas did not scale, so a curated introspected surface balanced safety and maintainability.

“what we actually wanted is like access not to all APIs but a very curated list of APIs.”transcript, stated
“most tools or most frameworks understand the JSON schema and they can that worked really well”transcript, stated

Planning model complexity

Chose higher-complexity models for task planning over cheap models for every step.

Rationale: Better planning prevents wrong tool calls and restarts, reducing execution time enough to offset higher planning cost.

“it is useful to use a high complexity model.”transcript, stated
“if you have a good tool planning capabilities, you will see an a reduction in in the execution time and it will actually make up all the extra costs”transcript, stated

Gotchas (what bit them)

Agent frameworks were not a free win in a secure non-Python production stack.

Root cause: Framework dependency chains increase audit burden, and Digits runs Kotlin/Golang rather than Python in production.

Resolution: Implement the core loop directly and reuse existing APIs for tools.

“they come with a ton of dependencies. So in our use in in our use case we have to go through various audits for security etc.”transcript, stated
“we don't run Python in production. We run Cotlin and Golang. And so I couldn't even use those decorators in the first place.”transcript, stated

Manual tool definitions do not scale.

Root cause: Writing objective, schema, inputs, and outputs for every tool becomes time-consuming as tool count grows.

Resolution: Curate the API list and introspect selected APIs into JSON schemas agents can call.

“This works with like maybe two, three, four tools. But if you have like 10, 20 or maybe a hundred different tools, that doesn't scale.”transcript, stated
“we use like um the inflection or introspect to convert our APIs into a JSON schema”transcript, stated

Tool-heavy agents become hard to debug quickly.

Root cause: One task can fire multiple LLM requests and tool calls behind the scenes.

Resolution: Add agent observability with prompt/tool-call traces, latency, cost, and guardrail outcomes.

“if you have a single task and you give a single task to an agent it can fire off like a number of uh requests to various LLMs and uh make a number of tool calls.”transcript, stated
“you can also see like how our guardrails have evaluated the um the request in the first place”transcript, stated

Raw transcript-style storage does not create useful memory.

Root cause: Concatenating model outputs preserves text but does not compress preferences or make them reusable.

Resolution: Use memory tools that summarize short-term interactions and preserve long-term preferences in databases.

“So just concatenating your LLM output does not turn into memory.”transcript, stated
“short-term memory would be if you would summarize this into the last five calls into a summary of those um preferences.”transcript, stated

Evaluation

Digits evaluates production agents through observability traces, guardrail checks, confidence-based human review, acceptance rates, and async/sync request mix. The talk reports a 96% acceptance rate and about 3% user review rate for a classification case.

Metrics: 96% average acceptance rate for the classification case · 3% of questions bubble up to end users for review · 90% asynchronous requests and 10% synchronous chat-like requests · Prompt, tool-call, latency, cost, and guardrail traces in Phoenix

3 supporting quotes
“we have an average of like 96% um acceptance rate on those things and only like 3% of uh questions actually bubble up to the end user”transcript, stated
“currently we we see maybe 90% of the requests are asynchronous and 10% of the requests are actually people here coming online chatting with the use case.”transcript, stated
“we can track the latency and in the latest version also we can track the costs etc.”transcript, stated

Outcomes

Digits reports seven years of ML infrastructure, approximately 90% asynchronous requests, 10% synchronous requests, a 96% acceptance rate in one classification case, and roughly 3% user review escalation.

3 supporting quotes
“one of the major use cases is the um vendor hydration.”transcript, stated
“Another use case is for like the simplification of onboarding clients.”transcript, stated
“there's hand the handling of complex user questions. So we have a uh a UI. I will show you an example later where you can ask questions about your books”transcript, stated