The flow¶
From an email arriving to the work item closing.
| Page | Covers |
|---|---|
| 1. Capture | n8n creates or joins the work item, then the brain assesses and decides |
| 2. Execute | n8n runs the branch for whichever action was chosen |
| 3. Approve and loop | The human decides, we reconcile, we send, and back to the brain |
| The work item, walked | Every field across five different paths. A review artefact |
| Stages | Counters and step tracing: how to tell where an item is, and what it cost |
End to end¶
flowchart TB
T["Email arrives"] --> L
subgraph CAP ["1. Capture"]
L["<b>1.1</b><br/>n8n stores raw in landing,<br/>joins or creates the work item"]
L --> B["<b>1.2</b><br/>Brain: classify, resolve, decide"]
end
subgraph EX ["2. Execute"]
S{"Switch on<br/>action.name"}
S -->|"draft_reply"| D["<b>2.1</b><br/>Draft, then write<br/>the approval record"]
S -->|"draft_holding_reply"| DH["<b>2.2</b><br/>Acknowledgement,<br/>then approval record"]
S -->|"close_item"| C(["<b>2.3</b><br/>Stop"])
end
subgraph APP ["3. Approve"]
Q["<b>3.1</b><br/>Item waits in<br/>the review app"]
Q --> H{"<b>3.2</b><br/>Human decides"}
H -->|"approve"| RC{"<b>3.3</b><br/>Reconcile: did they<br/>already reply themselves?"}
RC -->|"yes"| CM(["closed_manual"])
RC -->|"no"| SND["<b>3.4</b><br/>Send via the mail connector"]
end
B --> S
D --> Q
DH --> Q
H -->|"discard"| C
SND --> B2["<b>4. Loop</b><br/>Brain, with the outcome"]
B2 --> S
classDef llm fill:#7c3aed,stroke:#5b21b6,color:#ffffff
class B,B2 llm
Purple means a model call
Throughout these docs, a purple node is where a language model is invoked: non-deterministic and billable. Everything else is code, a database query, or a rule, and behaves the same way every time.
The loop passes through the brain each time, so a conversation's cost is its
brain_calls count. That is why max_brain_calls exists.
Everything reaches a human. There is no path where an AI-generated action is sent without approval. Some items arrive with a draft to approve, some arrive with nothing and the human writes it, and attention_reason says which and why.
Resolve and decide do not return to n8n. They are stages inside a single brain call, so n8n calls once and gets back an assessment plus an action. Drafting is a second call, deliberately, so a draft failure does not lose the classification already paid for.
Rows written elsewhere¶
| Table | Written at |
|---|---|
message |
1.1 inbound, and step 3 outbound after sending |
decision |
Every brain call |
stage_trace |
Every stage, as reached |
approval |
Step 2, when a gated action is proposed |
mask_map |
First time a value is masked, then reused for the item's life |
The work item's state at each point is shown on that step's own page.
Where a problem goes¶
Three destinations, and conflating them is how a client ends up looking at our outages. The general rule is in architecture. For this product:
| Goes to | Client sees | |
|---|---|---|
escalated_by_design |
Client human, in the review app | The item |
escalated_cannot_determine |
Client human, in the review app | The item |
| System failure | Us, in the BOS Console | Nothing. It retries |
parse_failure is genuinely both. The email still needs answering by a human today, and the failure signals a regression we need telling about. So the item escalates to the client and an alert fires to us.
Surfaces¶
| Term | Is | Audience |
|---|---|---|
| Client review app | {tenant}.app.octopodia.com.au |
The client. Approvals and history |
| BOS Console | console.octopodia.com.au |
Operators only |
portal is reserved for the Internal Portal and is not used for either (ADR-0022 ยง4).