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(`(?