Agents

An agent (ai.agent) describes how an AI colleague behaves. It is not the same thing as the Odoo user account it may run as.

Two shapes

Chat persona (no linked user)

Example: shipped default Jarvis.

  • Used when a human opens the AI chat.

  • Runs as the chatting user (their ACLs, their AI policy membership).

  • System Prompt, model overrides and capabilities shape the session.

  • No supervisor required.

  • Restricted to groups can restrict who may invoke this persona.

Autonomous colleague (linked user)

  • User points at a dedicated res.users.

  • Runs with that user’s rights (like a human employee).

  • Supervisor is mandatory — authorises work and approves write proposals.

  • Channel rules decide who may address the agent and with what capability scope.

  • Appears as is_ai_agent on the user (read-only indicator).

Danger

Linking a wide-privilege user to an agent is equivalent to giving that privilege to a prompt-injectable worker. Always create a narrow user for the agent. Never use the superuser, portal users, Settings, or AI Administrator accounts.

Agent form fields

AI ‣ Configuration ‣ Behavior ‣ Agents

Field

Purpose

Name

Display name (e.g. Support Assistant).

Active

Inactive agents do not run.

Model

Optional model override; else main / defaults.

Temperature

Sampling override for this agent’s own turns, withheld from models that do not accept one.

Max Tokens (0 = no override)

0, the default, sends no cap at all: the model’s own output limit applies. A positive value caps this agent’s completions instead — see the note below.

System Prompt

Appended after global prompt layers.

Capabilities

Ceiling of tool classes for this agent.

Restricted to groups

Who may invoke as chat persona.

User

Optional linked internal user (unique).

Supervisor

Required if User is set; must be AI: User.

Channel Rules

Default-deny allow-lists per channel.

Default agent

Marks the persona used by default in chat.

Note

A cap only takes effect where the model record publishes an output limit of its own, and it behaves differently per provider. Both rules, and what an update does to agents that already carry a value, are described once under Completion caps.

Channel rules

AI ‣ Configuration ‣ Behavior ‣ Agents → channel rules (or dedicated channel rule views).

Channels:

  • Discuss direct message

  • Chatter @mention

  • Activity (assigned activity)

  • Assignment (e.g. project task assignee) — critical: without this, anyone who can assign a task could not be distinguished from a Discuss gate

  • Email / AI chat panel — reserved / progressive wiring; default-deny still applies

Rule fields:

  • Allowed groups / Allowed users — audience. Empty audience matches nobody (not everyone).

  • May Request — audience may trigger an ad-hoc run.

  • Scope Mode:

    • Agent rights ∩ requester rights (intersect, default) — capability classes both hold. Data is still read/written as the agent.

    • The agent’s full rights (agent_full) — trusted audience only.

Important

intersect is not “run as the requester”. It only narrows tool classes (read/write/web/…). Record visibility remains the agent’s. Only allow-list people you trust with whatever the agent can see.

Inbound flow (simplified)

  1. Message / assignment / activity targets the agent.

  2. If requester is banned → refuse (no LLM).

  3. Resolve channel rule (default deny) → else refuse + violation / strike.

  4. Enqueue inbound request; drain cron wakes.

  5. Optional triage may subtract authority only.

  6. Create task / run under supervisor scope; execute as agent user with committed capability ceiling.

  7. Writes follow that task’s Write Mode (default: pending proposals for the supervisor; see Task write mode (agent runs only)).

  8. Agent posts notes / drafts on the thread as itself — customer text never becomes a silent privilege grant.

Tasks and runs

Operational menus (AI: User, supervisor-scoped):

  • AI ‣ Agents ‣ Tasks — standing and scheduled tasks.

  • AI ‣ Agents ‣ Work Items — per-record queue drained into isolated child runs (see Per-record work items).

  • AI ‣ Agents ‣ Runs — execution ledger and steps.

Supervisors use these to see what the agent attempted, which tools ran, and which proposals are waiting.

Per-record work items

A standing task that processes many documents (vendor bills, and similar) must not load every attachment into one conversation: the model’s context window fills, and one provider error aborts the whole batch.

Put two texts on the task:

  • Instruction — the scout. Search candidate ids, call queue_work_items, then stop. Do not read PDFs here.

  • Work Item Instruction — the child. Placeholders {model} and {id}. Each queued record runs this in a new conversation. Empty uses a generic one-record prompt that still forbids further queueing.

The scheduled action AI: drain agent work items (every minute) starts at most eight pending items per tick, still bounded by the same dispatch budget as other scheduled tasks. Child runs leave Parent Run empty — that field marks an approval replay, not fan-out — and they do not count towards the task’s daily cap or circuit breaker.

queue_work_items needs the write capability. It only works on a standing-task run (not an inbox run, not a child), and it only queues records the agent can read. Ids that are still pending or running are skipped; done or failed items can be queued again. At most 200 ids per call.

Task write mode (agent runs only)

Each task carries Write Mode. It applies only to agent runs dispatched for that task — not to interactive chat (chat uses the global setting under AI ‣ Configuration ‣ Settings).

Value

Effect on that task’s runs

Always require confirmation (confirm, default)

Every create / write / delete / file attach becomes an ai.pending.write for the supervisor.

Create automatically, confirm updates (hybrid)

Creates apply immediately; updates, deletes and file attaches still need approval.

Apply immediately (auto)

Allowed mutations apply at once under the agent user’s rights and the run’s capability ceiling.

The global ai.write_mode parameter never overrides a task: an administrator cannot flip every unattended agent to auto with one setting. hybrid / auto are deliberate per-task opt-ins for trusted, low-risk work — for example an accounts-payable standing task that fills draft vendor bills and whose skill never posts invoices. Prefer confirm whenever a run could post, pay, delete, or touch customer-facing data.

When a proposal is created, the platform also places a To-Do activity (and usually a chatter note) on the target business record when one exists (e.g. the vendor bill being updated), falling back to the agent task for creates that have no id yet. Confirm and Cancel still live on AI ‣ Write Proposals; the activity is only a systray nudge so the supervisor lands on the invoice or partner, not only on the abstract proposal list. The Write Proposals form has Open record for the same jump. The activity is closed when the proposal is applied, cancelled or expired.

Tip

The hard-deny floor blocks raw AI tools on every ai.* platform model. Agents therefore cannot “manage” their own approval queue or AI config via tools — and should not try. Platform nudges and skill-driven review activities on business documents use controlled paths; instruct agents not to invent AI-config tool calls, or they will burn refusals and strikes.

A run’s ledger row becomes visible to other users only once the attempt has ended or parked for approval: the row is written and finalised inside the worker’s own transaction, so nothing is committed while the agent is still working. The runs list therefore shows completed work, not a live view of what is executing right now.

Failed runs carry a Failure Type on the run form that says which kind of failure it was — see Monitoring for the values worth watching.

Stopping a run

Open the run and use Request Cancellation. The button appears while the run is Running or Waiting for approval, and only the agent’s supervisor or an AI administrator may request it.

Important

This button is not a general “stop the agent now” control, because of the ledger behaviour above: a run that is executing normally has no row yet, so there is nothing to open. In practice you use it on a run parked in Waiting for approval, or on one left in Running by an earlier server incident. To stop unwanted work in advance instead, keep the task’s Deadline Seconds short enough that a run ends on its own, and clear Active on the task so it is not dispatched again.

Cancelling a run parked in Waiting for approval withdraws its open write proposals, then closes the run: as Done if a proposal of that run had already been applied, otherwise as Failed with Failure Type waiting_approval_empty, since nothing it proposed was approved.

Cancelling a run that is genuinely still executing is cooperative, never immediate. The request is read at the start of each provider round and again before each tool call, so it takes effect only after the round-trip already in flight has finished — allow up to about two minutes at the shipped defaults, and never in the middle of a provider call. Such a run then closes as Failed with Failure Type cancelled; there is no separate Cancelled state. The steps it did execute stay on the Steps tab, the run’s answer records the cancellation rather than a partial reply, and any write proposals it had already opened are cancelled with it, so nothing is left approvable. A cancellation is neutral for the task’s automatic deactivation: it neither counts as a failure nor clears an existing streak.

Note

If no worker is left to hear the request, the button answers Nothing in flight to cancel instead of confirming. Nothing is broken — the run has most likely already finished, or its worker died — but no worker will see the request and the run will not stop on its account. Reload the record to see where it really stands; a dead worker’s run is closed by the stuck-run reaper below.

Runs whose worker died

If the server process handling a run is killed (restart, out-of-memory, hard kill), nobody is left to finish the run. A scheduled action, AI: reap stuck agent runs, runs every 15 minutes and closes them: the run is recorded as Failed with Failure Type reaped_stuck, a note is posted on the task, and any write proposals still waiting on it are expired so nothing can be approved on behalf of a dead run. If the crash took the ledger row with it, the housekeeping job rebuilds one from the record the dispatch left behind — provided that record was written; a kill early enough to prevent even that leaves nothing to rebuild from.

Do not expect that closure within 15 minutes. The run has to age past its own time limit plus a grace period (10 minutes by default — see Configuration) before a pass will touch it, and passes are 15 minutes apart, so worst case is around half an hour. One pass closes at most 200 runs, oldest first; a large backlog after a restart storm drains over the following passes.

The same scheduled action also frees runs parked in Waiting for approval that have no open proposal left — for example when the last proposal expired while the supervisor was still confirming it — so such a run is not left holding an activity reminder for a proposal that no longer exists.

Tip

Every dispatch attempt carries a Dispatch Token, shown on the run form. It is the key that joins a run to the short-lived record written when the run started, which is what both the reaper and Request Cancellation look for — so it is also the value to quote when correlating a run with the server log.

Pre-run instruction check

Scheduled and Run Now runs execute the task’s standing instruction directly. Tick Triage On Dispatch on a task to run the same stage-1 check that an agent addressed from chat receives. The check can only narrow what the task already grants — it never widens anything.

Consider before enabling it:

  • it costs one extra model call per run (time and tokens), and the scheduler reserves about 30 seconds of its own tick budget for that call. A task whose Deadline Seconds already sits close to the worker’s time limit may therefore be skipped rather than dispatched;

  • the check has its own short deadline of 15 seconds and is fail-closed: a triage model that is slow, unreachable, or answers off-schema counts as a refusal;

  • a refusal means the agent never starts. The run is recorded as Failed with Failure Type triage_denied, a note is posted on the task, and a To-Do activity is created for the supervisor — so no refusal is silent;

  • refusals count towards the task’s automatic deactivation. The task is archived once five consecutive runs have failed and the streak is more than seven days old, and its supervisor is notified. Because a triage failure is a refusal, a long provider outage can archive a task that was never misconfigured; that is why the option is per task and off by default;

  • what the check decided is recorded on the run as Triage Verdict, on the Snapshot tab, and is empty on every run of a task that did not opt in. It is telemetry, not a boundary: the narrowing it describes is already committed in the run’s Allowed Caps, which is what the access gate reads.

The global kill switch for stage-1 triage — inbound addressing and this pre-run check alike — is the ai.triage_enabled system parameter, under Settings ‣ Technical ‣ Parameters ‣ System Parameters (which needs developer mode).

AI Ops project stages

The module ships an AI project category, an AI Agent project template, and a shared stage pack:

Inbox → Review → Ready → Doing → Waiting → Done / Cancelled

Suggested use:

  • automated audit findings land in Inbox without assignee;

  • managers refine in Review;

  • assign the agent user only from Ready;

  • Waiting for human input or approval;

  • never auto-apply skills/policies from an audit without a human.

Support Assistant pack

Shipped inactive Support Assistant agent with ask+read capabilities and channel rules whose audiences are empty until you configure them. Activate by:

  1. Creating a narrow internal user (helpdesk/project read as needed).

  2. Linking it on the agent; set supervisor.

  3. Filling channel audiences (groups/users who may DM / assign / @mention).

  4. Setting Active.

  5. Tuning AI access rules for ticket models.

Identity constraints (summary)

At link time the module rejects agent users that are:

  • superuser (uid 1);

  • share/portal;

  • Settings / system administrator;

  • AI Administrator;

  • holding API keys (non-interactive login risk).

These checks are point-in-time on the agent form — do not “upgrade” the user later from the Users menu.

Next: practical recipes in Agent recipes.