How to connect Claude with Odoo: an agent that pulls your financial statements every month
Pulling the monthly financial statements — income statement, balance sheet, cash flow — is usually a manual chore: log into Odoo, run reports, export, format and summarize for management. It’s repetitive and error-prone. In this guide you’ll see how to build an agent powered by Claude that does it on its own, every month, reading the data straight from Odoo.
What you’ll build
The architecture has three pieces:
- Odoo — the accounting data source, accessible via its API.
- Claude — the agent’s “brain”: it queries the data, arranges it into a financial statement and writes an executive summary.
- A monthly trigger — a cron job that, on the 1st of each month, runs the agent for the previous month and delivers the report by email (or wherever you want).
Step 1 — Access to the Odoo API
Odoo exposes its data via XML-RPC / JSON-RPC. First, generate an API key for a user (ideally a dedicated read-only user for the agent): in Odoo, Settings → Users → your user → “Account Security” tab → “New API Key”.
With that you authenticate and query the accounting models. For an income statement, the most direct approach is to group the journal items (account.move.line) for the period by account type:
import xmlrpc.client
URL = "https://yourcompany.odoo.com"
DB = "yourcompany"
USER = "agent@yourcompany.com"
API_KEY = "your_api_key"
common = xmlrpc.client.ServerProxy(f"{URL}/xmlrpc/2/common")
uid = common.authenticate(DB, USER, API_KEY, {})
models = xmlrpc.client.ServerProxy(f"{URL}/xmlrpc/2/object")
def balances_by_type(start, end):
# Sum debit/credit of posted journal items in the period, grouped by account type
return models.execute_kw(DB, uid, API_KEY,
"account.move.line", "read_group",
[[["date", ">=", start], ["date", "<=", end], ["parent_state", "=", "posted"]]],
{"fields": ["balance:sum"], "groupby": ["account_type"]})
print(balances_by_type("2026-05-01", "2026-05-31"))
That yields the big blocks: income and expenses (income statement) and assets, liabilities and equity (balance sheet). If you use Odoo’s native reports (the account.report engine), you can also invoke them via the API; starting with read_group is the simplest.
Step 2 — Expose Odoo to Claude
There are two ways for Claude to “use” Odoo:
Option A — An MCP server (recommended)
You wrap the Odoo API in an MCP server that exposes tools like get_income_statement, get_balance_sheet or account_balance. The advantage: it’s a reusable standard — the same server works for this agent, for your desktop assistant or for any model. (New to MCP? See our guide: What is MCP?)
Option B — Tools in the Claude API
For a one-off agent, you can define the functions directly as tools in the Claude API. That’s what we show below for simplicity.
Step 3 — The agent with Claude
We give Claude a tool to query Odoo and ask it for the month’s financial statement. Claude decides what to query, assembles the numbers and writes the summary:
import anthropic
client = anthropic.Anthropic() # uses ANTHROPIC_API_KEY from the environment
tools = [{
"name": "balances_by_type",
"description": "Returns Odoo accounting balances grouped by account type for a date range.",
"input_schema": {
"type": "object",
"properties": {
"start": {"type": "string", "description": "Start date YYYY-MM-DD"},
"end": {"type": "string", "description": "End date YYYY-MM-DD"}
},
"required": ["start", "end"]
}
}]
messages = [{"role": "user", "content":
"Generate the income statement and balance sheet for May 2026 from Odoo. "
"Include a 5-point executive summary of the most relevant changes."}]
while True:
resp = client.messages.create(
model="claude-opus-4-8",
max_tokens=8000,
thinking={"type": "adaptive"},
tools=tools,
messages=messages,
)
if resp.stop_reason != "tool_use":
break
messages.append({"role": "assistant", "content": resp.content})
results = []
for block in resp.content:
if block.type == "tool_use" and block.name == "balances_by_type":
data = balances_by_type(block.input["start"], block.input["end"])
results.append({"type": "tool_result", "tool_use_id": block.id,
"content": str(data)})
messages.append({"role": "user", "content": results})
# Claude's final text: the financial statement + the executive summary
report = next(b.text for b in resp.content if b.type == "text")
print(report)
Claude calls the tool as many times as needed (income, expenses, assets…), assembles the financial statement and pairs it with a natural-language analysis — exactly what a manager wants to read.
Step 4 — Make it run on its own every month
Save the script and schedule it with a cron job for the 1st of each month (processing the previous month). On a Linux server:
# 1st of each month, 6:00 AM — generates and sends the previous month's report
0 6 1 * * /usr/bin/python3 /opt/agent/financial_statements.py
In the cloud you can use an Azure Function or an equivalent scheduled task. The script computes the previous month’s range automatically, so you don’t touch anything each month.
Step 5 — Deliver the result
The report Claude produces can be delivered however suits your team best: an email to management, a PDF attachment, a Slack/Teams message, or even back into Odoo as a note. The most common: an email with the executive summary in the body and the detail attached.
Best practices (not optional)
- Read-only access: the agent should never be able to modify the accounting. Use an Odoo user restricted to read.
- Protect credentials: the Odoo and Claude API keys go in environment variables or a secrets manager, never in the code.
- Human review: an agent speeds up the work, it doesn’t replace the accountant. The numbers must reconcile against Odoo before making decisions — AI can be wrong and always needs oversight.
- Governance: define who can use the agent and how the financial data is handled. (See: AI Governance.)
Conclusion
With three pieces — Odoo, Claude and a cron job — you turn a tedious monthly task into an automatic process that also delivers ready-to-read analysis. The same pattern works for many other recurring reports from your ERP.
At Grupo TANDEM we design and implement AI agents connected to your systems — Odoo, Microsoft 365, whatever you use — securely. If you want to automate your reporting, let’s talk.
Need help with this?
At Grupo TANDEM we implement it for you. Let's talk about your case.
Talk to an advisor