# Sessions Sessions manage conversation state, track context usage, and extract long-term memories. Sessions use tiered storage (L0/L1/L2) to optimize token usage: - L0 (abstract): Session overview summary - L1 (overview): Key decisions - L2 (messages): Complete messages Sessions are stored under the current user's namespace: ```text viking://user/{user_id}/sessions/{session_id} ``` Session APIs are scoped to the authenticated user and return canonical user session URIs. URI-based APIs may also accept the backward-compatible `viking://session/{session_id}` alias, resolved in the same user context. ## API Reference ### create_session() #### 1. API Implementation Introduction Create a new session. Sessions are containers for conversations, storing messages, tracking context usage, and supporting commits for long-term memory extraction. **Processing Flow:** 1. Generate or use provided session_id 2. Initialize session metadata (creation time, user info, etc.) 3. Create session directory structure in storage 4. Return session info **Code Entries:** - `openviking/session/session.py:Session.__init__()` - Core Session class - `openviking/session/auto_commit_policy.py:AutoCommitPolicy` - Auto-commit policy defaults and validation - `openviking/server/routers/sessions.py:create_session()` - HTTP route - `openviking_cli/client/base.py:BaseClient.create_session()` - Python SDK - `crates/ov_cli/src/commands/session.rs:new_session()` - CLI command #### 2. Interface and Parameter Description **Parameters** | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | session_id | str | No | None | Session ID. Creates new session with auto-generated ID if None | | memory_policy | object | No | None | Default memory extraction policy for the session. Optional `self` and `peer` switches control write targets, optional `working_memory.enabled=false` skips archive summaries, and optional top-level `memory_types` limits extraction to specific enabled memory schemas. Use JSON booleans for every `enabled` value. Legacy boolean-like values remain accepted temporarily (including string `"false"`, which is parsed as false) but emit a deprecation warning. When `memory_types` is omitted or `null`, all enabled memory schemas are allowed. Invalid shapes or unknown memory types are rejected with `InvalidArgumentError`. | | auto_commit_policy | object | No | None | Optional auto-commit policy (see table below). Any provided fields are validated, clamped to their bounds, and merged over the defaults; the effective policy is returned in the response `result.auto_commit_policy` and persisted into session metadata. If no policy is provided, auto commit is disabled unless `memory.session_auto_commit.default_enabled=true`. The policy is immutable after creation. | `auto_commit_policy` fields (all optional; omitted fields fall back to the defaults when a policy is present): | Field | Type | Default | Max | Description | |-------|------|---------|-----|-------------| | `pending_token_threshold` | int | 10000 | 50000 | When uncommitted pending tokens exceed this value (strictly greater-than), an auto commit is triggered after a message write. | | `message_count_threshold` | int | 50 | 500 | When the uncommitted live message count exceeds this value (strictly greater-than), an auto commit is triggered after a message write. | | `idle_timeout_seconds` | int | 86400 | 604800 | After this many idle seconds, a session with uncommitted content becomes eligible for the server-side idle scheduler. An idle-timeout commit archives the full backlog and ignores `keep_recent_count`. | | `keep_recent_count` | int | 2 | 500 | Number of recent live messages to keep (not archived) on a threshold-triggered auto commit. Idle-timeout commits ignore this and commit everything. | | `min_commit_interval_seconds` | int | 0 | 604800 | Minimum seconds between two automatic commits (throttle). | All fields have a minimum of `0` and are clamped into `[0, max]`. Unknown keys are rejected with `InvalidArgumentError`. #### 3. Usage Examples **HTTP API** ```http POST /api/v1/sessions ``` ```bash # Create new session (auto-generated ID) curl -X POST http://localhost:1933/api/v1/sessions \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" # Create new session with specified ID curl -X POST http://localhost:1933/api/v1/sessions \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{"session_id": "my-custom-session-id"}' # Create new session with a custom auto-commit policy curl -X POST http://localhost:1933/api/v1/sessions \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{ "auto_commit_policy": { "pending_token_threshold": 8000, "message_count_threshold": 40, "idle_timeout_seconds": 600, "keep_recent_count": 10, "min_commit_interval_seconds": 0 } }' ``` **Python SDK** ```python import openviking as ov # Use HTTP client client = ov.Client(base_url="http://localhost:1933", api_key="your-key") # Create new session (auto-generated ID) result = await client.create_session() print(f"Session ID: {result['session_id']}") # Create new session with specified ID result = await client.create_session(session_id="my-custom-session-id") print(f"Session ID: {result['session_id']}") # Create new session with a custom auto-commit policy result = await client.create_session( auto_commit_policy={ "pending_token_threshold": 8000, "message_count_threshold": 40, "idle_timeout_seconds": 600, "keep_recent_count": 10, "min_commit_interval_seconds": 0, } ) print(result["auto_commit_policy"]) ``` **TypeScript SDK** ```typescript const session = await client.createSession(); console.log(session); ``` **Go SDK** ```go session, err := client.CreateSession(ctx, &openviking.CreateSessionOptions{ SessionID: "my-custom-session-id", }) if err != nil { return err } fmt.Println(session["session_id"]) ``` **CLI** ```bash ov session new ``` **Response Example** ```json { "status": "ok", "result": { "session_id": "a1b2c3d4", "uri": "viking://user/alice/sessions/a1b2c3d4", "user": { "account_id": "default", "user_id": "alice" }, "auto_commit_policy": null }, "time": 0.1 } ``` --- ### list_sessions() #### 1. API Implementation Introduction List all sessions for the current user. Returns session IDs and URI info for further operations. **Code Entries:** - `openviking/server/routers/sessions.py:list_sessions()` - HTTP route - `openviking_cli/client/base.py:BaseClient.list_sessions()` - Python SDK - `crates/ov_cli/src/commands/session.rs:list_sessions()` - CLI command #### 2. Interface and Parameter Description **Parameters** None. #### 3. Usage Examples **HTTP API** ```http GET /api/v1/sessions ``` ```bash curl -X GET http://localhost:1933/api/v1/sessions \ -H "X-API-Key: your-key" ``` **Python SDK** ```python import openviking as ov client = ov.Client(base_url="http://localhost:1933", api_key="your-key") sessions = await client.list_sessions() for s in sessions: print(f"{s['session_id']} -> {s['uri']}") ``` **TypeScript SDK** ```typescript console.log(await client.listSessions()); ``` **Go SDK** ```go sessions, err := client.ListSessions(ctx) if err != nil { return err } for _, session := range sessions { fmt.Println(session) } ``` **CLI** ```bash ov session list ``` **Response Example** ```json { "status": "ok", "result": [ { "session_id": "a1b2c3d4", "uri": "viking://user/alice/sessions/a1b2c3d4", "is_dir": true }, { "session_id": "e5f6g7h8", "uri": "viking://user/alice/sessions/e5f6g7h8", "is_dir": true } ], "time": 0.1 } ``` --- ### get_session() #### 1. API Implementation Introduction Get session details including metadata, message statistics, commit history, etc. Supports auto-creating sessions when they don't exist. **Return Fields Description:** - `message_count`: Number of current live, unarchived messages - `total_message_count`: Cumulative count of archived and current live messages (older sessions may omit this field) - `commit_count`: Number of successful commits - `memories_extracted`: Count statistics of extracted memories by category - `last_commit_at`: Time of last commit - `auto_commit_policy`: Effective auto-commit policy with defaults filled in; `null` when not enabled **Code Entries:** - `openviking/session/session.py:Session.load()` - Session loading - `openviking/server/routers/sessions.py:get_session()` - HTTP route - `openviking_cli/client/base.py:BaseClient.get_session()` - Python SDK - `crates/ov_cli/src/commands/session.rs:get_session()` - CLI command #### 2. Interface and Parameter Description **Parameters** | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | session_id | str | Yes | - | Session ID | | auto_create | bool | No | False | Whether to auto-create the session if it does not exist | #### 3. Usage Examples **HTTP API** ```http GET /api/v1/sessions/{session_id}?auto_create=false ``` ```bash curl -X GET http://localhost:1933/api/v1/sessions/a1b2c3d4 \ -H "X-API-Key: your-key" ``` **Python SDK** ```python import openviking as ov client = ov.Client(base_url="http://localhost:1933", api_key="your-key") # Get existing session (raises NotFoundError if not found) info = await client.get_session("a1b2c3d4") print(f"Live Messages: {info['message_count']}") print(f"Total Messages: {info.get('total_message_count', 'n/a')}") print(f"Commits: {info['commit_count']}") # Get or create session info = await client.get_session("a1b2c3d4", auto_create=True) ``` **TypeScript SDK** ```typescript console.log(await client.getSession("session-id")); ``` **Go SDK** ```go // Get an existing session. info, err := client.GetSession(ctx, "a1b2c3d4", nil) if err != nil { return err } fmt.Println(info["message_count"]) // Get or create session. info, err = client.GetSession(ctx, "a1b2c3d4", &openviking.GetSessionOptions{ AutoCreate: true, }) if err != nil { return err } fmt.Println(info["session_id"]) ``` **CLI** ```bash ov session get a1b2c3d4 ``` **Response Example** ```json { "status": "ok", "result": { "session_id": "a1b2c3d4", "created_at": "2026-03-23T10:00:00+08:00", "updated_at": "2026-03-23T11:30:00+08:00", "message_count": 5, "total_message_count": 20, "commit_count": 3, "memories_extracted": { "profile": 1, "preferences": 2, "entities": 3, "events": 1, "identity": 1, "soul": 1, "cases": 2, "trajectories": 1, "experiences": 2, "tools": 0, "skills": 0, "total": 14 }, "last_commit_at": "2026-03-23T11:00:00+08:00", "llm_token_usage": { "prompt_tokens": 5200, "completion_tokens": 1800, "total_tokens": 7000, "cached_tokens": 1200, "reasoning_tokens": 800 }, "user": { "account_id": "default", "user_id": "alice" }, "pending_tokens": 450, "auto_commit_policy": { "pending_token_threshold": 10000, "message_count_threshold": 50, "idle_timeout_seconds": 86400, "keep_recent_count": 2, "min_commit_interval_seconds": 0 } } } ``` --- ### Updating Session Config The auto-commit policy is immutable after creation. Set `auto_commit_policy` when creating the session, then use `GET /api/v1/sessions/{session_id}` to inspect the effective config. Runtime session-config updates are not exposed by the Sessions API. --- ### list_tool_results() List large tool results externalized from a session. | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | `session_id` | string | Yes | - | Session ID | | `tool_name` | string | No | - | Filter by tool name | | `limit` | integer | No | `50` | Maximum results | **HTTP API** ```http GET /api/v1/sessions/{session_id}/tool-results ``` ```bash curl --get http://localhost:1933/api/v1/sessions/session-id/tool-results \ -H "X-API-Key: your-key" \ --data-urlencode "tool_name=search" \ --data-urlencode "limit=50" ``` **Response example** ```json { "status": "ok", "result": { "tool_results": [ { "tool_result_id": "tr_search_a1b2c3", "tool_name": "search", "original_chars": 48210, "preview_chars": 2000, "mime_type": "text/plain", "synopsis_kind": "text", "storage_uri": "viking://user/default/sessions/session-id/tool-results/tr_search_a1b2c3", "offset_unit": "unicode_code_point" } ] } } ``` ### read_tool_result() Read one externalized tool result by Unicode character range. | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | `session_id` | string | Yes | - | Session ID | | `tool_result_id` | string | Yes | - | Tool-result ID | | `offset` | integer | No | `0` | Starting character offset | | `limit` | integer | No | `20000` | Maximum characters; `-1` reads to the end | | `include_metadata` | boolean | No | `true` | Include metadata in the response | **HTTP API** ```http GET /api/v1/sessions/{session_id}/tool-results/{tool_result_id} ``` ```bash curl --get http://localhost:1933/api/v1/sessions/session-id/tool-results/tool-result-id \ -H "X-API-Key: your-key" \ --data-urlencode "offset=0" \ --data-urlencode "limit=20000" ``` **Response example** ```json { "status": "ok", "result": { "tool_result_id": "tr_search_a1b2c3", "content": "A chunk of the tool output...", "offset": 0, "limit": 20000, "offset_unit": "unicode_code_point", "total_chars": 48210, "has_more": true, "metadata": { "tool_name": "search", "mime_type": "text/plain", "sha256": "..." } } } ``` `metadata` is omitted when `include_metadata=false`. To continue reading, set the next request's `offset` to the current `offset` plus the Unicode character count of `content`. ### search_tool_result() Search within one externalized tool result and return context around each match. | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | `q` | string | Yes | - | Search text | | `limit` | integer | No | `20` | Maximum matches | | `context_chars` | integer | No | `300` | Context characters around each match | **HTTP API** ```http GET /api/v1/sessions/{session_id}/tool-results/{tool_result_id}/search?q={query} ``` ```bash curl --get http://localhost:1933/api/v1/sessions/session-id/tool-results/tool-result-id/search \ -H "X-API-Key: your-key" \ --data-urlencode "q=authentication" \ --data-urlencode "limit=20" ``` **Response example** ```json { "status": "ok", "result": { "tool_result_id": "tr_search_a1b2c3", "matches": [ { "offset": 1284, "offset_unit": "unicode_code_point", "snippet": "...authentication failed because..." } ] } } ``` These endpoints are currently used by the Server and Web Studio. The public SDKs and CLI do not wrap them, so the sections above show only the HTTP tab. --- ### get_session_context() #### 1. API Implementation Introduction Get the assembled session context used for LLM context building. This endpoint returns the latest archive overview and current live messages. **Return Fields Description:** - `latest_archive_overview`: The `overview` of the latest completed archive, when it fits the token budget - `pre_archive_abstracts`: Kept for backward compatibility, returns empty array - `messages`: All incomplete archive messages after the latest completed archive, plus current live session messages - `estimatedTokens`: Estimated total tokens - `stats`: Statistics **Token Budget Allocation Strategy:** 1. First allocate to current live messages 2. Remaining budget prioritizes the latest archive overview 3. Pre-archive abstracts are not currently returned **Code Entries:** - `openviking/session/session.py:Session.get_session_context()` - Core implementation - `openviking/server/routers/sessions.py:get_session_context()` - HTTP route - `openviking_cli/client/base.py:BaseClient.get_session_context()` - Python SDK - `crates/ov_cli/src/commands/session.rs:get_session_context()` - CLI command #### 2. Interface and Parameter Description **Parameters** | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | session_id | str | Yes | - | Session ID | | token_budget | int | No | 128000 | Non-negative token budget for assembled archive payload after active `messages` | #### 3. Usage Examples **HTTP API** ```http GET /api/v1/sessions/{session_id}/context?token_budget=128000 ``` ```bash curl -X GET "http://localhost:1933/api/v1/sessions/a1b2c3d4/context?token_budget=128000" \ -H "X-API-Key: your-key" ``` **Python SDK** ```python import openviking as ov client = ov.Client(base_url="http://localhost:1933", api_key="your-key") context = await client.get_session_context("a1b2c3d4", token_budget=128000) print(context["latest_archive_overview"]) print(len(context["messages"])) ``` **TypeScript SDK** ```typescript console.log(await client.getSessionContext("session-id")); ``` **Go SDK** ```go contextPayload, err := client.GetSessionContext(ctx, "a1b2c3d4", 128000) if err != nil { return err } fmt.Println(contextPayload["latest_archive_overview"]) ``` **CLI** ```bash ov session get-session-context a1b2c3d4 --token-budget 128000 ``` **Response Example** ```json { "status": "ok", "result": { "latest_archive_overview": "# Session Summary\n\n**Overview**: User discussed deployment and auth setup.", "pre_archive_abstracts": [], "messages": [ { "id": "msg_pending_1", "role": "user", "parts": [ {"type": "text", "text": "Pending user message"} ], "created_at": "2026-03-24T09:10:11Z" }, { "id": "msg_live_1", "role": "assistant", "parts": [ {"type": "text", "text": "Current live message"} ], "created_at": "2026-03-24T09:10:20Z" } ], "estimatedTokens": 160, "stats": { "totalArchives": 2, "includedArchives": 1, "droppedArchives": 0, "failedArchives": 0, "activeTokens": 98, "archiveTokens": 62 } } } ``` --- ### get_session_archive() #### 1. API Implementation Introduction Get the full contents of one completed archive for a session. This endpoint is typically used with `get_session_context()` when you need to view older archive details. **Code Entries:** - `openviking/session/session.py:Session.get_session_archive()` - Core implementation - `openviking/server/routers/sessions.py:get_session_archive()` - HTTP route - `openviking_cli/client/base.py:BaseClient.get_session_archive()` - Python SDK - `crates/ov_cli/src/commands/session.rs:get_session_archive()` - CLI command #### 2. Interface and Parameter Description **Parameters** | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | session_id | str | Yes | - | Session ID | | archive_id | str | Yes | - | Archive ID such as `archive_002` | #### 3. Usage Examples **HTTP API** ```http GET /api/v1/sessions/{session_id}/archives/{archive_id} ``` ```bash curl -X GET "http://localhost:1933/api/v1/sessions/a1b2c3d4/archives/archive_002" \ -H "X-API-Key: your-key" ``` **Python SDK** ```python import openviking as ov client = ov.Client(base_url="http://localhost:1933", api_key="your-key") archive = await client.get_session_archive("a1b2c3d4", "archive_002") print(archive["archive_id"]) print(archive["overview"]) print(len(archive["messages"])) ``` **TypeScript SDK** ```typescript console.log(await client.getSessionArchive("session-id", "archive-id")); ``` **Go SDK** ```go archive, err := client.GetSessionArchive(ctx, "a1b2c3d4", "archive_002") if err != nil { return err } fmt.Println(archive["archive_id"]) ``` **CLI** ```bash ov session get-session-archive a1b2c3d4 archive_002 ``` **Response Example** ```json { "status": "ok", "result": { "archive_id": "archive_002", "abstract": "User discussed deployment and authentication setup.", "overview": "# Session Summary\n\n**Overview**: User discussed deployment and auth setup.", "messages": [ { "id": "msg_archive_1", "role": "user", "parts": [ {"type": "text", "text": "How should I deploy this service?"} ], "created_at": "2026-03-24T08:55:01Z" }, { "id": "msg_archive_2", "role": "assistant", "parts": [ {"type": "text", "text": "Use the staged deployment flow and verify auth first."} ], "created_at": "2026-03-24T08:55:18Z" } ] } } ``` **Error Response** If the archive does not exist, is incomplete, or does not belong to the session, the API returns 404: ```json { "status": "error", "error": { "code": "NOT_FOUND", "message": "Archive archive_002 not found" } } ``` --- ### delete_session() #### 1. API Implementation Introduction Delete a session and all its data, including messages, archive history, memories, etc. Deletion is irreversible. **Code Entries:** - `openviking/server/routers/sessions.py:delete_session()` - HTTP route - `openviking_cli/client/base.py:BaseClient.delete_session()` - Python SDK - `crates/ov_cli/src/commands/session.rs:delete_session()` - CLI command #### 2. Interface and Parameter Description **Parameters** | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | session_id | str | Yes | - | Session ID to delete | #### 3. Usage Examples **HTTP API** ```http DELETE /api/v1/sessions/{session_id} ``` ```bash curl -X DELETE http://localhost:1933/api/v1/sessions/a1b2c3d4 \ -H "X-API-Key: your-key" ``` **Python SDK** ```python import openviking as ov client = ov.Client(base_url="http://localhost:1933", api_key="your-key") # Delete session await client.delete_session("a1b2c3d4") ``` **TypeScript SDK** ```typescript await client.deleteSession("session-id"); ``` **Go SDK** ```go if err := client.DeleteSession(ctx, "a1b2c3d4"); err != nil { return err } ``` **CLI** ```bash ov session delete a1b2c3d4 ``` **Response Example** ```json { "status": "ok", "result": { "session_id": "a1b2c3d4" }, "time": 0.1 } ``` --- ### add_message() #### 1. API Implementation Introduction Add a message to the session. Supports two modes: simple text mode and Parts mode (supporting text, image URLs, context references, tool calls, etc.). **Part Types:** - `TextPart`: Pure text content - `ImagePart`: OpenAI-style image URL content. During memory extraction, OpenViking can use the configured VLM to turn images into text descriptions. - `ContextPart`: Context reference pointing to resources or memories - `ToolPart`: Tool call and result **Code Entries:** - `openviking/session/session.py:Session.add_message()` - Core implementation - `openviking/server/routers/sessions.py:add_message()` - HTTP route - `openviking_cli/client/base.py:BaseClient.add_message()` - Python SDK - `crates/ov_cli/src/commands/session.rs:add_message()` - CLI command #### 2. Interface and Parameter Description **Parameters** | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | session_id | str | Yes | - | Session ID | | role | str | Yes | - | Message role: "user" or "assistant" | | parts | List[Part] | Conditional | - | List of message parts (Required for Python SDK; Optional for HTTP API, mutually exclusive with content) | | content | str | Conditional | - | Message text content (HTTP API simple mode, mutually exclusive with parts) | | created_at | str | No | None | Optional ISO 8601 timestamp to persist on the message | | peer_id | str | No | None | Optional stable interaction peer identity | > **Note**: HTTP API supports two modes: > 1. **Simple mode**: Use `content` string (backward compatible) > 2. **Parts mode**: Use `parts` array (full Part support) > > If both `content` and `parts` are provided, `parts` takes precedence. **Part Types (Python SDK)** ```python from openviking.message import TextPart, ImagePart, ContextPart, ToolPart # Text content TextPart(text="Hello, how can I help?") # Image URL content ImagePart(url="https://example.com/photo.png", detail="auto") # Context reference ContextPart( uri="viking://resources/docs/auth/", context_type="resource", # "resource", "memory", or "skill" abstract="Authentication guide..." ) # Tool call ToolPart( tool_id="call_123", tool_name="search_web", skill_uri="viking://user/skills/search-web/", tool_input={"query": "OAuth best practices"}, tool_output="", tool_status="pending" # "pending", "running", "completed", "error" ) ``` #### 3. Usage Examples **HTTP API** ```http POST /api/v1/sessions/{session_id}/messages ``` **Simple Mode (Backward Compatible)** ```bash # Add user message curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/messages \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{ "role": "user", "content": "How do I authenticate users?" }' ``` **Parts Mode (Full Part Support)** ```bash # Add assistant message with context reference curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/messages \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{ "role": "assistant", "parts": [ {"type": "text", "text": "Based on the authentication guide..."}, {"type": "context", "uri": "viking://resources/docs/auth/", "context_type": "resource", "abstract": "Auth guide"} ] }' # Add assistant message with tool call curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/messages \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{ "role": "assistant", "parts": [ {"type": "text", "text": "Let me search for that..."}, {"type": "tool", "tool_id": "call_123", "tool_name": "search_web", "tool_input": {"query": "OAuth"}, "tool_status": "completed", "tool_output": "Results..."} ] }' # Add user message with an image URL curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/messages \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{ "role": "user", "parts": [ {"type": "text", "text": "Remember this studio layout."}, {"type": "image_url", "image_url": {"url": "https://example.com/studio.png", "detail": "auto"}} ] }' ``` **Python SDK** ```python import openviking as ov from openviking.message import TextPart, ImagePart, ContextPart client = ov.Client(base_url="http://localhost:1933", api_key="your-key") # Simple mode: Add user message await client.add_message( session_id="a1b2c3d4", role="user", content="How do I authenticate users?" ) # Parts mode: Add assistant message with context reference await client.add_message( session_id="a1b2c3d4", role="assistant", parts=[ TextPart(text="Based on the documentation, you can configure embedding..."), ContextPart( uri="viking://resources/docs/auth/", context_type="resource", abstract="Authentication guide" ) ] ) # Parts mode: Add user message with an image URL await client.add_message( session_id="a1b2c3d4", role="user", parts=[ TextPart(text="Remember this studio layout."), ImagePart(url="https://example.com/studio.png", detail="auto"), ] ) ``` **TypeScript SDK** ```typescript await client.addMessage("session-id", { role: "user", content: "Hello" }); ``` **Go SDK** ```go result, err := client.AddMessage(ctx, "a1b2c3d4", "user", openviking.AddMessageOptions{ Content: openviking.String("How do I authenticate users?"), PeerID: "web-visitor-alice", }) if err != nil { return err } fmt.Println(result["message_count"]) ``` **CLI** ```bash ov session add-message a1b2c3d4 --role user --content "How do I authenticate users?" ``` **Response Example** ```json { "status": "ok", "result": { "session_id": "a1b2c3d4", "message_count": 2 }, "time": 0.1 } ``` --- ### batch_add_messages() #### 1. API Implementation Introduction Add multiple messages to a session in a single request. Suitable for scenarios that require writing a large number of messages at once (e.g., importing conversation history, memory extraction), offering significantly better performance than calling `add_message()` repeatedly. **Difference from `add_message()`**: - `add_message()`: Add 1 message per request - `batch_add_messages()`: Add multiple messages per request (max 100), reducing network round trips and file I/O **Code Entry Points**: - `openviking/session/session.py:Session.add_messages()` - Core implementation - `openviking/server/routers/sessions.py:batch_add_messages()` - HTTP route - `openviking_cli/client/base.py:BaseClient.batch_add_messages()` - Python SDK - `crates/ov_cli/src/commands/session.rs:add_messages()` - CLI command #### 2. Interface and Parameter Description **Parameters** | Parameter | Type | Required | Default | Description | |------|------|------|--------|------| | session_id | str | Yes | - | Session ID | | messages | List[AddMessageRequest] | Yes | - | List of messages, each following the same format as `add_message()`, max 100 | | telemetry | bool | No | False | Whether to attach operation telemetry data | > **Note**: Each message follows the exact same format as `add_message()`, supporting both `content` (simple mode) and `parts` (Parts mode). If you need to add more than 100 messages, call in batches. #### 3. Usage Examples **HTTP API** ```http POST /api/v1/sessions/{session_id}/messages/batch ``` ```bash # Add multiple messages in batch curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/messages/batch \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{ "messages": [ {"role": "user", "content": "How do I authenticate users?"}, {"role": "assistant", "content": "You can use OAuth 2.0 for authentication."}, {"role": "user", "content": "Any specific recommendations?"} ] }' ``` **Python SDK** ```python import openviking as ov client = ov.Client(base_url="http://localhost:1933", api_key="your-key") # Add messages in batch result = await client.batch_add_messages( session_id="a1b2c3d4", messages=[ {"role": "user", "content": "How do I authenticate users?"}, {"role": "assistant", "content": "You can use OAuth 2.0 for authentication."}, {"role": "user", "content": "Any specific recommendations?"}, ], ) print(f"Added: {result['added']}, Total: {result['message_count']}") ``` **TypeScript SDK** ```typescript await client.batchAddMessages("session-id", [ { role: "user", content: "Hello" }, { role: "assistant", content: "Hi" }, ]); ``` **Go SDK** ```go result, err := client.BatchAddMessages(ctx, "a1b2c3d4", []openviking.Message{ {Role: "user", Content: openviking.String("How do I authenticate users?")}, {Role: "assistant", Content: openviking.String("You can use OAuth 2.0 for authentication.")}, {Role: "user", Content: openviking.String("Any specific recommendations?")}, }, nil) if err != nil { return err } fmt.Println(result["added"], result["message_count"]) ``` **CLI** ```bash # Add multiple messages to a session ov session add-messages a1b2c3d4 '[{"role":"user","content":"Hello"},{"role":"assistant","content":"Hi"}]' # ov add-memory also uses the batch interface internally ov add-memory '[{"role":"user","content":"Hello"},{"role":"assistant","content":"Hi"}]' ``` **Response Example** ```json { "status": "ok", "result": { "session_id": "a1b2c3d4", "message_count": 5, "added": 3 }, "time": 0.1 } ``` --- ### used() #### 1. API Implementation Introduction Record actually used contexts and skills in the session. When `commit()` is called, `active_count` is updated based on this usage data to optimize future retrieval ranking. **Code Entries:** - `openviking/session/session.py:Session.used()` - Core implementation - `openviking/server/routers/sessions.py:record_used()` - HTTP route #### 2. Interface and Parameter Description **Parameters** | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | session_id | str | Yes | - | Session ID | | contexts | List[str] | No | None | List of context URIs that were actually used | | skill | Dict[str, Any] | No | None | Skill usage record with keys: `uri`, `input`, `output`, `success` | #### 3. Usage Examples **HTTP API** ```http POST /api/v1/sessions/{session_id}/used ``` ```bash # Record used contexts curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/used \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{"contexts": ["viking://resources/docs/auth/"]}' # Record used skill curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/used \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{"skill": {"uri": "viking://user/skills/search-web/", "input": {"query": "OAuth"}, "output": "Results...", "success": true}}' ``` **Response Example** ```json { "status": "ok", "result": { "session_id": "a1b2c3d4", "contexts_used": 1, "skills_used": 0 }, "time": 0.1 } ``` --- ### commit() #### 1. API Implementation Introduction Commit a session. Message archiving (Phase 1) completes immediately. Summary generation and memory extraction (Phase 2) run asynchronously in the background when messages are archived. Archived commits return `status: "accepted"` with a `task_id`; no-op commits return `status: "skipped"` with `task_id: null`. **Two-Phase Commit Flow:** - **Phase 1 (Synchronous)**: Snapshot current messages, clear live session, create archive directory, write original messages - **Phase 2 (Asynchronous)**: Generate summaries (L0/L1), extract long-term memories, update relations and active_count **Notes:** - Rapid consecutive commits on the same session are accepted; each request gets its own `task_id`. - Empty sessions, or commits where all messages remain inside `keep_recent_count`, complete synchronously with `archived: false`. - Background Phase 2 work is serialized by archive order: archive `N+1` waits until archive `N` writes `.done`. - If an earlier archive failed and left no `.done`, later commit requests fail with `FAILED_PRECONDITION` until that failure is resolved. - If committed messages contain durable facts, judgments, preferences, or events that mention `viking://resources/...`, memory extraction preserves the resource as a markdown link and records it in `MEMORY_FIELDS.resource_refs`. **Code Entries:** - `openviking/session/session.py:Session.commit_async()` - Core implementation - `openviking/server/routers/sessions.py:commit_session()` - HTTP route - `openviking_cli/client/base.py:BaseClient.commit_session()` - Python SDK - `crates/ov_cli/src/commands/session.rs:commit_session()` - CLI command #### 2. Interface and Parameter Description **Parameters** | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | session_id | str | Yes | - | Session ID to commit | | keep_recent_count | int | No | 0 | Number of recent live messages to retain (kept live, not archived) after commit. `0` (default) archives all messages. | #### 3. Usage Examples **HTTP API** ```http POST /api/v1/sessions/{session_id}/commit ``` ```bash # Commit session (returns immediately) curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/commit \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" # Poll task status curl -X GET http://localhost:1933/api/v1/tasks/{task_id} \ -H "X-API-Key: your-key" ``` **Python SDK** ```python import openviking as ov client = ov.Client(base_url="http://localhost:1933", api_key="your-key") # Commit returns immediately with task_id; summary + memory extraction runs in background result = await client.commit_session("a1b2c3d4") print(f"Status: {result['status']}") print(f"Task ID: {result['task_id']}") # Poll background task status task = await client.get_task(result["task_id"]) if task["status"] == "completed": memories = task["result"]["memories_extracted"] total = sum(memories.values()) print(f"Memories extracted: {total}") ``` **TypeScript SDK** ```typescript console.log(await client.commitSession("session-id")); ``` **Go SDK** ```go commit, err := client.CommitSession(ctx, "a1b2c3d4", &openviking.CommitSessionOptions{ KeepRecentCount: 0, }) if err != nil { return err } fmt.Println(commit["status"], commit["task_id"]) taskID, _ := commit["task_id"].(string) task, err := client.GetTask(ctx, taskID) if err != nil { return err } fmt.Println(task["status"]) ``` **CLI** ```bash ov session commit a1b2c3d4 ``` **Response Example** ```json { "status": "ok", "result": { "session_id": "a1b2c3d4", "status": "accepted", "task_id": "uuid-xxx", "archive_uri": "viking://user/alice/sessions/a1b2c3d4/history/archive_001", "archived": true } } ``` **No-op Response Example** ```json { "status": "ok", "result": { "session_id": "a1b2c3d4", "status": "skipped", "task_id": null, "archive_uri": null, "archived": false, "reason": "no_messages" } } ``` --- ### extract() #### 1. API Implementation Introduction Trigger memory extraction immediately for an existing session without creating a new commit task. **Code Entries:** - `openviking/server/routers/sessions.py:extract_session()` - HTTP route #### 2. Interface and Parameter Description **Parameters** | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | session_id | str | Yes | - | Session ID to extract memories from | #### 3. Usage Examples **HTTP API** ```http POST /api/v1/sessions/{session_id}/extract ``` ```bash curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/extract \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" ``` **Response Example** The endpoint returns the extracted memory write results as a JSON list. The exact item shape depends on which memories were produced for that session. ## Session Properties | Property | Type | Description | |----------|------|-------------| | uri | str | Session Viking URI (`viking://user/{user_id}/sessions/{session_id}/`) | | messages | List[Message] | Current messages in the session | | stats | SessionStats | Session statistics | | summary | str | Compression summary | | usage_records | List[Usage] | Context and skill usage records | --- ## Session Storage Structure ``` viking://user/{user_id}/sessions/{session_id}/ +-- .abstract.md # L0: Session overview +-- .overview.md # L1: Key decisions +-- messages.jsonl # Current messages +-- tools/ # Tool executions | +-- {tool_id}/ | +-- tool.json +-- .meta.json # Metadata +-- .relations.json # Related contexts +-- history/ # Archived history +-- archive_001/ | +-- messages.jsonl # Written in Phase 1 | +-- .abstract.md # Written in Phase 2 (background) | +-- .overview.md # Written in Phase 2 (background) | +-- .meta.json # Archive metadata | +-- memory_diff.json # Written when long-term memory extraction completes | +-- .done # Phase 2 completion marker | +-- .failed.json # Phase 2 failure marker +-- archive_002/ ``` ### memory_diff.json Structure When long-term memory extraction runs successfully, the commit writes a `memory_diff.json` to the archive directory, recording all memory changes for auditing and rollback: ```json { "archive_uri": "viking://user/{user_id}/sessions/{session_id}/history/archive_001", "extracted_at": "2026-04-21T10:00:00Z", "operations": { "adds": [ { "uri": "memory/user/xxx/identity.md", "memory_type": "identity", "after": "Newly created file content" } ], "updates": [ { "uri": "memory/user/xxx/context/project.md", "memory_type": "context", "before": "Content before modification", "after": "Content after modification" } ], "deletes": [ { "uri": "memory/user/xxx/context/old.md", "memory_type": "context", "deleted_content": "Deleted file content" } ] }, "summary": { "total_adds": 1, "total_updates": 1, "total_deletes": 1 } } ``` | Field | Type | Description | |-------|------|-------------| | `archive_uri` | str | Archive directory URI for this commit | | `extracted_at` | str | ISO 8601 timestamp of extraction | | `operations.adds` | array | New memories created (`uri`, `memory_type`, `after`) | | `operations.updates` | array | Modified memories (`uri`, `memory_type`, `before`, `after`) | | `operations.deletes` | array | Deleted memories (`uri`, `memory_type`, `deleted_content`) | | `summary.total_adds` | int | Number of new memories | | `summary.total_updates` | int | Number of modified memories | | `summary.total_deletes` | int | Number of deleted memories | An empty `memory_diff.json` (all counts zero) is written when long-term memory extraction runs but produces no memory operations. ## Full Example **Python SDK** ```python import openviking as ov from openviking.message import TextPart, ContextPart # Initialize client client = ov.Client(base_url="http://localhost:1933", api_key="your-key") # Create new session session_result = await client.create_session() session_id = session_result["session_id"] print(f"Session created: {session_id}") # Add user message await client.add_message( session_id=session_id, role="user", content="How do I configure embedding?" ) # Search with session context results = await client.search("embedding configuration", session_id=session_id) # Add assistant message with context reference if results.resources: await client.add_message( session_id=session_id, role="assistant", parts=[ TextPart(text="Based on the documentation, you can configure embedding..."), ContextPart( uri=results.resources[0].uri, context_type="resource", abstract=results.resources[0].abstract ) ] ) # Commit session (returns immediately; summary + memory extraction runs in background) commit_result = await client.commit_session(session_id) print(f"Task ID: {commit_result['task_id']}") # Optional: poll for completion task = await client.get_task(commit_result["task_id"]) if task and task["status"] == "completed": memories = task["result"]["memories_extracted"] total = sum(memories.values()) print(f"Memories extracted: {total}") ``` **HTTP API** ```bash # Step 1: Create session curl -X POST http://localhost:1933/api/v1/sessions \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" # Returns: {"status": "ok", "result": {"session_id": "a1b2c3d4"}} # Step 2: Add user message curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/messages \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{"role": "user", "content": "How do I configure embedding?"}' # Step 3: Search with session context curl -X POST http://localhost:1933/api/v1/search/search \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{"query": "embedding configuration", "session_id": "a1b2c3d4"}' # Step 4: Add assistant message curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/messages \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{"role": "assistant", "content": "Based on the documentation, you can configure embedding..."}' # Step 5: Record used contexts curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/used \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" \ -d '{"contexts": ["viking://resources/docs/embedding/"]}' # Step 6: Commit session (returns immediately with task_id) curl -X POST http://localhost:1933/api/v1/sessions/a1b2c3d4/commit \ -H "Content-Type: application/json" \ -H "X-API-Key: your-key" # Returns: {"status": "ok", "result": {"status": "accepted", "task_id": "uuid-xxx", ...}} # Step 7: Poll background task status (optional) curl -X GET http://localhost:1933/api/v1/tasks/uuid-xxx \ -H "X-API-Key: your-key" ``` ## Best Practices ### Commit Regularly ```python # Commit after significant interactions session_info = await client.get_session(session_id) if session_info["message_count"] > 10: await client.commit_session(session_id) ``` ### Use Session Context for Search ```python # Better search results with conversation context results = await client.search(query, session_id=session_id) ``` --- ## Related Documentation - [Context Types](../concepts/02-context-types.md) - Memory types - [Memory](16-memory.md) - memory types and type-quota recall - [Retrieval](06-retrieval.md) - Search with session - [Resources](02-resources.md) - Resource management - [Background Tasks](17-tasks.md) - track commit tasks