Personas & Memory
An agent's personality is defined across two layers: the AGENT.md persona file (the job description) and the optional soul field (the character behind the role). Memory configuration controls how the agent remembers things -- scoped per-user, per-agent, or per-context.
See also: Agent Overview, Configuration, Tools & Delegation.
AGENT.md -- The Persona
The AGENT.md is the agent's job description in prose. It defines who the agent is when operating as this Agent -- capabilities, communication style, priorities, judgment calls. Think of it as the job description you would hand to a new hire on day one.
Only AGENT.md (persona) is required; agent.json (operational wiring) and manifest.json (marketplace identity, required only for apps) are optional. The persona is loaded into the agent's context at startup and shapes every interaction.
What goes in AGENT.md
The file is standard Markdown. Structure it with headings that cover the agent's role, communication style, judgment rules, and boundaries. There is no rigid schema -- write it the way you would write a job brief for a real person.
- Top heading -- the agent's role title
- Opening paragraph -- a concise description of who the agent is and what it does
- Communication Style -- how the agent talks, what tone it uses, formatting preferences
- Judgment -- decision-making rules, priorities, how it handles ambiguity
- What You Don't Do -- explicit boundaries and limitations
Complete AGENT.md example
Here is a full example for an Executive Assistant agent:
# Executive Assistant You are an Executive Assistant. You have been up for two hours before the principal opens their eyes. You already know what their day looks like, what matters most, and what can wait. Your job is to make sure the principal is never blindsided. You surface what's important, suppress what isn't, and interrupt only when something genuinely demands attention. ## Communication Style - Lead with the one thing that matters most today - Be direct. No preamble, no pleasantries in briefings - When you interrupt during the day, say why in one sentence - Evening wraps are reflective, not just recaps ## Judgment - "Important" means: time-sensitive, high-stakes, or likely to be missed - If two things compete for attention, pick the one with a deadline - Never surface something just because it's new -- surface it because it matters - When in doubt, mention it briefly rather than omit it entirely ## What You Don't Do - You don't make decisions for the principal -- you inform them - You don't send messages on their behalf unless explicitly told to - You don't editorialize about their schedule -- you present it clearly
Another example: Legal Analyst
# Legal Analyst You review contracts, flag risks, and summarize obligations. You write for lawyers who don't have time to read -- every output is structured, scannable, and cites the exact clause. ## Communication Style - Use numbered lists for findings - Bold the risk level: **High**, **Medium**, **Low** - Always cite the section number (e.g., "Section 4.2(a)") - Never give legal advice -- you flag, the lawyer decides ## Judgment - Indemnification clauses are always high priority - Termination-for-convenience = flag immediately - Standard boilerplate = skip unless it deviates from market norms - When two readings are possible, present both ## What You Don't Do - You don't draft language -- you analyze existing language - You don't recommend accept/reject -- you present findings - You don't summarize privileged communications
Agent Soul
The soul field is separate from AGENT.md. Where AGENT.md defines capabilities, communication style, and the job description, soul captures voice, personality quirks, tone, ethical boundaries, and values -- the character behind the role.
- Stored in the
agents.soulDB column - Injected into prompt assembly as
agent_soulcontext - Editable in Settings > Soul section
- Not parsed from
agent.json-- set via Settings UI or API
Soul example
# Core Truths - Be genuinely helpful, not performatively helpful - Have opinions and share them when relevant # Vibe - Conversational and warm, not corporate - Direct and honest -- skip filler words # Boundaries - Private things stay private. Period. - When in doubt, ask before acting externally
When to use soul vs AGENT.md
The two layers serve different purposes. Use both together for a complete agent identity.
| AGENT.md | soul | |
|---|---|---|
| Purpose | Job description | Personality |
| Contains | Capabilities, priorities, judgment rules | Voice, tone, quirks, values, ethical lines |
| Analogy | What the agent does | Who the agent is |
| Source | File in the .napp package | DB column, set via Settings UI or API |
| Prompt injection | Loaded as agent persona context | Injected as agent_soul context |
AGENT.md as the resume and soul as the personality test. An Executive Assistant agent's AGENT.md says "surface what's important, suppress what isn't." Its soul says "be warm, be direct, skip corporate filler."Memory Configuration
Memory controls how the agent remembers things across conversations. By default, each agent gets its own isolated memory pool. The memory field in agent.json extends that behavior with two flags.
| Field | Type | Default | Description |
|---|---|---|---|
inherit_user | boolean | false | When true, the agent can read the user's main Nebo preferences (timezone, language, communication style). Read-only -- the agent never writes to the user's memory scope. |
context_isolated | boolean | false | When true, memories are isolated per contextId from SDK embed sessions. Each document/project/record gets its own memory pool. |
Memory configuration example
{
"memory": {
"inherit_user": true,
"context_isolated": true
}
}Three-tier user_id convention
Memory scoping follows a layered naming convention. Each layer is a progressively narrower scope:
| Layer | user_id format | Description |
|---|---|---|
| Layer 1 (User) | "user123" | Nebo companion preferences (timezone, language, style) |
| Layer 2 (Agent) | "user123:agent:brief" | Agent-wide memories |
| Layer 3 (Context) | "user123:agent:brief:ctx:doc-123" | Per-document/project memories |
How the config flags interact
The two flags combine to control which layers the agent reads from and writes to:
| Configuration | Behavior |
|---|---|
Default (both false) | Reads/writes Layer 2 only |
inherit_user: true | Reads Layer 1 (read-only) + reads/writes Layer 2 |
context_isolated: true | Reads/writes Layer 3 instead of Layer 2 |
| Both enabled | Reads all 3 layers, writes Layer 3 |
When to use context_isolated
Use context_isolated when your agent handles multiple independent contexts -- legal clients, project documents, patient records -- where facts from one context must never leak into another. The contextId comes from the SDK embed:
nebo.chat.mount(container, { contextId: document.id });Each context maintains its own memory pool. Agent-wide memories (stored without a contextId) are still visible to all contexts.
Example: Legal document agent
A legal analysis agent embedded in a document management system. Each document gets its own memory so facts from Contract A never leak into Contract B:
{
"memory": {
"context_isolated": true
}
}
// SDK embed -- each document gets its own memory pool
nebo.chat.mount(container, { contextId: "contract-2024-0847" });
nebo.chat.mount(container, { contextId: "contract-2024-0912" });When to use inherit_user
Use inherit_user when your agent needs user preferences without asking for them -- timezone for scheduling, language for communication, name for personalization. The agent reads from the main Nebo companion's tacit/preferences memories (read-only).
Example: Scheduling agent
A briefing agent that needs to know the user's timezone and preferred language without asking:
{
"memory": {
"inherit_user": true
}
}With this configuration, the agent automatically knows the user's timezone, preferred language, and communication style preferences. It reads from Layer 1 (read-only) and reads/writes its own agent-wide memories in Layer 2.
Example: Full memory configuration
An agent embedded in a project management tool that needs user preferences and per-project memory isolation:
{
"workflows": {
"daily-standup": {
"trigger": {
"type": "schedule",
"cron": "0 9 * * 1-5"
},
"description": "Morning standup summary per project"
}
},
"memory": {
"inherit_user": true,
"context_isolated": true
},
"requires": {
"plugins": ["PLUG-PJ3Z-ECFV"]
}
}
// Each project gets its own memory scope
nebo.chat.mount(container, { contextId: project.id });This agent reads user preferences from Layer 1, stores agent-wide memories in Layer 2, and isolates project-specific memories in Layer 3. The user's timezone is used for scheduling the daily standup, and each project's standup content stays separate.
Followup Suggestions
After each chat turn, the agent generates 2-3 contextual follow-up suggestions displayed as clickable chips below the response. This helps users continue the conversation without typing.
How they work
- Followup generation happens asynchronously after the main response completes
- The chips are delivered to the frontend via WebSocket
- Uses the cheapest available provider (avoids Janus credits for background operations)
Format constraints
| Rule | Detail |
|---|---|
| Length | 2-8 words each |
| Tone | Not phrased as questions |
| Avoid | No "Tell me" / "Can you" patterns |
| Count | 2-3 suggestions per response |
Example followups
After a briefing response, the agent might suggest:
// Good followups: "Show open action items" "Reschedule the 2pm meeting" "Draft a reply to Sarah" // Bad followups (violate format rules): "Can you show me the open action items?" // question format "Tell me about today's meetings" // "Tell me" pattern "What should I do next?" // question + too vague
Putting it all together
A complete agent identity spans three pieces: the AGENT.md persona, the soul, and the memory configuration. Here is how they combine for a fully configured agent:
AGENT.md
# Project Manager You keep projects on track. You know every deadline, every blocker, and every dependency. You report status clearly and escalate early. ## Communication Style - Start with the project health: green, yellow, or red - List blockers before progress - Use bullet points, not paragraphs - Tag people by name when assigning actions ## Judgment - A missed deadline is always red, even if the delay is small - Dependencies between teams are higher risk than internal ones - If no update in 48 hours, escalate proactively ## What You Don't Do - You don't write code or review PRs - You don't make scope decisions -- you flag them for the PM lead - You don't schedule meetings -- you recommend them
Soul (set via Settings UI)
# Core Truths - Deadlines matter but people matter more - Transparency builds trust # Vibe - Calm and organized, even when projects are on fire - Encouraging but honest -- no sugarcoating # Boundaries - Never blame individuals in group channels - Keep 1:1 feedback private
agent.json memory section
{
"memory": {
"inherit_user": true,
"context_isolated": true
}
}The AGENT.md tells the agent what to do. The soul tells it how to be. The memory configuration tells it what to remember and where.