Skip to main content
Standalone Memory Layer

Endpoint Walkthrough

Reference for sessions.start, session.context, session.turn, /process, sessions.end — plus the read endpoints that surface the extracted behavioral data.

The endpoints below cover everything you might need.

  • Pattern 1 minimum: sessions.start → loop of session.context() + session.turn()session.end().
  • Pattern 2 minimum: just /process (auto-creates a session).

sessions.start — open a Session handle

Opens a session and returns a Session object that owns agentId, userId, sessionId, and provider/model defaults.

const session = await client.agents.sessions.start("agent-id", {
userId: "user-123",
sessionId: "session-abc",
userDisplayName: "Alice",
toolDefinitions: yourTools,                    // optional
provider: "gemini",                            // optional default for .turn()
model: "gemini-3.1-flash-lite-preview",        // optional default for .turn()
});

session.context() — enriched 7-layer context

Fetches the 7-layer enriched context: personality, mood, relevant memories, active goals, habits, relationship state, and proactive signals. Pass a query matching the current topic for best memory recall.

const ctx = await session.context({ query: "What should we talk about?" });

// ctx is a flat object — no nested envelope. Useful fields:
//   personality_prompt        — agent identity / system instructions
//   bio, speech_patterns      — agent identity bits
//   true_interests, true_dislikes
//   big5, dimensions, preferences, behaviors
//   recent_personality_shifts, significant_moments, active_goals, habits
//   current_mood, emotional_state
//   loaded_facts              — recalled facts (each has atomic_text, fact_type, importance)
//   long_term_summaries       — multi-session digests
//   proactive_memories        — pending proactive signals
//   constellation_patterns    — deeper behavioral patterns
//   relationship_narrative, chemistry_score, love_from_agent, love_from_user
//   knowledge.results         — KB hits for the query (only nested key)
//   recent_turns              — buffered messages from this session
//   backend_context           — custom application state (if set)

session.turn() — submit a single turn (Pattern 1)

POST /agents/{agentId}/sessions/{sessionId}/turn — sync mood update inline (~300–500ms), deeper extraction continues in the background (5–15 seconds). Accepts role: "tool" and tool_calls on assistant messages.

const { mood, extraction_id, extraction_status } = await session.turn({
messages: [
  { role: "user", content: userMessage },
  // intermediate tool calls/results here
  { role: "assistant", content: assistantMessage },
],
// provider/model fall back to the session-level defaults; both are optional.
});

Response shape:

{
  "success": true,
  "mood": { "valence": 0.4, "arousal": 0.2, "tension": -0.1, "affiliation": 0.3 },
  "extraction_id": "ext_abc123",
  "extraction_status": "queued"
}

Polling background extraction

const status = await session.status(extraction_id);
// { extraction_id: "...", state: "queued" | "running" | "done" | "failed" }

Fetch the next context in the same response

If you can predict the next user query (or just want to pre-warm with a generic query), pass fetchNextContext on .turn() and the server returns an enriched context inside the same response under next_context. This eliminates one roundtrip on the next render.

const { mood, next_context } = await session.turn({
messages: [...],
fetchNextContext: { query: "any query you'd run on the next turn" },
});

// next_context has the same shape as session.context() — use it directly
// to render the system prompt for the next turn without calling /context.

/process — batch ingest a transcript (Pattern 2)

Send a full transcript and run extraction immediately. Auto-creates a session if sessionId is omitted; the response surfaces the auto-generated session_id.

const result = await client.agents.process("agent-id", {
userId: "user-123",
// sessionId omitted — auto-created
messages: [
  { role: "user", content: userMessage },
  { role: "assistant", content: assistantMessage },
  // tool messages allowed too
],
provider: "gemini",                            // optional
model: "gemini-3.1-flash-lite-preview",        // optional
});

console.log(result.session_id);          // auto-generated when not passed
console.log(result.facts_extracted);     // count of facts extracted this call
console.log(result.side_effects);        // { mood_updated: true, ... summary counts }

// Then read the extracted state back via the dedicated endpoints:
const memory = await client.agents.memory.list("agent-id", { userId: "user-123" });
const mood   = await client.agents.getMood("agent-id", { userId: "user-123" });

The response is intentionally a small summary — { success, facts_extracted, side_effects, session_id }. To inspect the extracted facts/personality/mood/habits themselves, call the dedicated read endpoints (see Reading Behavioral Data below).

sessions.end / session.end()

Closes the session. If you call this without messages (after using /turn or /process), it's a finalize-only call. If you call it with messages and skipped /process, this becomes your extraction trigger — functionally equivalent to /process, but lifecycle-scoped and async-capable on tenants where enabled.

// Just close — no extraction needed if you used /turn or /process already.
await session.end({ totalMessages: 12, durationSeconds: 600 });

// OR — pass messages here as the extraction trigger (Option B).
await session.end({
messages: transcript,
totalMessages: transcript.length,
durationSeconds: 600,
});

Tool messages

Both /turn and /process accept OpenAI/Anthropic-style tool messages. Sonzai's extractor reads tool results and can capture facts that only appeared in tool output.

{
  "messages": [
    { "role": "user", "content": "Where did my last order ship from?" },
    {
      "role": "assistant",
      "tool_calls": [
        {
          "id": "call_1",
          "type": "function",
          "function": { "name": "order-lookup", "arguments": "{\"limit\":1}" }
        }
      ]
    },
    {
      "role": "tool",
      "tool_call_id": "call_1",
      "content": "{\"order_id\":\"42\",\"origin\":\"Tokyo\",\"carrier\":\"DHL\"}"
    },
    { "role": "assistant", "content": "Your last order shipped from Tokyo via DHL." }
  ]
}

The extractor will surface a fact like "User's last order (#42) shipped from Tokyo via DHL" — a fact that never appeared in the user's or assistant's own text.

Provider / model overrides

Both /turn and /process (and sessions.start / sessions.end) accept optional provider and model fields. Resolution order:

  1. Per-call override on /turn or /process
  2. Session-level default set on sessions.start
  3. Tenant default configured in your account
  4. Platform defaultgemini-3.1-flash-lite-preview

Omit the fields entirely and the platform default applies.

Reading behavioral data

After processing, all behavioral data is available via dedicated endpoints.

Memory & facts

const memory = await client.agents.memory.list("agent-id", { userId: "user-123" });
const results = await client.agents.memory.search("agent-id", { query: "hiking" });

Personality & mood

const personality = await client.agents.personality.get("agent-id");
const mood = await client.agents.getMood("agent-id", { userId: "user-123" });
const shifts = await client.agents.personality.getRecentShifts("agent-id");
const moments = await client.agents.personality.getSignificantMoments("agent-id");

Goals, habits & relationships

const goals = await client.agents.listGoals("agent-id");
const habits = await client.agents.listHabits("agent-id", { userId: "user-123" });
const interests = await client.agents.getInterests("agent-id");
const relationships = await client.agents.getRelationships("agent-id");

Proactive notifications

The Context Engine schedules proactive outreach (check-ins, follow-ups) based on conversation patterns. Poll for pending notifications and consume them when delivered.

const notifications = await client.agents.notifications.list("agent-id");

for (const notif of notifications) {
await deliverToUser(notif.user_id, notif.message);
await client.agents.notifications.consume("agent-id", notif.message_id);
}

What gets extracted

Memory Facts
Atomic facts (preferences, events, commitments) with importance scoring, deduplication, and topic tagging. Sourced from user, assistant, AND tool messages.
Personality Deltas
Big5 trait shifts (openness, conscientiousness, extraversion, agreeableness, neuroticism) with reasoning.
Mood Changes
4D mood delta (valence, arousal, tension, affiliation). Sync mood lands inline on /turn; richer extraction is deferred.
Habit Detection
New and reinforced behavioral patterns — exercise routines, reading habits, social patterns.
Interest Tracking
Topics the user engages with, categorized by domain with confidence and engagement scores.
Relationship Dynamics
Love score changes with reasoning — tracks rapport, trust, and emotional connection.
Proactive Outreach
Scheduled check-ins and follow-ups based on conversation context (e.g., 'ask about the hike tomorrow').
Emotional Themes
Detected emotional tones — joy, creative spark, feeling overwhelmed, seeking connection, etc.

Choosing an extraction model

When calling /turn or /process, specify which of our LLM providers to use for extraction. Omitting provider/model falls back to the platform default gemini-3.1-flash-lite-preview.

const models = await client.agents.getModels("agent-id");
// {
//   default_provider: "gemini",
//   default_model: "gemini-3.1-flash-lite-preview",
//   providers: [
//     { provider: "gemini", provider_name: "Google Gemini", default_model: "..." },
//     { provider: "zhipu", provider_name: "Zhipu AI", default_model: "..." },
//     ...
//   ]
// }

On this page