diff --git a/build-an-oracle/reference/bundled-plugins/memory.mdx b/build-an-oracle/reference/bundled-plugins/memory.mdx
index 8395880..63c4813 100644
--- a/build-an-oracle/reference/bundled-plugins/memory.mdx
+++ b/build-an-oracle/reference/bundled-plugins/memory.mdx
@@ -39,6 +39,28 @@ Durable memory across conversations — who the user is, what you have made for
Tools available beyond the default selection (e.g. `memory-engine__add_oracle_knowledge`, `memory-engine__delete_edge`) can be enabled by passing `selectedTools` to `new MemoryPlugin({ selectedTools: [...] })`.
+## How memory reaches the prompt
+
+Memory context does not arrive in the prompt because the agent calls a tool to fetch it. Instead, a `UserContextFetcher` runs **before** the main agent is compiled — eagerly loading all six context slots in a single pass, before any message is processed.
+
+**What the fetcher loads:** six slots, in this order:
+1. `identity` — who the user is (name, role, background)
+2. `work` — ongoing projects and responsibilities
+3. `goals` — stated objectives and priorities
+4. `interests` — topics and domains the user cares about
+5. `relationships` — people and organizations mentioned in past conversations
+6. `recent` — notable things from the last few sessions
+
+**When it runs:** at agent-compile time, before turn 1. The fetcher runs once per session and caches the result for **5 minutes** (keyed by `sessionId`). Subsequent turns within the same session reuse the cached context — the Memory Engine is not called again unless the cache expires.
+
+**What appears in the prompt:** if at least one slot is non-empty, the runtime inserts a `## What you know about the user` block (section 6 of the 15-section prompt) containing all populated slots. If every slot is empty (no prior memory for this user), the block is omitted entirely.
+
+**Implication for oracle authors:** you do not need to instruct the agent to "look up the user's context" or "recall memory before responding" in `config.prompt.opening` or anywhere else. The context is already in the system prompt when the agent sees the user's first message. Adding such instructions is redundant and wastes tokens.
+
+
+The 5-minute session cache means very-recent memory writes (e.g. the agent just called `memory-engine__add_memory` in the same session) may not appear in the fetched context until the next session or cache expiry. This is intentional — the fetcher is optimised for read latency, not write-through consistency.
+
+
## Adding global oracle knowledge
Global knowledge is content the oracle should know on every turn, for every user — product docs, brand voice, FAQs, reference material. It's stored on the Memory Engine and indexed under the **oracle's entity DID**, not the user's DID.
diff --git a/build-an-oracle/reference/createoracleapp.mdx b/build-an-oracle/reference/createoracleapp.mdx
index 2d4d7b0..983e34b 100644
--- a/build-an-oracle/reference/createoracleapp.mdx
+++ b/build-an-oracle/reference/createoracleapp.mdx
@@ -51,6 +51,59 @@ export interface CreateOracleAppOptions {
},
}
```
+
+ **prompt sub-fields** — all three are optional. Omit any you don't need.
+
+ **`opening`**
+
+ Used **verbatim** as the identity preamble — the very first section of the assembled system prompt. Write it as a complete paragraph describing who the oracle is and what it does.
+
+ If `opening` is absent, the runtime generates a fallback from the other top-level fields:
+ - `name` + `org` + `description` present → `"You are {name}, an AI agent operated by {org}. {description}."`
+ - `org` missing → `"You are {name}. {description}."`
+ - Both `org` and `description` missing → `"You are {name}."`
+
+ Providing `opening` gives you full control over tone, persona, and framing — use it whenever the generated fallback is too generic.
+
+ **`communicationStyle`**
+
+ Injected inside the hardcoded **"## Operating principles"** section of the prompt. If set, it appears as a paragraph within that section immediately after the 7 standard operating-principle bullets. If empty or absent, the field is omitted entirely — the operating-principles section still appears, just without the custom style block.
+
+ Use this to steer the agent's tone: formal, concise, empathetic, domain-specific jargon preferences, and so on.
+
+ **`capabilities`**
+
+ Rendered **above** the Tier-1 plugin capability block (the auto-generated list of `visibility='always'` plugins). No header is added by the runtime around this text — write your own heading if you want one. If empty or absent, the field is omitted entirely.
+
+ Use this to describe high-level skills the oracle has that aren't obvious from the plugin manifest alone — things like domain expertise, supported workflows, or what the agent should proactively offer.
+
+ **`entityDid`**
+
+ Do **not** set this in code. The runtime reads it from the `ORACLE_ENTITY_DID` environment variable and populates it automatically during boot. Setting it inline has no effect.
+
+ **Full example**
+
+ ```ts
+ config: {
+ name: 'Aria',
+ org: 'Acme Climate',
+ description: 'A carbon-project advisory oracle for Acme Climate portfolio managers.',
+ prompt: {
+ opening: `You are Aria, the carbon-project advisory oracle operated by Acme Climate.
+ You help portfolio managers track project status, assess methodology compliance,
+ and draft stakeholder communications. You have deep knowledge of Verra VCS,
+ Gold Standard, and REDD+ frameworks.`,
+ communicationStyle: `Be precise and data-driven. Lead with numbers and deadlines.
+ Use plain English — avoid jargon unless the user demonstrates familiarity.
+ When something is uncertain, say so explicitly rather than hedging with filler phrases.`,
+ capabilities: `## What Aria can do
+ - Retrieve live project status and registry issuance data via the IXO domain indexer.
+ - Draft verification reports, CORSIAs letters, and board summaries.
+ - Search and cite methodology documents from the oracle knowledge base.
+ - Schedule follow-up reminders and track open action items across conversations.`,
+ },
+ }
+ ```
diff --git a/build-an-oracle/understand/prompt-anatomy.mdx b/build-an-oracle/understand/prompt-anatomy.mdx
new file mode 100644
index 0000000..a4254ea
--- /dev/null
+++ b/build-an-oracle/understand/prompt-anatomy.mdx
@@ -0,0 +1,157 @@
+---
+title: "Prompt anatomy"
+description: "How the runtime assembles the system prompt — 15 sections, what's automatic, what you configure."
+icon: "layer-group"
+---
+
+## Overview
+
+Every time the main agent is invoked, the runtime compiles a system prompt from up to 15 sections. Most sections are automatic — the runtime builds them from env state, loaded plugins, and live session data. You are only responsible for three fields in `config.prompt`. Everything else is handled for you.
+
+## The 15 sections
+
+Sections appear in this fixed order. "Always present" means the section is included on every turn regardless of configuration; "conditional" means the section only appears when a specific condition is met.
+
+| # | Section | Present |
+| --- | --- | --- |
+| 1 | **Oracle section** — identity preamble | Always |
+| 2 | **Capabilities note** — `config.prompt.capabilities` text | Conditional |
+| 3 | **Capability block** — Tier-1 plugin manifest list | Conditional |
+| 4 | **Operating principles** — 7 standard bullets + optional style | Always |
+| 5 | **Working with files** — file-handling guidance | Always |
+| 6 | **What you know about the user** — memory context (6 slots) | Conditional |
+| 7 | **Current time** — `{currentTime}` (`{timezone}`) | Always |
+| 8 | **Current entity** — `{DID}` | Conditional |
+| 9 | **Available user secrets** | Conditional |
+| 10 | **User preferences** | Conditional |
+| 11 | **Operational mode** — general / editor / task / entity | Always |
+| 12 | **Composio context** — Composio tool context | Conditional |
+| 13 | **Editor section** — editor plugin state | Conditional |
+| 14 | **Slack formatting constraints** — Slack output rules | Conditional |
+| 15 | **Degraded services** — failed-init notices | Conditional |
+
+### Section details
+
+**1. Oracle section**
+
+The identity preamble. If `config.prompt.opening` is set, it is used verbatim. Otherwise the runtime generates a fallback from the other top-level fields: `"You are {name}, an AI agent operated by {org}. {description}."` (shorter variants when `org` or `description` are absent). See the [`createOracleApp` config reference](/build-an-oracle/reference/createoracleapp) for the exact fallback logic.
+
+**2. Capabilities note**
+
+Rendered if `config.prompt.capabilities` is non-empty. Appears immediately above the plugin capability block. No header is added by the runtime — include your own heading in the field value if you want one.
+
+**3. Capability block**
+
+Auto-generated list of all loaded plugins with `visibility='always'` (Tier-1). Each entry includes the plugin name and its manifest description. The runtime enforces a **5,000-token soft budget** on this block — if the combined manifest text would exceed that, lower-priority entries are trimmed. You never write this section; the runtime builds it from the loaded plugin set.
+
+**4. Operating principles**
+
+Always present. Contains 7 hardcoded bullets covering tool use, safety, honesty, and task handling. If `config.prompt.communicationStyle` is non-empty, it is injected here as an additional paragraph after those bullets. If `communicationStyle` is absent, the section still appears — just without the custom style block.
+
+**5. Working with files**
+
+Always present. Hardcoded guidance on how the agent should handle file uploads, attachments, and generated file output.
+
+**6. What you know about the user**
+
+Conditional on the memory plugin being loaded and at least one context slot being populated. Contains up to 6 slots fetched by `UserContextFetcher` before the agent is compiled: `identity`, `work`, `goals`, `interests`, `relationships`, `recent`. See [How memory reaches the prompt](/build-an-oracle/reference/bundled-plugins/memory) for the pre-fetch details.
+
+**7. Current time**
+
+Always present. Stamped at agent-compile time with the user's wall-clock time and resolved timezone.
+
+**8. Current entity**
+
+Conditional on `state.currentEntityDid` being set in the agent state. Surfaces the active entity DID so the agent can route entity-aware tool calls correctly.
+
+**9. Available user secrets**
+
+Conditional on the secrets service having entries for the current user. Lists secret names (not values) so the agent can reference them by name in tool calls.
+
+**10. User preferences**
+
+Conditional on the user-preferences plugin being loaded and the user having saved preferences. May include `agentName`, `language`, `tone`, `formality`, and `customInstructions`.
+
+**11. Operational mode**
+
+Always present, but content varies. The runtime selects one of four mode descriptions — `general`, `editor`, `task`, or `entity` — based on which plugins are active and the current session state.
+
+**12. Composio context**
+
+Conditional on the Composio plugin loading successfully. Auto-injected Composio account and connection context so the agent knows which third-party integrations are available for the current user.
+
+**13. Editor section**
+
+Conditional on the editor plugin being active in the current session. Describes the active document, cursor position, and editor affordances.
+
+**14. Slack formatting constraints**
+
+Conditional on the session client being Slack. Appends Slack-specific formatting rules to prevent the agent from using markdown that Slack does not render correctly (e.g. tables).
+
+**15. Degraded services**
+
+Appended after the main prompt when one or more plugins fail their init. Lists the failed services and tells the agent not to attempt their tools for this turn.
+
+## The 5,000-token capability block budget
+
+Section 3 (the Tier-1 capability block) is the only section subject to a token budget. If the combined manifest text of all `visibility='always'` plugins exceeds 5,000 tokens, the runtime trims lower-priority plugins from the block. The trimmed plugins are still loaded and their tools are still callable — they simply don't appear in the capability summary at the top of the prompt. To keep a plugin's description in the block reliably, keep its manifest description concise.
+
+## What you actually need to write in config.ts
+
+Only three things — all optional:
+
+| Field | What to write | What happens if you skip it |
+| --- | --- | --- |
+| `config.prompt.opening` | A paragraph describing the oracle's identity, purpose, and domain expertise. | Runtime generates a generic fallback from `name`, `org`, `description`. |
+| `config.prompt.communicationStyle` | One or two paragraphs on tone, vocabulary, and response style. | The operating-principles section appears without a custom style block. |
+| `config.prompt.capabilities` | A short section (with your own heading) listing what the oracle can do. | The capability-notes section is omitted; only the auto-generated plugin list appears. |
+
+Time, memory, user preferences, Composio context, entity DID, secrets, editor state, Slack constraints, and degraded-service notices are all injected automatically. You do not need to mention them in `config.ts`, instruct the agent to fetch them, or account for them in your opening paragraph.
+
+
+Because memory context is pre-fetched and already in the system prompt by turn 1, you do not need to write instructions like "recall the user's context before responding" in `config.prompt`. The agent already has the user's identity, goals, and recent history before it processes the first message.
+
+
+## Minimal config.ts example
+
+```ts
+// src/config.ts
+import type { OracleConfig } from '@ixo/oracle-runtime';
+
+export const config: OracleConfig = {
+ name: 'Aria',
+ org: 'Acme Climate',
+ description: 'Carbon-project advisory oracle for portfolio managers.',
+ prompt: {
+ opening: `You are Aria, the carbon-project advisory oracle operated by Acme Climate.
+You help portfolio managers track project status, assess compliance, and draft
+stakeholder communications across Verra VCS, Gold Standard, and REDD+ frameworks.`,
+ communicationStyle: `Be precise and data-driven. Lead with numbers and deadlines.
+Use plain English — avoid jargon unless the user demonstrates familiarity.
+When something is uncertain, say so explicitly.`,
+ capabilities: `## What Aria can do
+- Retrieve live project status and registry issuance data.
+- Draft verification reports, CORSIA letters, and board summaries.
+- Search and cite methodology documents from the oracle knowledge base.`,
+ },
+};
+```
+
+Everything else in the 15-section prompt — plugin tools, current time, user memory, preferences, Composio context — is assembled by the runtime from the loaded plugins and session state.
+
+## Related
+
+
+
+ Full reference for config.prompt fields and fallback logic.
+
+
+ How UserContextFetcher pre-loads memory into section 6.
+
+
+ What controls which plugins appear in the capability block.
+
+
+ How plugins declare the manifest text that feeds section 3.
+
+
diff --git a/docs.json b/docs.json
index 7e0df67..49c8dca 100644
--- a/docs.json
+++ b/docs.json
@@ -184,6 +184,7 @@
"build-an-oracle/understand/request-lifecycle",
"build-an-oracle/understand/plugins-vs-skills",
"build-an-oracle/understand/plugin-anatomy",
+ "build-an-oracle/understand/prompt-anatomy",
"build-an-oracle/understand/manifest",
"build-an-oracle/understand/visibility-tiers",
"build-an-oracle/understand/shared-state",
diff --git a/scripts/terminology-lint.mjs b/scripts/terminology-lint.mjs
index b3a6c3c..13a6598 100644
--- a/scripts/terminology-lint.mjs
+++ b/scripts/terminology-lint.mjs
@@ -29,6 +29,10 @@ function aliasScanPattern(alias) {
if (alias === "Matrix Client") {
return new RegExp(`\\b${escaped}\\b(?!\\s+SDK)`, "g");
}
+ // `JAMBO PWA` is deprecated but `JAMBO PWA SDK` (the canonical form) must not be flagged.
+ if (alias === "JAMBO PWA") {
+ return new RegExp(`\\b${escaped}\\b(?!\\s+SDK)`, "g");
+ }
// `Multiclient` (spelling) must stay case-sensitive so canonical `MultiClient` is not flagged.
if (alias === "Multiclient SDK") {
return new RegExp(`(?