An earlier revision collapsed detection and ordering into one nightly run. They are not the same job: detecting a coming stock-out depends on something happening and should be woken by it, while proposing a purchase order is genuinely periodic — grouped by supplier lead time, not by unit sold. Recorded because it changes what has to be built: the autonomous mandate is a cost of choosing a clock, not of the business need. Kafka is the target for the reactive half. Nothing in the estate emits a domain event today, which is what made a nightly sweep look inevitable. Detection stays unbuilt until then rather than being approximated by a periodic scan — a batch pretending to be reactive is worse than an absent feature, because it looks finished. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
5.5 KiB
Flows — the autonomous agents
Runtime: n8n · Mode: autonomous · Two agents in one repo.
| Agent | Client id | Trigger |
|---|---|---|
| Approvisionnement | classic-models-agent-approvisionnement |
event-driven, plus a periodic ordering run |
| Recouvrement | classic-models-agent-recouvrement |
weekly, Monday |
They share a repo because they are not code: n8n workflow exports, same tool, same owner. Splitting them would buy nothing.
Why low-code for these two
Their work is rules, thresholds and due dates — a sequence of conditions and calls, which a visual editor expresses better than code. The LLM is optional on their critical path, which makes them cheaper and more predictable than the conversational agents.
They remain full A2A agents: they publish an Agent Card, accept tasks, answer.
Approvisionnement
| MCP | catalog, sales |
| Scopes | catalog:read, catalog:write, sales:read |
Detect coming stock-outs, propose reorders — two jobs with two different triggers, which an earlier revision of this file collapsed into one nightly run.
Detection is reactive. It depends on something happening: an order placed, a stock level crossing a threshold. Finding that out up to a day later is latency chosen for nothing, and a nightly sweep re-reads the whole catalog to rediscover what the domain already knew at the moment it changed.
Proposing a purchase order is periodic. Nobody reorders on every unit sold; orders are grouped by supplier lead time and buying cycle. A clock is the right trigger there, and that run is periodic on purpose rather than a batch standing in for events.
Worth naming, because it changes what has to be built: the autonomous mandate
is a cost of the trigger, not of the business need. offline_access, a
refresh token stored encrypted and an exchange at trigger time are required only
because nobody is present at 3am. An agent woken by a domain event runs moments
after a human acted.
Exposes check_availability — called by Ventes before promising a delivery
date, and by Catalogue before discontinuing a reference. Returns a decision and a
date, never the stock table.
Recouvrement
| MCP | customers, payments |
| Scopes | customers:read, payments:read, payments:write |
Weekly: unpaid invoices past 30 days, dunning, escalation.
Exposes check_creditworthiness — called by Ventes before accepting a large
order.
Dunning is prepared automatically and sent only after human validation. Sending a letter to a customer is an outward-facing action; a rule bug would otherwise write to the entire customer base in one run.
The A2A server gap
The available n8n community nodes (n8n-nodes-a2a,
n8n-nodes-agent2agent) make n8n
an A2A client: Discover Agent, Send Task.
But both agents here must be servers — Ventes calls them. That needs an
Agent Card on /.well-known/agent.json and a JSON-RPC endpoint with the task
lifecycle. n8n webhooks can do it by hand, at which point it stops being no-code.
Preferred approach: Kong in front of n8n, exactly as it fronts every other resource. Kong serves the Agent Card statically and routes JSON-RPC to the webhook, and token verification lands where it already lives. No new component.
Alternative: a small FastA2A adapter, written once for both — see
classic-models-agent-catalogue, which uses FastA2A already.
The autonomous mandate
No user session exists when these run, so authority must be pre-established: the
user obtains offline_access when creating the mandate, the refresh token is
stored encrypted, and the exchange happens at trigger time. sub stays the user
who mandated, azp says which agent acted.
The MCP servers see no difference between an autonomous and a conversational
call — same sub, same azp, same audiences. That is deliberate: downstream
policy must not need to know the trigger mode.
Backlog
Events over Kafka. The target for the reactive half. The estate emits no
domain event today — classic-models-api has no signals, no outbound webhook,
and there is no bus in the cluster — so a workflow can only poll, which is what
made a nightly sweep look like the only option. Until Kafka is in place,
detection stays unbuilt rather than being approximated by a periodic scan: a
batch that pretends to be reactive is worse than an absent feature, because it
looks finished.
The periodic ordering run does not wait on this.
Two controls that become mandatory here
They were deferrable with a human in the loop. They are not, once an agent loops on its own.
- Read volume caps per
(azp, sub), enforced on Kong. An agent reads a thousand records in seconds where a human clicks ten; a scope authorises the read but says nothing about volume. - Authorisation on tool-call parameters, not just the tool name.
writeauthorises writing, not "this €40k transfer".
An autonomous agent hitting a rule that requires approval must fail cleanly and escalate, never decide. And any approval screen must be rendered from the structured tool-call parameters — never from a sentence the model produced, or a prompt injection writes what the human validates.
Before writing workflows
Read classic-models-agent-platform/CLAUDE.md for the identity model, the
endpoints and the known blockers.
Deliverables in English. Export workflows as JSON and commit them; do not rely on the n8n instance as the source of truth.