Skip to content

Documentation / Code and addons

Coding Agents

Let an AI coding agent change your addons in its own copy of your Odoo, or directly in a test system, then review its pull request.

A coding agent is an AI that works on one of your addon repositories for you. You describe the change, and the agent edits the code, tries it out in an Odoo and pushes it for a pull request that you review and merge. You follow along in the session, answer its questions and decide what it may do without asking you.

Coding agents are in early access and are being rolled out team by team. If you don't see Agent Sessions under Developer in the panel menu, they aren't enabled for your team yet. Get in touch and we'll switch them on.

How it works #

  • The agent always works in one Odoo: an agent copy, a fresh neutralized copy made for the session, or, in early access, directly in a test, demo or copy Odoo of your team's. Either way the session holds that Odoo until somebody releases it. Nothing releases it on its own. Releasing deletes an agent copy, and an Odoo the agent worked in directly gets its own addons back. See Where the agent works.
  • Where you start decides the kind. You never choose between the two in a form. See Starting a session.
  • An agent copy is created on the server for copies of the Odoo you start from, or on its own server if none is set. Agent copies do not count towards your plan's copy limit, but they use server resources until you remove them.
  • The agent runs next to its Odoo on your server. Its checkout, its conversation and the Odoo data stay on your server. What the agent reads from the Odoo does go to your AI provider: in an agent copy, tick Obfuscate personal data when you start the session to have its personal data encrypted first (see Obfuscating personal data).
  • The agent runs on your own AI provider key and your bill with that provider. The cost shown in the panel is an estimate.
  • Every git push asks for your approval, in every permission mode but Full access. In Full access the agent pushes without asking, and in an Odoo it works in directly it also restarts the Odoo, updates modules and runs SQL on its own. See Full access.

Before you start #

Add your API key #

A team owner or admin adds the key once:

  1. Open the team menu and choose Team profile.
  2. In AI / Coding agents, choose the Provider:
    • Anthropic runs Claude on your Anthropic key.
    • OpenRouter and Requesty run Claude and other models, such as GLM, Kimi or DeepSeek, on your key with them. For Requesty, choose the EU or Global region.
  3. Paste the key and optionally choose a Default model, which every new session starts with.
  4. Save.

A stored key is never shown again. Paste a new one to replace it, or remove it with the switch below the field.

Prepare the repository #

The agent works on a repository that is added to the Odoo through the calmo.cloud GitHub App, with addons synced for the Odoo's version. The pull request goes to that repository.

An agent that works directly in an Odoo can also go without a repository. It then sets that Odoo up instead of changing code: it installs apps, configures settings and enters data, such as your company details, users or a sales pipeline. See Without a repository.

Starting a session #

There are three ways in. Each one starts one kind of session:

You start it from What it starts
Create Copy on an Odoo, with Start a coding agent in this copy switched on An agent copy of that Odoo
Start session on the Agent Sessions page under Developer An agent copy of the Odoo you pick
Start agent in this Odoo in the ⋮ menu on the page of a test, demo or copy Odoo (early access) The agent works directly in that Odoo

The REST API and AI assistants choose the kind with a flag instead.

What you fill in #

Every way in asks for the same things:

Field What it does
Odoo Only on Start session: the Odoo the agent copy is made of. Each Odoo is listed with its type, and its Odoo version is shown below the field. Copies, previews and agent copies cannot be chosen, because a copy is never copied again.
Task What the agent should do, up to 10,000 characters. You can leave it empty when you attach files.
Attachments Up to 8 files per message, such as screenshots or sample data, 25 MB each.
Repository The repository the agent works on. Only repositories added to the Odoo are offered. Optional on Start agent in this Odoo: leave it empty for a task that sets the Odoo up rather than changes code.
Model Pick from your provider's list or type any model id.
Title Optional. A name for the session. It also becomes the title of the pull request. Left empty, it is the first line of the task.

Under More options, folded away because most sessions leave them as they are:

Field What it does
Branch Optional, and only shown once a repository is picked. The branch the agent starts from and the pull request targets. Defaults to the branch the Odoo pins for the repository on its Repositories tab, and otherwise to the repository's branch for the Odoo's version.
Reasoning effort From Low (fastest) to Max (deepest reasoning). Levels a model does not support are lowered automatically.
Permission mode How often the agent asks before acting. See Permissions and questions.
Obfuscate personal data On Start session and in the Create Copy dialog: encrypts the personal data of the agent copy before the agent sees it. Switched on and locked when the Odoo is obfuscated already, since its copies are too.

Getting the Odoo ready takes a few minutes, an agent copy the longest because it is copied and loaded first. You land on the session page, which shows how far it is (see When a session ends) and then the conversation as it happens.

From the Create Copy dialog #

Click Create Copy on an Odoo, on its page, in the list of Odoos or in its Copies tab, and switch on Start a coding agent in this copy. The switch is there for teams with coding agents who may start them on that Odoo, but not when you create a copy from a backup.

With the switch on, the dialog turns into the start of a session:

  • Its heading says that you copy the Odoo and start an agent, and its button reads Create copy and start agent.
  • Neutralize sensitive data is switched on and locked: an agent copy is always neutralized. Obfuscate personal data stays yours to choose.
  • Server and Share the copy with are gone: an agent copy is made for the session, on the Odoo's server for copies.
  • The fields above appear.

The switch is greyed out, with the reason below it, when your team has no API key for its model provider or when the Odoo has no repository the agent can push to.

An agent copy does not count towards your plan's copy limit and does not wait for a copy that is still being made. When no plain copy can be made, because your plan has no room for another one, a copy of the Odoo is already being made, or plain copies are not open to you on this Odoo, the dialog still opens for an agent: the switch is on and locked, and a warning says why only an agent copy can be made.

From the list of sessions #

Open Agent Sessions under Developer and click Start session. The dialog Start agent in a copy asks for the Odoo first and then for the fields above. Its button reads Create copy and start agent.

Directly in an Odoo #

Open the page of a test, demo or copy Odoo, open the ⋮ menu at the end of the header and click Start agent in this Odoo. See Working directly in an Odoo.

Where the agent works #

The agent always works in one Odoo, and the session holds it until somebody releases it. Every difference between the two kinds follows from one fact: nobody else uses an agent copy, while other people use an Odoo the agent works in directly.

Agent copy Directly in an Odoo
Started from The Create Copy dialog or Start session Start agent in this Odoo in the ⋮ menu on the Odoo's page
Offered on Live, test and demo systems. Not on a copy, a preview or an agent copy, because a copy is never copied again. Test, demo and copy systems, never live. Early access: only for teams it has been switched on for.
Data A neutralized copy of the Odoo. Obfuscate personal data is optional. The Odoo's data as it is. Obfuscate personal data is not offered. On an Odoo that is not neutralized you have to confirm that its mail and integrations may be live.
Others Nobody else is affected. You can have any number of agent copies. Everyone using the Odoo is briefly disconnected when the agent arrives and when it leaves. It takes one agent at a time.
Approvals The permission mode decides. A push asks in every mode but Full access. Restarting the Odoo, updating modules, running SQL and running odoo shell ask in every mode but Full access, and so does a push.
When you stop the session The agent stops. The agent copy stays, so you can look at what it built, until it is released. The agent stops and the Odoo is released at once. Work that was never pushed is lost.
Released on its own Never. The agent copy stays until somebody removes it. Never. The agent keeps the Odoo, running its checkout if it has one, until somebody releases it.
Module updates Run next to the running Odoo, which then restarts. The Odoo stops while the update runs and starts again afterwards.

In both kinds the agent logs in with an administrator account made for this session alone. Your users and the Odoo's own admin login are not touched, and the admin credentials of an agent copy are not the agent's.

Start with an agent copy unless the change has to be tried where your team already tests, with that Odoo's data, its other addons and its users, and a fresh copy would not be the same.

Working directly in an Odoo #

Working directly in an existing Odoo is in early access and is being rolled out team by team. If you don't see Start agent in this Odoo in the ⋮ menu on the page of a test system, it isn't enabled for your team yet. Get in touch and we'll switch it on.

Instead of an agent copy, the agent can work directly in a test, demo or copy system, for example the test system your team already uses to try out changes. Open that Odoo, open the ⋮ menu at the end of the header and click Start agent in this Odoo. The entry only appears on test, demo and copy Odoos, never on a live system, a preview or an agent copy, and only to people who may start coding agents on that Odoo.

The dialog opens with an info box that states three facts before you start: what happens to the Data, to Others who use the Odoo and Afterwards. When the Odoo is stopped, it adds that the agent's arrival starts it, and when it has configuration changes that were not deployed yet, that they are deployed with the agent. If the Odoo is not neutralized, you also have to confirm that you understand its mail and integrations may be live. Then come the fields above, and the button reads Start agent.

An Odoo takes one agent at a time. While another agent holds it, Start agent in this Odoo is greyed out in the ⋮ menu, and its tooltip says which session holds the Odoo if it is your team's own, and otherwise only that an agent of another team does. It also tells you to release the Odoo from the agent card on its page first or, if your team cannot, to ask the team that hosts it to release it. If an agent arrives while your dialog is open, Start agent refuses with Another agent works in this Odoo and the dialog stays open.

What changes in the Odoo #

  • The Odoo is redeployed with the agent next to it, so it restarts when the agent arrives. With a repository, the Odoo runs the agent's checkout of the repository instead of its own deployed version of it until the agent leaves, for everyone who uses it. Updates to that repository's addons on the Odoo take effect when the agent leaves, when a running Odoo restarts once more.
  • Nothing is copied or neutralized for the session: the agent sees the Odoo's data as it is, and what it reads goes to your AI provider. If the Odoo is not neutralized, its outgoing mail and scheduled actions may be live. The agent is told so and asked not to trigger them unless you ask it to. A mail catcher on the Odoo does not change that: it only catches mail the Odoo sends without a mail server of its own.
  • An Odoo takes one agent at a time. A session that finds another agent in it does not wait: it ends as Failed and does not block the Odoo. See If the start fails.
  • Automatic redeploys wait while the agent works in the Odoo. Whatever changed meanwhile is deployed when the agent leaves.
  • Stopping, restarting or redeploying the Odoo interrupts the agent. The confirmation says so. Deleting the Odoo ends the session, as Failed if it was still running, and the session stops holding the Odoo.

Without a repository #

Leave Repository empty in Start agent in this Odoo and the agent works on the Odoo itself rather than on code. It looks at what is installed and set up first, installs the apps the task needs in one go, and sets up settings and data through Odoo itself, for example:

  • install Sales, CRM and the German accounting localization
  • enter your company details and create three users with the right access rights
  • set up a sales pipeline with its stages

Without a repository the agent has no checkout: it writes no modules, pushes nothing and opens no pull request, and the session page shows no Changes badge. When a task needs code of its own, the agent says so; start a session with a repository for it. Everything it sets up is stored in the Odoo's database and stays after the agent leaves. The agent only gives a user it creates a password when you ask it to, and then tells you which one. It never changes the passwords or logins of your existing users.

An agent copy always needs a repository, since its work only leaves the copy through a push.

Approvals #

Because other people use the Odoo, the agent's tools for restarting the Odoo, updating modules, running SQL and running odoo shell scripts ask for your approval there in every permission mode but Full access, Auto included. Everything else follows the permission mode as usual, and a push asks, as in an agent copy.

In Full access nothing asks, these tools included: the agent restarts the Odoo, updates modules and runs SQL and odoo shell without asking first, for everyone who uses the Odoo. See Full access.

A module update stops the Odoo while it runs and starts it again afterwards, so the Odoo answers no requests during the update. A restart or an update disconnects everyone using the Odoo.

Seeing who works in an Odoo #

An Odoo holds at most one agent, so its page shows one agent card at the top, never a list of sessions. The card appears as soon as the agent is on its way and stays until the Odoo is released.

  • An agent works directly in the Odoo. The card reads A coding agent works in this Odoo. It says whose agent it is and which repository's addons its checkout replaces, or, for an agent without a repository, that it changes the Odoo itself. Once the session has ended, it says that the agent keeps the Odoo, running its checkout if it has one, until you release it. Its buttons are View session and Release Odoo.
  • The Odoo is an agent copy. The card reads This copy was made for a coding agent. It says whose agent it is, how far it is and, once the session has ended, that the copy stays until you remove it. Its buttons are View session and, once the session has ended, Remove copy. Removing the copy takes you back to the list of Odoos, since the page is gone.
  • The session could not start. The team that started it sees the reason on the card as Last error.

Only the team that started a session sees its title and can open it. To every other team, for example the hosting team of a shared Odoo, the card reads, for example, An agent of Acme GmbH, without a title, a link or an error.

Elsewhere in the panel:

  • The Agent column in the list of Odoos shows a sparkles icon while an agent is getting an Odoo ready or works in it, in an agent copy as well as directly. Hover over it to see whose agent it is.
  • The Copies tab of an Odoo lists its agent copies with its other copies. Its Type column says Agent copy, and its Agent column links to the session of your own team.
  • The confirmation for deleting an Odoo an agent works in, or an agent copy that its session still holds, says that the session ends and that whatever the agent has not pushed is lost.
  • ⋮ > Agent sessions on the Odoo's page opens the history of the sessions started from that Odoo, with All sessions selected. The entry is there for people who may start coding agents on the Odoo. It is not on an agent copy, whose sessions were started from the Odoo it was made of, and on a copy it appears once your team has started a session from it.

When a session ends #

The session's status says what the agent does. The stage of its Odoo says what the Odoo goes through, and it is not the same thing: a session that completed, failed or was stopped goes on holding its Odoo until somebody releases it. The session page shows the stage of every session, whichever kind it is, under Works in, with the name and type of its Odoo. Under Started, below the date, the page names the Odoo the session was started from and links to it while you can open it. It stays when an agent copy is gone, and is left out when the agent works in that Odoo directly.

Stage What it means
Preparing… An agent copy is being copied and loaded, or the agent's login is being created in the Odoo.
Starting… The Odoo is up and the agent is starting next to it.
Agent working The agent works in its Odoo.
Held The session ended, but it keeps its Odoo until somebody releases it. There is no deadline. An agent copy is still there to look at, and an Odoo the agent worked in directly still runs its checkout, if it has one.
Released The agent copy is deleted, or the agent left the Odoo, which runs its own addons again.
Not used The session ended before it got an Odoo, because it could not start.

Nothing is released on its own #

An ended session keeps its Odoo until somebody releases it. No date counts down, and nothing deletes an agent copy or gives an Odoo back after some days.

  • An agent copy stays, with its database and the agent's checkout, until you remove it. It does not count towards your plan's copy limit, but it keeps using server resources, so remove the ones you are done with.
  • An Odoo the agent worked in directly stays with the agent, running its checkout if it has one, for everyone who uses it, until you release it.

Releasing loses work that was never pushed, so ask the agent to push it first. See Releasing.

Continuing a session #

  • A session is Completed when the agent has finished and gone idle. Send another message to resume it with the same conversation and checkout. This works for as long as the session holds its Odoo, with no deadline.
  • A session that Failed, for example because the agent stopped unexpectedly, can also be resumed with a message as long as it still holds its Odoo.
  • A session you stopped, or that could not start, cannot be resumed. Start a new one.
  • Once its Odoo is released, a session can no longer be resumed, whichever way that happened. The conversation stays readable.

The Agent Sessions list shows Active & unfinished sessions by default: those still running or waiting for you, those that still hold a test, demo or copy Odoo they work in directly, those whose agent copy still has work that was never pushed, and those whose work has not reached a merged pull request yet. Switch to All sessions for the full history. Sessions are grouped by Odoo, with an estimated cost per group.

Releasing #

Releasing an Odoo means the session lets go of it:

  • An agent copy is deleted, with its database, the agent's checkout, its transcript and the session's files.
  • An Odoo the agent worked in directly stays. The agent leaves it: its checkout, conversation history and login are removed from the Odoo, and the Odoo gets its own addons back. A running Odoo restarts for that; a stopped one stays stopped and only has its configuration written again. Whatever the agent changed in the database stays, such as modules it installed or upgraded and records it changed, so update the Odoo's addons if its own code is older than what the agent upgraded.

Work in the agent's checkout that was never pushed is lost, and the session can no longer be continued, so ask the agent to push before you release. The conversation stays readable. The activity log of an Odoo the agent worked in directly records when an agent arrived and when it left.

An Odoo is released only when:

  • you click Remove copy or Release Odoo on the session page, once the session has ended. The button is Remove copy for an agent copy and Release Odoo for an Odoo the agent worked in directly. The confirmation warns you if the checkout holds unpushed work. A running session has to be stopped first.
  • you stop the session, for an agent that works directly in an Odoo. Stop session releases the Odoo right away, whatever the agent is doing, and the confirmation warns you about unpushed work. Stopping through the API or an AI assistant does the same. Stopping an agent copy session leaves the copy as it is until somebody removes it.
  • a colleague clicks Release Odoo or Remove copy on the Odoo's agent card. The hosting team and the team that started the session can use them, as long as they may redeploy the Odoo, so a colleague does not have to wait for the person who started the session. A partner team can never release the hosting team's agent or another partner's.
  • the Odoo is deleted. The session stops holding it, and whatever the agent has not pushed is lost.
  • the team loses access. When a partner team is removed from a shared Odoo or leaves it, its agents are released from that Odoo and from all its copies, and the agent copies its sessions made of them are deleted too. Lowering its role to Viewer or Operator, which cannot start coding-agent sessions, does the same for that Odoo, but not for its copies, where the team keeps the role it has there.
  • you remove or release it through the API or an AI assistant. See Webhooks and the API.

If the start fails #

A session that cannot get the Odoo it was to work in ends as Failed with the reason, whichever kind it is. It does not stay pending and does not block anything. The person who started it is notified, and the session cannot be resumed: start a new one. The reasons are:

  • For an agent copy: the Odoo it was started on no longer exists, has no server, or your team may no longer start coding agents on it, or the copy for the agent could not be made.
  • For an agent that works directly in an Odoo: another session already holds the Odoo, your team no longer has access to it, it has no server, or the agent's login could not be created in it. Start the new session in an agent copy, or once the other one has released the Odoo.

If the Odoo is ready but the agent itself cannot be started in it, the session stays pending with the reason shown on the session page. Stop it and start a new one. If the team's API key is gone by the time the agent starts, the session fails with that reason instead. Add the key and send a message to continue it.

The start dialogs refuse before anything is made, with a message and the dialog left open, when your team has no API key for its model provider (the message links to the team settings if you may open them), when another agent already works in the Odoo you start an agent in directly, or when your team may not start coding agents on the Odoo.

What the agent can do #

In its Odoo, the agent can read and change the repository's files, run commands and commit, when the session has a repository. It can also:

  • restart the Odoo and read its logs
  • install and upgrade modules, optionally running their tests
  • run SQL and odoo shell against the database
  • open the Odoo in a browser, logged in with the administrator account made for the session; your users and their passwords are not touched
  • read the emails the Odoo sent, attachments included, to check that a change emails the right people. This needs the mail catcher on the server.
  • share files with you, such as screenshots or exports

In an Odoo it works in directly, its tools for restarting the Odoo, updating modules, running SQL and the Odoo shell ask for your approval in every mode but Full access; see Approvals.

Permissions and questions #

The permission mode decides when the agent stops to ask:

Mode Behaviour
Ask every time The agent asks before every action that changes something. The default.
Auto-accept edits File edits go through. Other actions still ask.
Auto The agent decides what is safe to run.
Plan mode The agent only reads and plans, without changing anything.
Full access Nothing asks: the agent takes every action without your approval, pushes included. Only its questions still wait for you. See Full access.

In every mode but Full access, a push asks for your approval, and so do the agent's tools for restarting the Odoo, updating modules, running SQL and the Odoo shell in an Odoo it works in directly; see Approvals.

A request appears in the conversation as Permission requested with Approve and Deny. When the agent needs input, it asks a question with options to pick from or room for your own answer, and waits until you reply. You can change the model, the reasoning effort and the permission mode while the session runs.

The person who started a session gets an in-app notification when the agent needs a decision or a reply, and when the session fails or cannot start.

Full access #

Use Full access only for a task you trust. The agent pushes to GitHub without asking, so nobody sees a push before it goes out, and in an Odoo it works in directly it also restarts the Odoo, updates modules and runs SQL and odoo shell without asking, for everyone who uses that Odoo.

In Full access the agent asks for no approval at all. Every action goes through as soon as the agent takes it: file edits, commands, pushes and, in an Odoo it works in directly, the tools that ask there in every other mode (see Approvals). No Permission requested appears in the conversation.

  • Questions still wait for you. A question is not an approval: when the agent needs input, it asks and waits for your reply, as in every other mode.
  • Protect the branches your Odoos deploy from. The agent is told to push only its own work branch and to leave merging to you, but in Full access nothing checks a push before it reaches GitHub. To make sure changes reach those branches only through a pull request you review, protect them on GitHub with a branch protection rule or a ruleset. If you add modules with Add Module, let the calmo.cloud GitHub App bypass that rule, since it commits to the branch directly.
  • A request that is already waiting stays waiting. Switching to Full access does not approve it, so approve or deny it as usual; only what the agent does after the switch goes through without asking. When you switch to another mode, the agent asks again as that mode says.
  • Choosing it needs no extra permission. Whoever may choose the permission mode may choose Full access, when starting a session or while it runs, in the panel, through the REST API (fullAccess) or through an AI assistant. The agent cannot switch itself to it.

Getting the changes #

The badge in the session header shows where the changes stand: No changes, Unpushed, Pushed, PR open, Merged or PR closed. When the agent has unpushed commits, click Request push and approve the push. In Full access the agent pushes without asking, so there is nothing to approve. Then click Open pull request. If a pull request for the branch already exists, the session adopts it. Its status follows GitHub from then on.

Click Open Odoo to try the change yourself before you merge.

Shared Odoos #

On an Odoo shared with your team, starting sessions needs the Developer role. Sessions belong to the team that started them: the hosting team does not see a partner team's sessions, and the other way round. A partner team starts an agent copy of a shared Odoo from the Create Copy dialog like any other team, and the copy is shared with that partner team alone.

A partner team's agent can work directly in a shared test, demo or copy Odoo as well. The hosting team sees it on the Odoo's page, where the agent card names the partner team rather than the session. It cannot open the session, but it can release the agent with Release Odoo if it may redeploy the Odoo. The partner team can release its own agents the same way, but never the hosting team's or another partner's. The permission mode of the partner team's session applies in the shared Odoo too, so in Full access its agent restarts the Odoo, updates modules and runs SQL there without asking anyone, the hosting team included.

When a partner team is removed from the Odoo, or leaves it, its agents are released from the Odoo and from all its copies, and the agent copies its sessions made of them are deleted. Lowering its role to Viewer or Operator, which cannot start coding-agent sessions, does the same for the Odoo itself, but not for its copies, where the team keeps the role it has there.

Webhooks and the API #

  • Webhooks tell your system when a session changes status, asks for a decision, opens a pull request or shares files. The Webhooks button on the session list takes team admins there.
  • The REST API and AI assistants over MCP can start sessions, reply to them and answer their requests. For a team coding agents aren't enabled for, the agent-session calls of the REST API answer 403 and AI assistants don't get the agent tools; the team endpoint shows it as early_access.coding_agents. A session started this way works in an agent copy. Once working directly in an Odoo is enabled for your team, pass attached: true to have the agent work directly in a test, demo or copy system; the team endpoint shows it as early_access.coding_agents_attach. With attached: true the repository is optional: leave repository_uuid out for an agent that sets the Odoo up, and leave out branch with it. The API and MCP need the Agency plan; in the panel, coding agents work on every plan.
  • Removing the agent copy of an ended session over the API or MCP does what the button does: it deletes an agent copy, and for an Odoo the agent worked in directly it gives the Odoo back. An AI assistant has to repeat the session's work branch to confirm.
  • Cancelling a session that works directly in an Odoo, over the API or MCP, releases the Odoo exactly as Stop session does, and discards work that was never pushed. An AI assistant has to repeat the session's work branch to confirm. Cancelling an agent copy session leaves the copy as it is.
  • A session whose Odoo was released reports resumable: false.
  • A session reports ended_at, when it last ended, and service_stage (preparing, starting, working, holding, released or not_used), whichever kind it is. An Odoo reports is_neutralized and, when it is fetched on its own, coding_agent_working.
  • A session that could not get the Odoo it was meant to work in ends as failed, whichever kind it is; its webhook status_changed carries the cause start_failed and the reason.