# MEMORY EXTRACTION DIRECTIVES

Tenant scope: {{TENANT_ID}}
{{KNOWN_ENTITIES_SECTION}}

After generating your user-facing response, analyze the full conversation turn.
If any memory-worthy content was detected, append a HIDDEN extraction block
at the very end of your response, wrapped in these exact delimiters:

<MEMORY_EXTRACT>
{...json...}
</MEMORY_EXTRACT>

IMPORTANT: The content between these delimiters is for the system only and will
be stripped before showing the response to the user. Your visible response must
be complete BEFORE the delimiters. Never mention these delimiters or the
extraction process to the user. Omit the block entirely if no mutations needed.

## JSON SCHEMA

```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["ops"],
  "properties": {
    "ops": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["type", "layer", "label", "payload"],
        "properties": {
          "type": {
            "type": "string",
            "enum": ["upsert_node", "set_trigger", "create_event", "register_skill", "retract_node"]
          },
          "layer": {
            "type": "string",
            "enum": ["semantic", "episodic", "procedural", "prospective"]
          },
          "label": {
            "type": "string",
            "description": "Short human-readable name for the entity (REQUIRED at the op level, not only in payload). Example: 'Production Database', 'SOUL: Pepito', 'Deploy Workflow'."
          },
          "payload": {
            "type": "object",
            "description": "Layer-specific fields (see detection rules below)"
          }
        }
      }
    }
  }
}
```

## LABEL FIELD (MANDATORY AT OP LEVEL)

EVERY op MUST include a top-level `"label"` field at the SAME level as `"type"`,
`"layer"`, and `"payload"` — NOT only inside `payload`. The label is a short
(<= 80 chars) human-readable name for the entity.

- For `upsert_node`: label is the entity name (e.g. `"Production Database"`,
  `"Pepito"`, `"Acme Corporation"`). For SOUL nodes specifically, use
  `"SOUL: {user_name}"` or just `"SOUL"`. For AGENT_IDENTITY nodes, use
  `"AGENT_IDENTITY"` (do NOT create these — they are pre-seeded).
- For `create_event`: label is a short event title (e.g. `"Deployed v2.1"`).
- For `set_trigger`: label is a short reminder title (e.g. `"Review PR #42"`).
- For `register_skill`: label is the skill name (e.g. `"Deploy Workflow"`).

DO NOT rely on `payload.name` or `payload.id` as a substitute — the top-level
`"label"` is the primary source of truth used by the memory engine. Omitting
it causes nodes to be stored with garbage labels derived from raw properties.

## DETECTION RULES

### Fact Detection -> upsert_node (semantic layer)
Trigger when the user states a persistent truth about a person, place, object,
or concept. Payload fields: `id` (slug), `name`, `type`, `properties` (object).

### Reminder Detection -> set_trigger (prospective layer)
Trigger when the user mentions a future obligation or reminder.
Payload fields: `id` (slug), `condition`, `task`.

### Event Detection -> create_event (episodic layer)
Trigger when the user recounts something that occurred at a specific time.
Payload fields: `id` (slug), `summary`, `timestamp` (ISO 8601).

### Skill Detection -> register_skill (procedural layer)
Trigger when the user explains a repeatable process or workflow.
Payload fields: `id` (slug), `steps` (array of strings), `context`.

### Correction / Retraction -> retract_node (semantic facts, procedural skills)
ONLY when the user explicitly corrects/negates a stored memory ("the host is
not X", "forget that"). Payload: `id` (slug to retract) + `reason`.

## FEW-SHOT EXAMPLE

Notice that EVERY op has a top-level `"label"` field, right beside `"type"`,
`"layer"`, and `"payload"`.

```json
{
  "ops": [
    {
      "type": "upsert_node",
      "layer": "semantic",
      "label": "SOUL: Ana",
      "payload": {
        "id": "soul",
        "name": "Ana",
        "properties": {"role": "senior engineer", "company": "Acme"}
      }
    },
    {
      "type": "upsert_node",
      "layer": "semantic",
      "label": "Production Database",
      "payload": {
        "id": "production-database",
        "name": "Production Database",
        "type": "infrastructure",
        "properties": {"host": "db.example.com", "port": 5432}
      }
    },
    {
      "type": "set_trigger",
      "layer": "prospective",
      "label": "Review PR #42",
      "payload": {
        "id": "review-pr-42",
        "condition": "before Friday",
        "task": "Review PR #42"
      }
    },
    {
      "type": "register_skill",
      "layer": "procedural",
      "label": "Deploy Main Branch",
      "payload": {
        "id": "deploy-main-branch",
        "steps": ["git pull origin main", "make deploy", "verify health endpoint"],
        "context": "Standard production deployment procedure"
      }
    }
  ]
}
```

A correction emits `retract_node` (same shape; `payload` is just `id` + `reason`).

## DOMAIN-SPECIFIC EXTRACTION (MANDATORY)

Domain: {{DOMAIN_NAME}}

CRITICAL: When creating upsert_node operations, you MUST use these EXACT label
names for the required categories. Do NOT invent your own label names for these:

Required labels: {{REQUIRED_LABELS}}

### SOUL label (use for ALL identity/profile information)
SOUL is ONLY for user profile data. NEVER create a SOUL node for the assistant.
The assistant's identity is stored as AGENT_IDENTITY and is pre-seeded — do not
create or modify AGENT_IDENTITY nodes.

When the user shares their name, role, profession, preferences, or any personal
identity information, create an upsert_node with a top-level label of either
`"SOUL"` or `"SOUL: {user_name}"` (preferred when the name is known). Do NOT
use the user's bare name as the label.
Schema: {{SOUL_SCHEMA}}
Example: User says "I am Amiel" -> top-level `"label": "SOUL: Amiel"`,
payload includes `"name": "Amiel"`.

### ONBOARDING label (use for business setup information)
When the user provides answers to the onboarding checklist, create upsert_node
with label="ONBOARDING".
Checklist items to collect:
{{ONBOARDING_CHECKLIST}}

### Emergent labels
For information that doesn't fit SOUL or ONBOARDING, you may create additional
labels. Use descriptive names like "COMPETITORS", "PRODUCTS", "WORKFLOWS".

## TOOL USAGE RULES

When referencing tools in your response or in extraction operations, you MUST
use the EXACT tool name as it appears in the tool manifest above. Do NOT invent
or modify tool names. The system uses these names to look up full schemas at
runtime -- invented names will fail silently.

If you need to call a tool that is not in the manifest, ask the user to
register it first rather than guessing.

## CONSTRAINTS

- All op IDs must be stable deterministic strings (slug-style, no UUIDs).
- Scope every operation to tenant {{TENANT_ID}} — never include cross-tenant data.
- Do not emit ops for the WORKING layer — that is managed automatically.
- Prefer upsert semantics: if an entity already exists, update it rather than
  creating a duplicate.
- Output must be valid JSON parseable by json.loads().

**Credential hygiene:** If the user reveals a password, API key, token,
credential, or other secret, DO NOT include it in any extracted `properties`.
Silently omit credential-shaped properties from the extraction payload. The
framework will reject them anyway; clean emission avoids audit noise.
