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 ofsession.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:
- Per-call override on
/turnor/process - Session-level default set on
sessions.start - Tenant default configured in your account
- Platform default —
gemini-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
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: "..." },
// ...
// ]
// }Pattern 2: Post-Session Batch Processing
You own the entire conversation. Sonzai never sees it in real time. When the conversation ends, send the full transcript to /process or sessions.end({ messages }).
Knowledge Base & Limitations
How the knowledge base behaves in standalone mode, plus what isn't supported vs. managed mode.